mirror of
https://github.com/danog/dart-sass.git
synced 2024-11-27 04:34:59 +01:00
Always track variables' source spans
This is necessary for generating useful error messages for /-as-division.
This commit is contained in:
parent
be2d3e848a
commit
742023a877
@ -25,6 +25,11 @@ import 'utils.dart';
|
|||||||
import 'value.dart';
|
import 'value.dart';
|
||||||
import 'visitor/clone_css.dart';
|
import 'visitor/clone_css.dart';
|
||||||
|
|
||||||
|
// TODO(nweiz): This used to avoid tracking source spans for variables if source
|
||||||
|
// map generation was disabled. We always have to track them now to produce
|
||||||
|
// better warnings for /-as-division, but once those warnings are gone we should
|
||||||
|
// go back to tracking conditionally.
|
||||||
|
|
||||||
/// The lexical environment in which Sass is executed.
|
/// The lexical environment in which Sass is executed.
|
||||||
///
|
///
|
||||||
/// This tracks lexically-scoped information, such as variables, functions, and
|
/// This tracks lexically-scoped information, such as variables, functions, and
|
||||||
@ -77,12 +82,10 @@ class AsyncEnvironment {
|
|||||||
|
|
||||||
/// The nodes where each variable in [_variables] was defined.
|
/// The nodes where each variable in [_variables] was defined.
|
||||||
///
|
///
|
||||||
/// This is `null` if source mapping is disabled.
|
|
||||||
///
|
|
||||||
/// This stores [AstNode]s rather than [FileSpan]s so it can avoid calling
|
/// This stores [AstNode]s rather than [FileSpan]s so it can avoid calling
|
||||||
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
||||||
/// real work to manufacture a source span.
|
/// real work to manufacture a source span.
|
||||||
final List<Map<String, AstNode>>? _variableNodes;
|
final List<Map<String, AstNode>> _variableNodes;
|
||||||
|
|
||||||
/// A map of variable names to their indices in [_variables].
|
/// A map of variable names to their indices in [_variables].
|
||||||
///
|
///
|
||||||
@ -145,7 +148,7 @@ class AsyncEnvironment {
|
|||||||
/// Creates an [AsyncEnvironment].
|
/// Creates an [AsyncEnvironment].
|
||||||
///
|
///
|
||||||
/// If [sourceMap] is `true`, this tracks variables' source locations
|
/// If [sourceMap] is `true`, this tracks variables' source locations
|
||||||
AsyncEnvironment({bool sourceMap = false})
|
AsyncEnvironment()
|
||||||
: _modules = {},
|
: _modules = {},
|
||||||
_namespaceNodes = {},
|
_namespaceNodes = {},
|
||||||
_globalModules = {},
|
_globalModules = {},
|
||||||
@ -155,7 +158,7 @@ class AsyncEnvironment {
|
|||||||
_nestedForwardedModules = null,
|
_nestedForwardedModules = null,
|
||||||
_allModules = [],
|
_allModules = [],
|
||||||
_variables = [{}],
|
_variables = [{}],
|
||||||
_variableNodes = sourceMap ? [{}] : null,
|
_variableNodes = [{}],
|
||||||
_variableIndices = {},
|
_variableIndices = {},
|
||||||
_functions = [{}],
|
_functions = [{}],
|
||||||
_functionIndices = {},
|
_functionIndices = {},
|
||||||
@ -199,7 +202,7 @@ class AsyncEnvironment {
|
|||||||
_nestedForwardedModules,
|
_nestedForwardedModules,
|
||||||
_allModules,
|
_allModules,
|
||||||
_variables.toList(),
|
_variables.toList(),
|
||||||
_variableNodes?.toList(),
|
_variableNodes.toList(),
|
||||||
_functions.toList(),
|
_functions.toList(),
|
||||||
_mixins.toList(),
|
_mixins.toList(),
|
||||||
_content);
|
_content);
|
||||||
@ -218,7 +221,7 @@ class AsyncEnvironment {
|
|||||||
null,
|
null,
|
||||||
[],
|
[],
|
||||||
_variables.toList(),
|
_variables.toList(),
|
||||||
_variableNodes?.toList(),
|
_variableNodes.toList(),
|
||||||
_functions.toList(),
|
_functions.toList(),
|
||||||
_mixins.toList(),
|
_mixins.toList(),
|
||||||
_content);
|
_content);
|
||||||
@ -406,7 +409,7 @@ class AsyncEnvironment {
|
|||||||
for (var variable in forwardedVariableNames) {
|
for (var variable in forwardedVariableNames) {
|
||||||
_variableIndices.remove(variable);
|
_variableIndices.remove(variable);
|
||||||
_variables.last.remove(variable);
|
_variables.last.remove(variable);
|
||||||
_variableNodes?.last.remove(variable);
|
_variableNodes.last.remove(variable);
|
||||||
}
|
}
|
||||||
for (var function in forwardedFunctionNames) {
|
for (var function in forwardedFunctionNames) {
|
||||||
_functionIndices.remove(function);
|
_functionIndices.remove(function);
|
||||||
@ -468,17 +471,10 @@ class AsyncEnvironment {
|
|||||||
/// required, since some nodes need to do real work to manufacture a source
|
/// required, since some nodes need to do real work to manufacture a source
|
||||||
/// span.
|
/// span.
|
||||||
AstNode? getVariableNode(String name, {String? namespace}) {
|
AstNode? getVariableNode(String name, {String? namespace}) {
|
||||||
var variableNodes = _variableNodes;
|
if (namespace != null) return _getModule(namespace).variableNodes[name];
|
||||||
if (variableNodes == null) {
|
|
||||||
throw StateError(
|
|
||||||
"getVariableNodes() should only be called if sourceMap = true was "
|
|
||||||
"passed in.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (namespace != null) return _getModule(namespace).variableNodes![name];
|
|
||||||
|
|
||||||
if (_lastVariableName == name) {
|
if (_lastVariableName == name) {
|
||||||
return variableNodes[_lastVariableIndex!][name] ??
|
return _variableNodes[_lastVariableIndex!][name] ??
|
||||||
_getVariableNodeFromGlobalModule(name);
|
_getVariableNodeFromGlobalModule(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,7 +482,7 @@ class AsyncEnvironment {
|
|||||||
if (index != null) {
|
if (index != null) {
|
||||||
_lastVariableName = name;
|
_lastVariableName = name;
|
||||||
_lastVariableIndex = index;
|
_lastVariableIndex = index;
|
||||||
return variableNodes[index][name] ??
|
return _variableNodes[index][name] ??
|
||||||
_getVariableNodeFromGlobalModule(name);
|
_getVariableNodeFromGlobalModule(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,7 +492,8 @@ class AsyncEnvironment {
|
|||||||
_lastVariableName = name;
|
_lastVariableName = name;
|
||||||
_lastVariableIndex = index;
|
_lastVariableIndex = index;
|
||||||
_variableIndices[name] = index;
|
_variableIndices[name] = index;
|
||||||
return variableNodes[index][name] ?? _getVariableNodeFromGlobalModule(name);
|
return _variableNodes[index][name] ??
|
||||||
|
_getVariableNodeFromGlobalModule(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the node for the variable named [name] from a namespaceless
|
/// Returns the node for the variable named [name] from a namespaceless
|
||||||
@ -511,7 +508,7 @@ class AsyncEnvironment {
|
|||||||
// We don't need to worry about multiple modules defining the same variable,
|
// We don't need to worry about multiple modules defining the same variable,
|
||||||
// because that's already been checked by [getVariable].
|
// because that's already been checked by [getVariable].
|
||||||
for (var module in _globalModules) {
|
for (var module in _globalModules) {
|
||||||
var value = module.variableNodes![name];
|
var value = module.variableNodes[name];
|
||||||
if (value != null) return value;
|
if (value != null) return value;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -559,7 +556,7 @@ class AsyncEnvironment {
|
|||||||
/// defined with the given namespace, if no variable with the given [name] is
|
/// defined with the given namespace, if no variable with the given [name] is
|
||||||
/// defined in module with the given namespace, or if no [namespace] is passed
|
/// defined in module with the given namespace, or if no [namespace] is passed
|
||||||
/// and multiple global modules define variables named [name].
|
/// and multiple global modules define variables named [name].
|
||||||
void setVariable(String name, Value value, AstNode? nodeWithSpan,
|
void setVariable(String name, Value value, AstNode nodeWithSpan,
|
||||||
{String? namespace, bool global = false}) {
|
{String? namespace, bool global = false}) {
|
||||||
if (namespace != null) {
|
if (namespace != null) {
|
||||||
_getModule(namespace).setVariable(name, value, nodeWithSpan);
|
_getModule(namespace).setVariable(name, value, nodeWithSpan);
|
||||||
@ -587,7 +584,7 @@ class AsyncEnvironment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_variables.first[name] = value;
|
_variables.first[name] = value;
|
||||||
if (nodeWithSpan != null) _variableNodes?.first[name] = nodeWithSpan;
|
_variableNodes.first[name] = nodeWithSpan;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -617,7 +614,7 @@ class AsyncEnvironment {
|
|||||||
_lastVariableName = name;
|
_lastVariableName = name;
|
||||||
_lastVariableIndex = index;
|
_lastVariableIndex = index;
|
||||||
_variables[index][name] = value;
|
_variables[index][name] = value;
|
||||||
_variableNodes?[index][name] = nodeWithSpan!;
|
_variableNodes[index][name] = nodeWithSpan;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the variable named [name] to [value], associated with
|
/// Sets the variable named [name] to [value], associated with
|
||||||
@ -629,15 +626,13 @@ class AsyncEnvironment {
|
|||||||
/// This takes an [AstNode] rather than a [FileSpan] so it can avoid calling
|
/// This takes an [AstNode] rather than a [FileSpan] so it can avoid calling
|
||||||
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
||||||
/// real work to manufacture a source span.
|
/// real work to manufacture a source span.
|
||||||
void setLocalVariable(String name, Value value, AstNode? nodeWithSpan) {
|
void setLocalVariable(String name, Value value, AstNode nodeWithSpan) {
|
||||||
var index = _variables.length - 1;
|
var index = _variables.length - 1;
|
||||||
_lastVariableName = name;
|
_lastVariableName = name;
|
||||||
_lastVariableIndex = index;
|
_lastVariableIndex = index;
|
||||||
_variableIndices[name] = index;
|
_variableIndices[name] = index;
|
||||||
_variables[index][name] = value;
|
_variables[index][name] = value;
|
||||||
if (nodeWithSpan != null) {
|
_variableNodes[index][name] = nodeWithSpan;
|
||||||
_variableNodes?[index][name] = nodeWithSpan;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the value of the function named [name], optionally with the given
|
/// Returns the value of the function named [name], optionally with the given
|
||||||
@ -789,7 +784,7 @@ class AsyncEnvironment {
|
|||||||
_inSemiGlobalScope = semiGlobal;
|
_inSemiGlobalScope = semiGlobal;
|
||||||
|
|
||||||
_variables.add({});
|
_variables.add({});
|
||||||
_variableNodes?.add({});
|
_variableNodes.add({});
|
||||||
_functions.add({});
|
_functions.add({});
|
||||||
_mixins.add({});
|
_mixins.add({});
|
||||||
_nestedForwardedModules?.add([]);
|
_nestedForwardedModules?.add([]);
|
||||||
@ -818,12 +813,12 @@ class AsyncEnvironment {
|
|||||||
var configuration = <String, ConfiguredValue>{};
|
var configuration = <String, ConfiguredValue>{};
|
||||||
for (var i = 0; i < _variables.length; i++) {
|
for (var i = 0; i < _variables.length; i++) {
|
||||||
var values = _variables[i];
|
var values = _variables[i];
|
||||||
var nodes = _variableNodes?[i] ?? <String, AstNode>{};
|
var nodes = _variableNodes[i];
|
||||||
for (var entry in values.entries) {
|
for (var entry in values.entries) {
|
||||||
// Implicit configurations are never invalid, making [configurationSpan]
|
// Implicit configurations are never invalid, making [configurationSpan]
|
||||||
// unnecessary, so we pass null here to avoid having to compute it.
|
// unnecessary, so we pass null here to avoid having to compute it.
|
||||||
configuration[entry.key] =
|
configuration[entry.key] =
|
||||||
ConfiguredValue.implicit(entry.value, nodes[entry.key]);
|
ConfiguredValue.implicit(entry.value, nodes[entry.key]!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Configuration.implicit(configuration);
|
return Configuration.implicit(configuration);
|
||||||
@ -921,7 +916,7 @@ class _EnvironmentModule implements Module {
|
|||||||
|
|
||||||
final List<Module> upstream;
|
final List<Module> upstream;
|
||||||
final Map<String, Value> variables;
|
final Map<String, Value> variables;
|
||||||
final Map<String, AstNode>? variableNodes;
|
final Map<String, AstNode> variableNodes;
|
||||||
final Map<String, AsyncCallable> functions;
|
final Map<String, AsyncCallable> functions;
|
||||||
final Map<String, AsyncCallable> mixins;
|
final Map<String, AsyncCallable> mixins;
|
||||||
final ExtensionStore extensionStore;
|
final ExtensionStore extensionStore;
|
||||||
@ -951,10 +946,8 @@ class _EnvironmentModule implements Module {
|
|||||||
_makeModulesByVariable(forwarded),
|
_makeModulesByVariable(forwarded),
|
||||||
_memberMap(environment._variables.first,
|
_memberMap(environment._variables.first,
|
||||||
forwarded.map((module) => module.variables)),
|
forwarded.map((module) => module.variables)),
|
||||||
environment._variableNodes.andThen((nodes) => _memberMap(
|
_memberMap(environment._variableNodes.first,
|
||||||
nodes.first,
|
forwarded.map((module) => module.variableNodes)),
|
||||||
// dart-lang/sdk#45348
|
|
||||||
forwarded!.map((module) => module.variableNodes!))),
|
|
||||||
_memberMap(environment._functions.first,
|
_memberMap(environment._functions.first,
|
||||||
forwarded.map((module) => module.functions)),
|
forwarded.map((module) => module.functions)),
|
||||||
_memberMap(environment._mixins.first,
|
_memberMap(environment._mixins.first,
|
||||||
@ -1017,7 +1010,7 @@ class _EnvironmentModule implements Module {
|
|||||||
required this.transitivelyContainsExtensions})
|
required this.transitivelyContainsExtensions})
|
||||||
: upstream = _environment._allModules;
|
: upstream = _environment._allModules;
|
||||||
|
|
||||||
void setVariable(String name, Value value, AstNode? nodeWithSpan) {
|
void setVariable(String name, Value value, AstNode nodeWithSpan) {
|
||||||
var module = _modulesByVariable[name];
|
var module = _modulesByVariable[name];
|
||||||
if (module != null) {
|
if (module != null) {
|
||||||
module.setVariable(name, value, nodeWithSpan);
|
module.setVariable(name, value, nodeWithSpan);
|
||||||
@ -1029,9 +1022,7 @@ class _EnvironmentModule implements Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_environment._variables.first[name] = value;
|
_environment._variables.first[name] = value;
|
||||||
if (nodeWithSpan != null) {
|
_environment._variableNodes.first[name] = nodeWithSpan;
|
||||||
_environment._variableNodes?.first[name] = nodeWithSpan;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,9 +17,7 @@ class ConfiguredValue {
|
|||||||
final FileSpan? configurationSpan;
|
final FileSpan? configurationSpan;
|
||||||
|
|
||||||
/// The [AstNode] where the variable's value originated.
|
/// The [AstNode] where the variable's value originated.
|
||||||
///
|
final AstNode assignmentNode;
|
||||||
/// This is used to generate source maps.
|
|
||||||
final AstNode? assignmentNode;
|
|
||||||
|
|
||||||
/// Creates a variable value that's been configured explicitly with a `with`
|
/// Creates a variable value that's been configured explicitly with a `with`
|
||||||
/// clause.
|
/// clause.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// DO NOT EDIT. This file was generated from async_environment.dart.
|
// DO NOT EDIT. This file was generated from async_environment.dart.
|
||||||
// See tool/grind/synchronize.dart for details.
|
// See tool/grind/synchronize.dart for details.
|
||||||
//
|
//
|
||||||
// Checksum: bb0b47fc04e32f36a0f87dc73bdfe3f89dc51aa4
|
// Checksum: 588f0864bb1f889586178c799d91696341ecf218
|
||||||
//
|
//
|
||||||
// ignore_for_file: unused_import
|
// ignore_for_file: unused_import
|
||||||
|
|
||||||
@ -32,6 +32,11 @@ import 'utils.dart';
|
|||||||
import 'value.dart';
|
import 'value.dart';
|
||||||
import 'visitor/clone_css.dart';
|
import 'visitor/clone_css.dart';
|
||||||
|
|
||||||
|
// TODO(nweiz): This used to avoid tracking source spans for variables if source
|
||||||
|
// map generation was disabled. We always have to track them now to produce
|
||||||
|
// better warnings for /-as-division, but once those warnings are gone we should
|
||||||
|
// go back to tracking conditionally.
|
||||||
|
|
||||||
/// The lexical environment in which Sass is executed.
|
/// The lexical environment in which Sass is executed.
|
||||||
///
|
///
|
||||||
/// This tracks lexically-scoped information, such as variables, functions, and
|
/// This tracks lexically-scoped information, such as variables, functions, and
|
||||||
@ -84,12 +89,10 @@ class Environment {
|
|||||||
|
|
||||||
/// The nodes where each variable in [_variables] was defined.
|
/// The nodes where each variable in [_variables] was defined.
|
||||||
///
|
///
|
||||||
/// This is `null` if source mapping is disabled.
|
|
||||||
///
|
|
||||||
/// This stores [AstNode]s rather than [FileSpan]s so it can avoid calling
|
/// This stores [AstNode]s rather than [FileSpan]s so it can avoid calling
|
||||||
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
||||||
/// real work to manufacture a source span.
|
/// real work to manufacture a source span.
|
||||||
final List<Map<String, AstNode>>? _variableNodes;
|
final List<Map<String, AstNode>> _variableNodes;
|
||||||
|
|
||||||
/// A map of variable names to their indices in [_variables].
|
/// A map of variable names to their indices in [_variables].
|
||||||
///
|
///
|
||||||
@ -152,7 +155,7 @@ class Environment {
|
|||||||
/// Creates an [Environment].
|
/// Creates an [Environment].
|
||||||
///
|
///
|
||||||
/// If [sourceMap] is `true`, this tracks variables' source locations
|
/// If [sourceMap] is `true`, this tracks variables' source locations
|
||||||
Environment({bool sourceMap = false})
|
Environment()
|
||||||
: _modules = {},
|
: _modules = {},
|
||||||
_namespaceNodes = {},
|
_namespaceNodes = {},
|
||||||
_globalModules = {},
|
_globalModules = {},
|
||||||
@ -162,7 +165,7 @@ class Environment {
|
|||||||
_nestedForwardedModules = null,
|
_nestedForwardedModules = null,
|
||||||
_allModules = [],
|
_allModules = [],
|
||||||
_variables = [{}],
|
_variables = [{}],
|
||||||
_variableNodes = sourceMap ? [{}] : null,
|
_variableNodes = [{}],
|
||||||
_variableIndices = {},
|
_variableIndices = {},
|
||||||
_functions = [{}],
|
_functions = [{}],
|
||||||
_functionIndices = {},
|
_functionIndices = {},
|
||||||
@ -206,7 +209,7 @@ class Environment {
|
|||||||
_nestedForwardedModules,
|
_nestedForwardedModules,
|
||||||
_allModules,
|
_allModules,
|
||||||
_variables.toList(),
|
_variables.toList(),
|
||||||
_variableNodes?.toList(),
|
_variableNodes.toList(),
|
||||||
_functions.toList(),
|
_functions.toList(),
|
||||||
_mixins.toList(),
|
_mixins.toList(),
|
||||||
_content);
|
_content);
|
||||||
@ -225,7 +228,7 @@ class Environment {
|
|||||||
null,
|
null,
|
||||||
[],
|
[],
|
||||||
_variables.toList(),
|
_variables.toList(),
|
||||||
_variableNodes?.toList(),
|
_variableNodes.toList(),
|
||||||
_functions.toList(),
|
_functions.toList(),
|
||||||
_mixins.toList(),
|
_mixins.toList(),
|
||||||
_content);
|
_content);
|
||||||
@ -414,7 +417,7 @@ class Environment {
|
|||||||
for (var variable in forwardedVariableNames) {
|
for (var variable in forwardedVariableNames) {
|
||||||
_variableIndices.remove(variable);
|
_variableIndices.remove(variable);
|
||||||
_variables.last.remove(variable);
|
_variables.last.remove(variable);
|
||||||
_variableNodes?.last.remove(variable);
|
_variableNodes.last.remove(variable);
|
||||||
}
|
}
|
||||||
for (var function in forwardedFunctionNames) {
|
for (var function in forwardedFunctionNames) {
|
||||||
_functionIndices.remove(function);
|
_functionIndices.remove(function);
|
||||||
@ -476,17 +479,10 @@ class Environment {
|
|||||||
/// required, since some nodes need to do real work to manufacture a source
|
/// required, since some nodes need to do real work to manufacture a source
|
||||||
/// span.
|
/// span.
|
||||||
AstNode? getVariableNode(String name, {String? namespace}) {
|
AstNode? getVariableNode(String name, {String? namespace}) {
|
||||||
var variableNodes = _variableNodes;
|
if (namespace != null) return _getModule(namespace).variableNodes[name];
|
||||||
if (variableNodes == null) {
|
|
||||||
throw StateError(
|
|
||||||
"getVariableNodes() should only be called if sourceMap = true was "
|
|
||||||
"passed in.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (namespace != null) return _getModule(namespace).variableNodes![name];
|
|
||||||
|
|
||||||
if (_lastVariableName == name) {
|
if (_lastVariableName == name) {
|
||||||
return variableNodes[_lastVariableIndex!][name] ??
|
return _variableNodes[_lastVariableIndex!][name] ??
|
||||||
_getVariableNodeFromGlobalModule(name);
|
_getVariableNodeFromGlobalModule(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,7 +490,7 @@ class Environment {
|
|||||||
if (index != null) {
|
if (index != null) {
|
||||||
_lastVariableName = name;
|
_lastVariableName = name;
|
||||||
_lastVariableIndex = index;
|
_lastVariableIndex = index;
|
||||||
return variableNodes[index][name] ??
|
return _variableNodes[index][name] ??
|
||||||
_getVariableNodeFromGlobalModule(name);
|
_getVariableNodeFromGlobalModule(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,7 +500,8 @@ class Environment {
|
|||||||
_lastVariableName = name;
|
_lastVariableName = name;
|
||||||
_lastVariableIndex = index;
|
_lastVariableIndex = index;
|
||||||
_variableIndices[name] = index;
|
_variableIndices[name] = index;
|
||||||
return variableNodes[index][name] ?? _getVariableNodeFromGlobalModule(name);
|
return _variableNodes[index][name] ??
|
||||||
|
_getVariableNodeFromGlobalModule(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the node for the variable named [name] from a namespaceless
|
/// Returns the node for the variable named [name] from a namespaceless
|
||||||
@ -519,7 +516,7 @@ class Environment {
|
|||||||
// We don't need to worry about multiple modules defining the same variable,
|
// We don't need to worry about multiple modules defining the same variable,
|
||||||
// because that's already been checked by [getVariable].
|
// because that's already been checked by [getVariable].
|
||||||
for (var module in _globalModules) {
|
for (var module in _globalModules) {
|
||||||
var value = module.variableNodes![name];
|
var value = module.variableNodes[name];
|
||||||
if (value != null) return value;
|
if (value != null) return value;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -567,7 +564,7 @@ class Environment {
|
|||||||
/// defined with the given namespace, if no variable with the given [name] is
|
/// defined with the given namespace, if no variable with the given [name] is
|
||||||
/// defined in module with the given namespace, or if no [namespace] is passed
|
/// defined in module with the given namespace, or if no [namespace] is passed
|
||||||
/// and multiple global modules define variables named [name].
|
/// and multiple global modules define variables named [name].
|
||||||
void setVariable(String name, Value value, AstNode? nodeWithSpan,
|
void setVariable(String name, Value value, AstNode nodeWithSpan,
|
||||||
{String? namespace, bool global = false}) {
|
{String? namespace, bool global = false}) {
|
||||||
if (namespace != null) {
|
if (namespace != null) {
|
||||||
_getModule(namespace).setVariable(name, value, nodeWithSpan);
|
_getModule(namespace).setVariable(name, value, nodeWithSpan);
|
||||||
@ -595,7 +592,7 @@ class Environment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_variables.first[name] = value;
|
_variables.first[name] = value;
|
||||||
if (nodeWithSpan != null) _variableNodes?.first[name] = nodeWithSpan;
|
_variableNodes.first[name] = nodeWithSpan;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,7 +622,7 @@ class Environment {
|
|||||||
_lastVariableName = name;
|
_lastVariableName = name;
|
||||||
_lastVariableIndex = index;
|
_lastVariableIndex = index;
|
||||||
_variables[index][name] = value;
|
_variables[index][name] = value;
|
||||||
_variableNodes?[index][name] = nodeWithSpan!;
|
_variableNodes[index][name] = nodeWithSpan;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the variable named [name] to [value], associated with
|
/// Sets the variable named [name] to [value], associated with
|
||||||
@ -637,15 +634,13 @@ class Environment {
|
|||||||
/// This takes an [AstNode] rather than a [FileSpan] so it can avoid calling
|
/// This takes an [AstNode] rather than a [FileSpan] so it can avoid calling
|
||||||
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
||||||
/// real work to manufacture a source span.
|
/// real work to manufacture a source span.
|
||||||
void setLocalVariable(String name, Value value, AstNode? nodeWithSpan) {
|
void setLocalVariable(String name, Value value, AstNode nodeWithSpan) {
|
||||||
var index = _variables.length - 1;
|
var index = _variables.length - 1;
|
||||||
_lastVariableName = name;
|
_lastVariableName = name;
|
||||||
_lastVariableIndex = index;
|
_lastVariableIndex = index;
|
||||||
_variableIndices[name] = index;
|
_variableIndices[name] = index;
|
||||||
_variables[index][name] = value;
|
_variables[index][name] = value;
|
||||||
if (nodeWithSpan != null) {
|
_variableNodes[index][name] = nodeWithSpan;
|
||||||
_variableNodes?[index][name] = nodeWithSpan;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the value of the function named [name], optionally with the given
|
/// Returns the value of the function named [name], optionally with the given
|
||||||
@ -795,7 +790,7 @@ class Environment {
|
|||||||
_inSemiGlobalScope = semiGlobal;
|
_inSemiGlobalScope = semiGlobal;
|
||||||
|
|
||||||
_variables.add({});
|
_variables.add({});
|
||||||
_variableNodes?.add({});
|
_variableNodes.add({});
|
||||||
_functions.add({});
|
_functions.add({});
|
||||||
_mixins.add({});
|
_mixins.add({});
|
||||||
_nestedForwardedModules?.add([]);
|
_nestedForwardedModules?.add([]);
|
||||||
@ -824,12 +819,12 @@ class Environment {
|
|||||||
var configuration = <String, ConfiguredValue>{};
|
var configuration = <String, ConfiguredValue>{};
|
||||||
for (var i = 0; i < _variables.length; i++) {
|
for (var i = 0; i < _variables.length; i++) {
|
||||||
var values = _variables[i];
|
var values = _variables[i];
|
||||||
var nodes = _variableNodes?[i] ?? <String, AstNode>{};
|
var nodes = _variableNodes[i];
|
||||||
for (var entry in values.entries) {
|
for (var entry in values.entries) {
|
||||||
// Implicit configurations are never invalid, making [configurationSpan]
|
// Implicit configurations are never invalid, making [configurationSpan]
|
||||||
// unnecessary, so we pass null here to avoid having to compute it.
|
// unnecessary, so we pass null here to avoid having to compute it.
|
||||||
configuration[entry.key] =
|
configuration[entry.key] =
|
||||||
ConfiguredValue.implicit(entry.value, nodes[entry.key]);
|
ConfiguredValue.implicit(entry.value, nodes[entry.key]!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Configuration.implicit(configuration);
|
return Configuration.implicit(configuration);
|
||||||
@ -928,7 +923,7 @@ class _EnvironmentModule implements Module<Callable> {
|
|||||||
|
|
||||||
final List<Module<Callable>> upstream;
|
final List<Module<Callable>> upstream;
|
||||||
final Map<String, Value> variables;
|
final Map<String, Value> variables;
|
||||||
final Map<String, AstNode>? variableNodes;
|
final Map<String, AstNode> variableNodes;
|
||||||
final Map<String, Callable> functions;
|
final Map<String, Callable> functions;
|
||||||
final Map<String, Callable> mixins;
|
final Map<String, Callable> mixins;
|
||||||
final ExtensionStore extensionStore;
|
final ExtensionStore extensionStore;
|
||||||
@ -958,10 +953,8 @@ class _EnvironmentModule implements Module<Callable> {
|
|||||||
_makeModulesByVariable(forwarded),
|
_makeModulesByVariable(forwarded),
|
||||||
_memberMap(environment._variables.first,
|
_memberMap(environment._variables.first,
|
||||||
forwarded.map((module) => module.variables)),
|
forwarded.map((module) => module.variables)),
|
||||||
environment._variableNodes.andThen((nodes) => _memberMap(
|
_memberMap(environment._variableNodes.first,
|
||||||
nodes.first,
|
forwarded.map((module) => module.variableNodes)),
|
||||||
// dart-lang/sdk#45348
|
|
||||||
forwarded!.map((module) => module.variableNodes!))),
|
|
||||||
_memberMap(environment._functions.first,
|
_memberMap(environment._functions.first,
|
||||||
forwarded.map((module) => module.functions)),
|
forwarded.map((module) => module.functions)),
|
||||||
_memberMap(environment._mixins.first,
|
_memberMap(environment._mixins.first,
|
||||||
@ -1025,7 +1018,7 @@ class _EnvironmentModule implements Module<Callable> {
|
|||||||
required this.transitivelyContainsExtensions})
|
required this.transitivelyContainsExtensions})
|
||||||
: upstream = _environment._allModules;
|
: upstream = _environment._allModules;
|
||||||
|
|
||||||
void setVariable(String name, Value value, AstNode? nodeWithSpan) {
|
void setVariable(String name, Value value, AstNode nodeWithSpan) {
|
||||||
var module = _modulesByVariable[name];
|
var module = _modulesByVariable[name];
|
||||||
if (module != null) {
|
if (module != null) {
|
||||||
module.setVariable(name, value, nodeWithSpan);
|
module.setVariable(name, value, nodeWithSpan);
|
||||||
@ -1037,9 +1030,7 @@ class _EnvironmentModule implements Module<Callable> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_environment._variables.first[name] = value;
|
_environment._variables.first[name] = value;
|
||||||
if (nodeWithSpan != null) {
|
_environment._variableNodes.first[name] = nodeWithSpan;
|
||||||
_environment._variableNodes?.first[name] = nodeWithSpan;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,15 +26,13 @@ abstract class Module<T extends AsyncCallable> {
|
|||||||
|
|
||||||
/// The nodes where each variable in [_variables] was defined.
|
/// The nodes where each variable in [_variables] was defined.
|
||||||
///
|
///
|
||||||
/// This is `null` if source mapping is disabled.
|
|
||||||
///
|
|
||||||
/// This stores [AstNode]s rather than [FileSpan]s so it can avoid calling
|
/// This stores [AstNode]s rather than [FileSpan]s so it can avoid calling
|
||||||
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
||||||
/// real work to manufacture a source span.
|
/// real work to manufacture a source span.
|
||||||
///
|
///
|
||||||
/// Implementations must ensure that this has the same keys as [variables] if
|
/// Implementations must ensure that this has the same keys as [variables] if
|
||||||
/// it's not `null`.
|
/// it's not `null`.
|
||||||
Map<String, AstNode>? get variableNodes;
|
Map<String, AstNode> get variableNodes;
|
||||||
|
|
||||||
/// The module's functions.
|
/// The module's functions.
|
||||||
///
|
///
|
||||||
@ -71,7 +69,7 @@ abstract class Module<T extends AsyncCallable> {
|
|||||||
///
|
///
|
||||||
/// Throws a [SassScriptException] if this module doesn't define a variable
|
/// Throws a [SassScriptException] if this module doesn't define a variable
|
||||||
/// named [name].
|
/// named [name].
|
||||||
void setVariable(String name, Value value, AstNode? nodeWithSpan);
|
void setVariable(String name, Value value, AstNode nodeWithSpan);
|
||||||
|
|
||||||
/// Returns an opaque object that will be equal to another
|
/// Returns an opaque object that will be equal to another
|
||||||
/// `variableIdentity()` return value for the same name in another module if
|
/// `variableIdentity()` return value for the same name in another module if
|
||||||
|
@ -44,7 +44,7 @@ class BuiltInModule<T extends AsyncCallable> implements Module<T> {
|
|||||||
: UnmodifiableMapView(
|
: UnmodifiableMapView(
|
||||||
{for (var callable in callables) callable.name: callable}));
|
{for (var callable in callables) callable.name: callable}));
|
||||||
|
|
||||||
void setVariable(String name, Value value, AstNode? nodeWithSpan) {
|
void setVariable(String name, Value value, AstNode nodeWithSpan) {
|
||||||
if (!variables.containsKey(name)) {
|
if (!variables.containsKey(name)) {
|
||||||
throw SassScriptException("Undefined variable.");
|
throw SassScriptException("Undefined variable.");
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import '../exception.dart';
|
|||||||
import '../extend/extension_store.dart';
|
import '../extend/extension_store.dart';
|
||||||
import '../module.dart';
|
import '../module.dart';
|
||||||
import '../util/limited_map_view.dart';
|
import '../util/limited_map_view.dart';
|
||||||
import '../util/nullable.dart';
|
|
||||||
import '../util/prefixed_map_view.dart';
|
import '../util/prefixed_map_view.dart';
|
||||||
import '../value.dart';
|
import '../value.dart';
|
||||||
|
|
||||||
@ -31,7 +30,7 @@ class ForwardedModuleView<T extends AsyncCallable> implements Module<T> {
|
|||||||
_inner.transitivelyContainsExtensions;
|
_inner.transitivelyContainsExtensions;
|
||||||
|
|
||||||
final Map<String, Value> variables;
|
final Map<String, Value> variables;
|
||||||
final Map<String, AstNode>? variableNodes;
|
final Map<String, AstNode> variableNodes;
|
||||||
final Map<String, T> functions;
|
final Map<String, T> functions;
|
||||||
final Map<String, T> mixins;
|
final Map<String, T> mixins;
|
||||||
|
|
||||||
@ -53,8 +52,8 @@ class ForwardedModuleView<T extends AsyncCallable> implements Module<T> {
|
|||||||
ForwardedModuleView(this._inner, this._rule)
|
ForwardedModuleView(this._inner, this._rule)
|
||||||
: variables = _forwardedMap(_inner.variables, _rule.prefix,
|
: variables = _forwardedMap(_inner.variables, _rule.prefix,
|
||||||
_rule.shownVariables, _rule.hiddenVariables),
|
_rule.shownVariables, _rule.hiddenVariables),
|
||||||
variableNodes = _inner.variableNodes.andThen((inner) => _forwardedMap(
|
variableNodes = _forwardedMap(_inner.variableNodes, _rule.prefix,
|
||||||
inner, _rule.prefix, _rule.shownVariables, _rule.hiddenVariables)),
|
_rule.shownVariables, _rule.hiddenVariables),
|
||||||
functions = _forwardedMap(_inner.functions, _rule.prefix,
|
functions = _forwardedMap(_inner.functions, _rule.prefix,
|
||||||
_rule.shownMixinsAndFunctions, _rule.hiddenMixinsAndFunctions),
|
_rule.shownMixinsAndFunctions, _rule.hiddenMixinsAndFunctions),
|
||||||
mixins = _forwardedMap(_inner.mixins, _rule.prefix,
|
mixins = _forwardedMap(_inner.mixins, _rule.prefix,
|
||||||
@ -86,7 +85,7 @@ class ForwardedModuleView<T extends AsyncCallable> implements Module<T> {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setVariable(String name, Value value, AstNode? nodeWithSpan) {
|
void setVariable(String name, Value value, AstNode nodeWithSpan) {
|
||||||
var shownVariables = _rule.shownVariables;
|
var shownVariables = _rule.shownVariables;
|
||||||
var hiddenVariables = _rule.hiddenVariables;
|
var hiddenVariables = _rule.hiddenVariables;
|
||||||
if (shownVariables != null && !shownVariables.contains(name)) {
|
if (shownVariables != null && !shownVariables.contains(name)) {
|
||||||
|
@ -9,7 +9,6 @@ import '../exception.dart';
|
|||||||
import '../extend/extension_store.dart';
|
import '../extend/extension_store.dart';
|
||||||
import '../module.dart';
|
import '../module.dart';
|
||||||
import '../util/limited_map_view.dart';
|
import '../util/limited_map_view.dart';
|
||||||
import '../util/nullable.dart';
|
|
||||||
import '../utils.dart';
|
import '../utils.dart';
|
||||||
import '../value.dart';
|
import '../value.dart';
|
||||||
|
|
||||||
@ -28,7 +27,7 @@ class ShadowedModuleView<T extends AsyncCallable> implements Module<T> {
|
|||||||
_inner.transitivelyContainsExtensions;
|
_inner.transitivelyContainsExtensions;
|
||||||
|
|
||||||
final Map<String, Value> variables;
|
final Map<String, Value> variables;
|
||||||
final Map<String, AstNode>? variableNodes;
|
final Map<String, AstNode> variableNodes;
|
||||||
final Map<String, T> functions;
|
final Map<String, T> functions;
|
||||||
final Map<String, T> mixins;
|
final Map<String, T> mixins;
|
||||||
|
|
||||||
@ -57,8 +56,7 @@ class ShadowedModuleView<T extends AsyncCallable> implements Module<T> {
|
|||||||
ShadowedModuleView(this._inner,
|
ShadowedModuleView(this._inner,
|
||||||
{Set<String>? variables, Set<String>? functions, Set<String>? mixins})
|
{Set<String>? variables, Set<String>? functions, Set<String>? mixins})
|
||||||
: variables = _shadowedMap(_inner.variables, variables),
|
: variables = _shadowedMap(_inner.variables, variables),
|
||||||
variableNodes =
|
variableNodes = _shadowedMap(_inner.variableNodes, variables),
|
||||||
_inner.variableNodes.andThen((map) => _shadowedMap(map, variables)),
|
|
||||||
functions = _shadowedMap(_inner.functions, functions),
|
functions = _shadowedMap(_inner.functions, functions),
|
||||||
mixins = _shadowedMap(_inner.mixins, mixins);
|
mixins = _shadowedMap(_inner.mixins, mixins);
|
||||||
|
|
||||||
@ -77,7 +75,7 @@ class ShadowedModuleView<T extends AsyncCallable> implements Module<T> {
|
|||||||
Map<String, Object?> map, Set<String>? blocklist) =>
|
Map<String, Object?> map, Set<String>? blocklist) =>
|
||||||
blocklist != null && map.isNotEmpty && blocklist.any(map.containsKey);
|
blocklist != null && map.isNotEmpty && blocklist.any(map.containsKey);
|
||||||
|
|
||||||
void setVariable(String name, Value value, AstNode? nodeWithSpan) {
|
void setVariable(String name, Value value, AstNode nodeWithSpan) {
|
||||||
if (!variables.containsKey(name)) {
|
if (!variables.containsKey(name)) {
|
||||||
throw SassScriptException("Undefined variable.");
|
throw SassScriptException("Undefined variable.");
|
||||||
} else {
|
} else {
|
||||||
|
@ -298,7 +298,7 @@ class _EvaluateVisitor
|
|||||||
_sourceMap = sourceMap,
|
_sourceMap = sourceMap,
|
||||||
// The default environment is overridden in [_execute] for full
|
// The default environment is overridden in [_execute] for full
|
||||||
// stylesheets, but for [AsyncEvaluator] this environment is used.
|
// stylesheets, but for [AsyncEvaluator] this environment is used.
|
||||||
_environment = AsyncEnvironment(sourceMap: sourceMap) {
|
_environment = AsyncEnvironment() {
|
||||||
var metaFunctions = [
|
var metaFunctions = [
|
||||||
// These functions are defined in the context of the evaluator because
|
// These functions are defined in the context of the evaluator because
|
||||||
// they need access to the [_environment] or other local state.
|
// they need access to the [_environment] or other local state.
|
||||||
@ -677,7 +677,7 @@ class _EvaluateVisitor
|
|||||||
return alreadyLoaded;
|
return alreadyLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
var environment = AsyncEnvironment(sourceMap: _sourceMap);
|
var environment = AsyncEnvironment();
|
||||||
late CssStylesheet css;
|
late CssStylesheet css;
|
||||||
var extensionStore = ExtensionStore();
|
var extensionStore = ExtensionStore();
|
||||||
await _withEnvironment(environment, () async {
|
await _withEnvironment(environment, () async {
|
||||||
@ -2219,7 +2219,7 @@ class _EvaluateVisitor
|
|||||||
_environment.setLocalVariable(
|
_environment.setLocalVariable(
|
||||||
declaredArguments[i].name,
|
declaredArguments[i].name,
|
||||||
evaluated.positional[i].withoutSlash(),
|
evaluated.positional[i].withoutSlash(),
|
||||||
evaluated.positionalNodes?[i]);
|
evaluated.positionalNodes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = evaluated.positional.length;
|
for (var i = evaluated.positional.length;
|
||||||
@ -2231,8 +2231,8 @@ class _EvaluateVisitor
|
|||||||
_environment.setLocalVariable(
|
_environment.setLocalVariable(
|
||||||
argument.name,
|
argument.name,
|
||||||
value.withoutSlash(),
|
value.withoutSlash(),
|
||||||
evaluated.namedNodes?[argument.name] ??
|
evaluated.namedNodes[argument.name] ??
|
||||||
argument.defaultValue.andThen(_expressionNode));
|
_expressionNode(argument.defaultValue!));
|
||||||
}
|
}
|
||||||
|
|
||||||
SassArgumentList? argumentList;
|
SassArgumentList? argumentList;
|
||||||
@ -2325,7 +2325,7 @@ class _EvaluateVisitor
|
|||||||
/// body.
|
/// body.
|
||||||
Future<Value> _runBuiltInCallable(ArgumentInvocation arguments,
|
Future<Value> _runBuiltInCallable(ArgumentInvocation arguments,
|
||||||
AsyncBuiltInCallable callable, AstNode nodeWithSpan) async {
|
AsyncBuiltInCallable callable, AstNode nodeWithSpan) async {
|
||||||
var evaluated = await _evaluateArguments(arguments, trackSpans: false);
|
var evaluated = await _evaluateArguments(arguments);
|
||||||
|
|
||||||
var oldCallableNode = _callableNode;
|
var oldCallableNode = _callableNode;
|
||||||
_callableNode = nodeWithSpan;
|
_callableNode = nodeWithSpan;
|
||||||
@ -2405,12 +2405,13 @@ class _EvaluateVisitor
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the evaluated values of the given [arguments].
|
/// Returns the evaluated values of the given [arguments].
|
||||||
///
|
Future<_ArgumentResults> _evaluateArguments(
|
||||||
/// If [trackSpans] is `true`, this tracks the source spans of the arguments
|
ArgumentInvocation arguments) async {
|
||||||
/// being passed in. It defaults to [_sourceMap].
|
// TODO(nweiz): This used to avoid tracking source spans for arguments if
|
||||||
Future<_ArgumentResults> _evaluateArguments(ArgumentInvocation arguments,
|
// [_sourceMap]s was false or it was being called from
|
||||||
{bool? trackSpans}) async {
|
// [_runBuiltInCallable]. We always have to track them now to produce better
|
||||||
trackSpans ??= _sourceMap;
|
// warnings for /-as-division, but once those warnings are gone we should go
|
||||||
|
// back to tracking conditionally.
|
||||||
|
|
||||||
var positional = [
|
var positional = [
|
||||||
for (var expression in arguments.positional) await expression.accept(this)
|
for (var expression in arguments.positional) await expression.accept(this)
|
||||||
@ -2420,23 +2421,18 @@ class _EvaluateVisitor
|
|||||||
entry.key: await entry.value.accept(this)
|
entry.key: await entry.value.accept(this)
|
||||||
};
|
};
|
||||||
|
|
||||||
var positionalNodes = trackSpans
|
var positionalNodes = [
|
||||||
? [
|
for (var expression in arguments.positional) _expressionNode(expression)
|
||||||
for (var expression in arguments.positional)
|
];
|
||||||
_expressionNode(expression)
|
var namedNodes = {
|
||||||
]
|
|
||||||
: null;
|
|
||||||
var namedNodes = trackSpans
|
|
||||||
? {
|
|
||||||
for (var entry in arguments.named.entries)
|
for (var entry in arguments.named.entries)
|
||||||
entry.key: _expressionNode(entry.value)
|
entry.key: _expressionNode(entry.value)
|
||||||
}
|
};
|
||||||
: null;
|
|
||||||
|
|
||||||
var restArgs = arguments.rest;
|
var restArgs = arguments.rest;
|
||||||
if (restArgs == null) {
|
if (restArgs == null) {
|
||||||
return _ArgumentResults(positional, named, ListSeparator.undecided,
|
return _ArgumentResults(positional, positionalNodes, named, namedNodes,
|
||||||
positionalNodes: positionalNodes, namedNodes: namedNodes);
|
ListSeparator.undecided);
|
||||||
}
|
}
|
||||||
|
|
||||||
var rest = await restArgs.accept(this);
|
var rest = await restArgs.accept(this);
|
||||||
@ -2444,42 +2440,42 @@ class _EvaluateVisitor
|
|||||||
var separator = ListSeparator.undecided;
|
var separator = ListSeparator.undecided;
|
||||||
if (rest is SassMap) {
|
if (rest is SassMap) {
|
||||||
_addRestMap(named, rest, restArgs, (value) => value);
|
_addRestMap(named, rest, restArgs, (value) => value);
|
||||||
namedNodes?.addAll({
|
namedNodes.addAll({
|
||||||
for (var key in rest.contents.keys)
|
for (var key in rest.contents.keys)
|
||||||
(key as SassString).text: restNodeForSpan
|
(key as SassString).text: restNodeForSpan
|
||||||
});
|
});
|
||||||
} else if (rest is SassList) {
|
} else if (rest is SassList) {
|
||||||
positional.addAll(rest.asList);
|
positional.addAll(rest.asList);
|
||||||
positionalNodes?.addAll(List.filled(rest.lengthAsList, restNodeForSpan));
|
positionalNodes.addAll(List.filled(rest.lengthAsList, restNodeForSpan));
|
||||||
separator = rest.separator;
|
separator = rest.separator;
|
||||||
|
|
||||||
if (rest is SassArgumentList) {
|
if (rest is SassArgumentList) {
|
||||||
rest.keywords.forEach((key, value) {
|
rest.keywords.forEach((key, value) {
|
||||||
named[key] = value;
|
named[key] = value;
|
||||||
if (namedNodes != null) namedNodes[key] = restNodeForSpan;
|
namedNodes[key] = restNodeForSpan;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
positional.add(rest);
|
positional.add(rest);
|
||||||
positionalNodes?.add(restNodeForSpan);
|
positionalNodes.add(restNodeForSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
var keywordRestArgs = arguments.keywordRest;
|
var keywordRestArgs = arguments.keywordRest;
|
||||||
if (keywordRestArgs == null) {
|
if (keywordRestArgs == null) {
|
||||||
return _ArgumentResults(positional, named, separator,
|
return _ArgumentResults(
|
||||||
positionalNodes: positionalNodes, namedNodes: namedNodes);
|
positional, positionalNodes, named, namedNodes, separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
var keywordRest = await keywordRestArgs.accept(this);
|
var keywordRest = await keywordRestArgs.accept(this);
|
||||||
var keywordRestNodeForSpan = _expressionNode(keywordRestArgs);
|
var keywordRestNodeForSpan = _expressionNode(keywordRestArgs);
|
||||||
if (keywordRest is SassMap) {
|
if (keywordRest is SassMap) {
|
||||||
_addRestMap(named, keywordRest, keywordRestArgs, (value) => value);
|
_addRestMap(named, keywordRest, keywordRestArgs, (value) => value);
|
||||||
namedNodes?.addAll({
|
namedNodes.addAll({
|
||||||
for (var key in keywordRest.contents.keys)
|
for (var key in keywordRest.contents.keys)
|
||||||
(key as SassString).text: keywordRestNodeForSpan
|
(key as SassString).text: keywordRestNodeForSpan
|
||||||
});
|
});
|
||||||
return _ArgumentResults(positional, named, separator,
|
return _ArgumentResults(
|
||||||
positionalNodes: positionalNodes, namedNodes: namedNodes);
|
positional, positionalNodes, named, namedNodes, separator);
|
||||||
} else {
|
} else {
|
||||||
throw _exception(
|
throw _exception(
|
||||||
"Variable keyword arguments must be a map (was $keywordRest).",
|
"Variable keyword arguments must be a map (was $keywordRest).",
|
||||||
@ -2892,10 +2888,10 @@ class _EvaluateVisitor
|
|||||||
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
||||||
/// real work to manufacture a source span.
|
/// real work to manufacture a source span.
|
||||||
AstNode _expressionNode(Expression expression) {
|
AstNode _expressionNode(Expression expression) {
|
||||||
// If we aren't making a source map this doesn't matter, but we still return
|
// TODO(nweiz): This used to return [expression] as-is if source map
|
||||||
// the expression so we don't have to make the type (and everything
|
// generation was disabled. We always have to track the original location
|
||||||
// downstream of it) nullable.
|
// now to produce better warnings for /-as-division, but once those warnings
|
||||||
if (!_sourceMap) return expression;
|
// are gone we should go back to short-circuiting.
|
||||||
|
|
||||||
if (expression is VariableExpression) {
|
if (expression is VariableExpression) {
|
||||||
return _environment.getVariableNode(expression.name,
|
return _environment.getVariableNode(expression.name,
|
||||||
@ -3205,28 +3201,26 @@ class _ArgumentResults {
|
|||||||
/// Arguments passed by position.
|
/// Arguments passed by position.
|
||||||
final List<Value> positional;
|
final List<Value> positional;
|
||||||
|
|
||||||
/// The [AstNode]s that hold the spans for each [positional] argument, or
|
/// The [AstNode]s that hold the spans for each [positional] argument.
|
||||||
/// `null` if source span tracking is disabled.
|
|
||||||
///
|
///
|
||||||
/// This stores [AstNode]s rather than [FileSpan]s so it can avoid calling
|
/// This stores [AstNode]s rather than [FileSpan]s so it can avoid calling
|
||||||
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
||||||
/// real work to manufacture a source span.
|
/// real work to manufacture a source span.
|
||||||
final List<AstNode>? positionalNodes;
|
final List<AstNode> positionalNodes;
|
||||||
|
|
||||||
/// Arguments passed by name.
|
/// Arguments passed by name.
|
||||||
final Map<String, Value> named;
|
final Map<String, Value> named;
|
||||||
|
|
||||||
/// The [AstNode]s that hold the spans for each [named] argument, or `null` if
|
/// The [AstNode]s that hold the spans for each [named] argument.
|
||||||
/// source span tracking is disabled.
|
|
||||||
///
|
///
|
||||||
/// This stores [AstNode]s rather than [FileSpan]s so it can avoid calling
|
/// This stores [AstNode]s rather than [FileSpan]s so it can avoid calling
|
||||||
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
||||||
/// real work to manufacture a source span.
|
/// real work to manufacture a source span.
|
||||||
final Map<String, AstNode>? namedNodes;
|
final Map<String, AstNode> namedNodes;
|
||||||
|
|
||||||
/// The separator used for the rest argument list, if any.
|
/// The separator used for the rest argument list, if any.
|
||||||
final ListSeparator separator;
|
final ListSeparator separator;
|
||||||
|
|
||||||
_ArgumentResults(this.positional, this.named, this.separator,
|
_ArgumentResults(this.positional, this.positionalNodes, this.named,
|
||||||
{this.positionalNodes, this.namedNodes});
|
this.namedNodes, this.separator);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
// DO NOT EDIT. This file was generated from async_evaluate.dart.
|
// DO NOT EDIT. This file was generated from async_evaluate.dart.
|
||||||
// See tool/grind/synchronize.dart for details.
|
// See tool/grind/synchronize.dart for details.
|
||||||
//
|
//
|
||||||
// Checksum: acaafcfe17e8cb582fb01ea8b95afaf871af4eed
|
// Checksum: 6351ed2d303a58943ce6be39dc794fb46286fd64
|
||||||
//
|
//
|
||||||
// ignore_for_file: unused_import
|
// ignore_for_file: unused_import
|
||||||
|
|
||||||
@ -306,7 +306,7 @@ class _EvaluateVisitor
|
|||||||
_sourceMap = sourceMap,
|
_sourceMap = sourceMap,
|
||||||
// The default environment is overridden in [_execute] for full
|
// The default environment is overridden in [_execute] for full
|
||||||
// stylesheets, but for [AsyncEvaluator] this environment is used.
|
// stylesheets, but for [AsyncEvaluator] this environment is used.
|
||||||
_environment = Environment(sourceMap: sourceMap) {
|
_environment = Environment() {
|
||||||
var metaFunctions = [
|
var metaFunctions = [
|
||||||
// These functions are defined in the context of the evaluator because
|
// These functions are defined in the context of the evaluator because
|
||||||
// they need access to the [_environment] or other local state.
|
// they need access to the [_environment] or other local state.
|
||||||
@ -682,7 +682,7 @@ class _EvaluateVisitor
|
|||||||
return alreadyLoaded;
|
return alreadyLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
var environment = Environment(sourceMap: _sourceMap);
|
var environment = Environment();
|
||||||
late CssStylesheet css;
|
late CssStylesheet css;
|
||||||
var extensionStore = ExtensionStore();
|
var extensionStore = ExtensionStore();
|
||||||
_withEnvironment(environment, () {
|
_withEnvironment(environment, () {
|
||||||
@ -2206,7 +2206,7 @@ class _EvaluateVisitor
|
|||||||
_environment.setLocalVariable(
|
_environment.setLocalVariable(
|
||||||
declaredArguments[i].name,
|
declaredArguments[i].name,
|
||||||
evaluated.positional[i].withoutSlash(),
|
evaluated.positional[i].withoutSlash(),
|
||||||
evaluated.positionalNodes?[i]);
|
evaluated.positionalNodes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = evaluated.positional.length;
|
for (var i = evaluated.positional.length;
|
||||||
@ -2218,8 +2218,8 @@ class _EvaluateVisitor
|
|||||||
_environment.setLocalVariable(
|
_environment.setLocalVariable(
|
||||||
argument.name,
|
argument.name,
|
||||||
value.withoutSlash(),
|
value.withoutSlash(),
|
||||||
evaluated.namedNodes?[argument.name] ??
|
evaluated.namedNodes[argument.name] ??
|
||||||
argument.defaultValue.andThen(_expressionNode));
|
_expressionNode(argument.defaultValue!));
|
||||||
}
|
}
|
||||||
|
|
||||||
SassArgumentList? argumentList;
|
SassArgumentList? argumentList;
|
||||||
@ -2310,7 +2310,7 @@ class _EvaluateVisitor
|
|||||||
/// body.
|
/// body.
|
||||||
Value _runBuiltInCallable(ArgumentInvocation arguments,
|
Value _runBuiltInCallable(ArgumentInvocation arguments,
|
||||||
BuiltInCallable callable, AstNode nodeWithSpan) {
|
BuiltInCallable callable, AstNode nodeWithSpan) {
|
||||||
var evaluated = _evaluateArguments(arguments, trackSpans: false);
|
var evaluated = _evaluateArguments(arguments);
|
||||||
|
|
||||||
var oldCallableNode = _callableNode;
|
var oldCallableNode = _callableNode;
|
||||||
_callableNode = nodeWithSpan;
|
_callableNode = nodeWithSpan;
|
||||||
@ -2390,12 +2390,12 @@ class _EvaluateVisitor
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the evaluated values of the given [arguments].
|
/// Returns the evaluated values of the given [arguments].
|
||||||
///
|
_ArgumentResults _evaluateArguments(ArgumentInvocation arguments) {
|
||||||
/// If [trackSpans] is `true`, this tracks the source spans of the arguments
|
// TODO(nweiz): This used to avoid tracking source spans for arguments if
|
||||||
/// being passed in. It defaults to [_sourceMap].
|
// [_sourceMap]s was false or it was being called from
|
||||||
_ArgumentResults _evaluateArguments(ArgumentInvocation arguments,
|
// [_runBuiltInCallable]. We always have to track them now to produce better
|
||||||
{bool? trackSpans}) {
|
// warnings for /-as-division, but once those warnings are gone we should go
|
||||||
trackSpans ??= _sourceMap;
|
// back to tracking conditionally.
|
||||||
|
|
||||||
var positional = [
|
var positional = [
|
||||||
for (var expression in arguments.positional) expression.accept(this)
|
for (var expression in arguments.positional) expression.accept(this)
|
||||||
@ -2405,23 +2405,18 @@ class _EvaluateVisitor
|
|||||||
entry.key: entry.value.accept(this)
|
entry.key: entry.value.accept(this)
|
||||||
};
|
};
|
||||||
|
|
||||||
var positionalNodes = trackSpans
|
var positionalNodes = [
|
||||||
? [
|
for (var expression in arguments.positional) _expressionNode(expression)
|
||||||
for (var expression in arguments.positional)
|
];
|
||||||
_expressionNode(expression)
|
var namedNodes = {
|
||||||
]
|
|
||||||
: null;
|
|
||||||
var namedNodes = trackSpans
|
|
||||||
? {
|
|
||||||
for (var entry in arguments.named.entries)
|
for (var entry in arguments.named.entries)
|
||||||
entry.key: _expressionNode(entry.value)
|
entry.key: _expressionNode(entry.value)
|
||||||
}
|
};
|
||||||
: null;
|
|
||||||
|
|
||||||
var restArgs = arguments.rest;
|
var restArgs = arguments.rest;
|
||||||
if (restArgs == null) {
|
if (restArgs == null) {
|
||||||
return _ArgumentResults(positional, named, ListSeparator.undecided,
|
return _ArgumentResults(positional, positionalNodes, named, namedNodes,
|
||||||
positionalNodes: positionalNodes, namedNodes: namedNodes);
|
ListSeparator.undecided);
|
||||||
}
|
}
|
||||||
|
|
||||||
var rest = restArgs.accept(this);
|
var rest = restArgs.accept(this);
|
||||||
@ -2429,42 +2424,42 @@ class _EvaluateVisitor
|
|||||||
var separator = ListSeparator.undecided;
|
var separator = ListSeparator.undecided;
|
||||||
if (rest is SassMap) {
|
if (rest is SassMap) {
|
||||||
_addRestMap(named, rest, restArgs, (value) => value);
|
_addRestMap(named, rest, restArgs, (value) => value);
|
||||||
namedNodes?.addAll({
|
namedNodes.addAll({
|
||||||
for (var key in rest.contents.keys)
|
for (var key in rest.contents.keys)
|
||||||
(key as SassString).text: restNodeForSpan
|
(key as SassString).text: restNodeForSpan
|
||||||
});
|
});
|
||||||
} else if (rest is SassList) {
|
} else if (rest is SassList) {
|
||||||
positional.addAll(rest.asList);
|
positional.addAll(rest.asList);
|
||||||
positionalNodes?.addAll(List.filled(rest.lengthAsList, restNodeForSpan));
|
positionalNodes.addAll(List.filled(rest.lengthAsList, restNodeForSpan));
|
||||||
separator = rest.separator;
|
separator = rest.separator;
|
||||||
|
|
||||||
if (rest is SassArgumentList) {
|
if (rest is SassArgumentList) {
|
||||||
rest.keywords.forEach((key, value) {
|
rest.keywords.forEach((key, value) {
|
||||||
named[key] = value;
|
named[key] = value;
|
||||||
if (namedNodes != null) namedNodes[key] = restNodeForSpan;
|
namedNodes[key] = restNodeForSpan;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
positional.add(rest);
|
positional.add(rest);
|
||||||
positionalNodes?.add(restNodeForSpan);
|
positionalNodes.add(restNodeForSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
var keywordRestArgs = arguments.keywordRest;
|
var keywordRestArgs = arguments.keywordRest;
|
||||||
if (keywordRestArgs == null) {
|
if (keywordRestArgs == null) {
|
||||||
return _ArgumentResults(positional, named, separator,
|
return _ArgumentResults(
|
||||||
positionalNodes: positionalNodes, namedNodes: namedNodes);
|
positional, positionalNodes, named, namedNodes, separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
var keywordRest = keywordRestArgs.accept(this);
|
var keywordRest = keywordRestArgs.accept(this);
|
||||||
var keywordRestNodeForSpan = _expressionNode(keywordRestArgs);
|
var keywordRestNodeForSpan = _expressionNode(keywordRestArgs);
|
||||||
if (keywordRest is SassMap) {
|
if (keywordRest is SassMap) {
|
||||||
_addRestMap(named, keywordRest, keywordRestArgs, (value) => value);
|
_addRestMap(named, keywordRest, keywordRestArgs, (value) => value);
|
||||||
namedNodes?.addAll({
|
namedNodes.addAll({
|
||||||
for (var key in keywordRest.contents.keys)
|
for (var key in keywordRest.contents.keys)
|
||||||
(key as SassString).text: keywordRestNodeForSpan
|
(key as SassString).text: keywordRestNodeForSpan
|
||||||
});
|
});
|
||||||
return _ArgumentResults(positional, named, separator,
|
return _ArgumentResults(
|
||||||
positionalNodes: positionalNodes, namedNodes: namedNodes);
|
positional, positionalNodes, named, namedNodes, separator);
|
||||||
} else {
|
} else {
|
||||||
throw _exception(
|
throw _exception(
|
||||||
"Variable keyword arguments must be a map (was $keywordRest).",
|
"Variable keyword arguments must be a map (was $keywordRest).",
|
||||||
@ -2870,10 +2865,10 @@ class _EvaluateVisitor
|
|||||||
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
||||||
/// real work to manufacture a source span.
|
/// real work to manufacture a source span.
|
||||||
AstNode _expressionNode(Expression expression) {
|
AstNode _expressionNode(Expression expression) {
|
||||||
// If we aren't making a source map this doesn't matter, but we still return
|
// TODO(nweiz): This used to return [expression] as-is if source map
|
||||||
// the expression so we don't have to make the type (and everything
|
// generation was disabled. We always have to track the original location
|
||||||
// downstream of it) nullable.
|
// now to produce better warnings for /-as-division, but once those warnings
|
||||||
if (!_sourceMap) return expression;
|
// are gone we should go back to short-circuiting.
|
||||||
|
|
||||||
if (expression is VariableExpression) {
|
if (expression is VariableExpression) {
|
||||||
return _environment.getVariableNode(expression.name,
|
return _environment.getVariableNode(expression.name,
|
||||||
@ -3146,28 +3141,26 @@ class _ArgumentResults {
|
|||||||
/// Arguments passed by position.
|
/// Arguments passed by position.
|
||||||
final List<Value> positional;
|
final List<Value> positional;
|
||||||
|
|
||||||
/// The [AstNode]s that hold the spans for each [positional] argument, or
|
/// The [AstNode]s that hold the spans for each [positional] argument.
|
||||||
/// `null` if source span tracking is disabled.
|
|
||||||
///
|
///
|
||||||
/// This stores [AstNode]s rather than [FileSpan]s so it can avoid calling
|
/// This stores [AstNode]s rather than [FileSpan]s so it can avoid calling
|
||||||
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
||||||
/// real work to manufacture a source span.
|
/// real work to manufacture a source span.
|
||||||
final List<AstNode>? positionalNodes;
|
final List<AstNode> positionalNodes;
|
||||||
|
|
||||||
/// Arguments passed by name.
|
/// Arguments passed by name.
|
||||||
final Map<String, Value> named;
|
final Map<String, Value> named;
|
||||||
|
|
||||||
/// The [AstNode]s that hold the spans for each [named] argument, or `null` if
|
/// The [AstNode]s that hold the spans for each [named] argument.
|
||||||
/// source span tracking is disabled.
|
|
||||||
///
|
///
|
||||||
/// This stores [AstNode]s rather than [FileSpan]s so it can avoid calling
|
/// This stores [AstNode]s rather than [FileSpan]s so it can avoid calling
|
||||||
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
/// [AstNode.span] if the span isn't required, since some nodes need to do
|
||||||
/// real work to manufacture a source span.
|
/// real work to manufacture a source span.
|
||||||
final Map<String, AstNode>? namedNodes;
|
final Map<String, AstNode> namedNodes;
|
||||||
|
|
||||||
/// The separator used for the rest argument list, if any.
|
/// The separator used for the rest argument list, if any.
|
||||||
final ListSeparator separator;
|
final ListSeparator separator;
|
||||||
|
|
||||||
_ArgumentResults(this.positional, this.named, this.separator,
|
_ArgumentResults(this.positional, this.positionalNodes, this.named,
|
||||||
{this.positionalNodes, this.namedNodes});
|
this.namedNodes, this.separator);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user