diff --git a/lib/src/ast/sass.dart b/lib/src/ast/sass.dart index 149641670..f4deef43b 100644 --- a/lib/src/ast/sass.dart +++ b/lib/src/ast/sass.dart @@ -2,9 +2,7 @@ // MIT-style license that can be found in the LICENSE file or at // https://opensource.org/licenses/MIT. -export 'sass/argument.dart'; -export 'sass/argument_declaration.dart'; -export 'sass/argument_invocation.dart'; +export 'sass/argument_list.dart'; export 'sass/at_root_query.dart'; export 'sass/callable_invocation.dart'; export 'sass/configured_variable.dart'; @@ -33,6 +31,8 @@ export 'sass/import/dynamic.dart'; export 'sass/import/static.dart'; export 'sass/interpolation.dart'; export 'sass/node.dart'; +export 'sass/parameter.dart'; +export 'sass/parameter_list.dart'; export 'sass/reference.dart'; export 'sass/statement.dart'; export 'sass/statement/at_root_rule.dart'; diff --git a/lib/src/ast/sass/argument_invocation.dart b/lib/src/ast/sass/argument_list.dart similarity index 95% rename from lib/src/ast/sass/argument_invocation.dart rename to lib/src/ast/sass/argument_list.dart index 92e7645cf..84a53b67e 100644 --- a/lib/src/ast/sass/argument_invocation.dart +++ b/lib/src/ast/sass/argument_list.dart @@ -13,7 +13,7 @@ import 'node.dart'; /// A set of arguments passed in to a function or mixin. /// /// {@category AST} -final class ArgumentInvocation implements SassNode { +final class ArgumentList implements SassNode { /// The arguments passed by position. final List positional; @@ -31,7 +31,7 @@ final class ArgumentInvocation implements SassNode { /// Returns whether this invocation passes no arguments. bool get isEmpty => positional.isEmpty && named.isEmpty && rest == null; - ArgumentInvocation( + ArgumentList( Iterable positional, Map named, this.span, {this.rest, this.keywordRest}) : positional = List.unmodifiable(positional), @@ -40,7 +40,7 @@ final class ArgumentInvocation implements SassNode { } /// Creates an invocation that passes no arguments. - ArgumentInvocation.empty(this.span) + ArgumentList.empty(this.span) : positional = const [], named = const {}, rest = null, diff --git a/lib/src/ast/sass/callable_invocation.dart b/lib/src/ast/sass/callable_invocation.dart index ed0a5ddb7..93aa40b2d 100644 --- a/lib/src/ast/sass/callable_invocation.dart +++ b/lib/src/ast/sass/callable_invocation.dart @@ -4,7 +4,7 @@ import 'package:meta/meta.dart'; -import 'argument_invocation.dart'; +import 'argument_list.dart'; import 'node.dart'; /// An abstract class for invoking a callable (a function or mixin). @@ -13,5 +13,5 @@ import 'node.dart'; @sealed abstract class CallableInvocation implements SassNode { /// The arguments passed to the callable. - ArgumentInvocation get arguments; + ArgumentList get arguments; } diff --git a/lib/src/ast/sass/expression/function.dart b/lib/src/ast/sass/expression/function.dart index 0f2fce7eb..78b7c734a 100644 --- a/lib/src/ast/sass/expression/function.dart +++ b/lib/src/ast/sass/expression/function.dart @@ -7,7 +7,7 @@ import 'package:source_span/source_span.dart'; import '../../../util/span.dart'; import '../../../visitor/interface/expression.dart'; import '../expression.dart'; -import '../argument_invocation.dart'; +import '../argument_list.dart'; import '../callable_invocation.dart'; import '../reference.dart'; @@ -33,7 +33,7 @@ final class FunctionExpression extends Expression final String originalName; /// The arguments to pass to the function. - final ArgumentInvocation arguments; + final ArgumentList arguments; final FileSpan span; diff --git a/lib/src/ast/sass/expression/if.dart b/lib/src/ast/sass/expression/if.dart index 95e305e47..1cec007e0 100644 --- a/lib/src/ast/sass/expression/if.dart +++ b/lib/src/ast/sass/expression/if.dart @@ -16,11 +16,11 @@ import '../../../visitor/interface/expression.dart'; /// {@category AST} final class IfExpression extends Expression implements CallableInvocation { /// The declaration of `if()`, as though it were a normal function. - static final declaration = ArgumentDeclaration.parse( - r"@function if($condition, $if-true, $if-false) {"); + static final declaration = + ParameterList.parse(r"@function if($condition, $if-true, $if-false) {"); /// The arguments passed to `if()`. - final ArgumentInvocation arguments; + final ArgumentList arguments; final FileSpan span; diff --git a/lib/src/ast/sass/expression/interpolated_function.dart b/lib/src/ast/sass/expression/interpolated_function.dart index cd5e2abf2..8e72c71ee 100644 --- a/lib/src/ast/sass/expression/interpolated_function.dart +++ b/lib/src/ast/sass/expression/interpolated_function.dart @@ -6,7 +6,7 @@ import 'package:source_span/source_span.dart'; import '../../../visitor/interface/expression.dart'; import '../expression.dart'; -import '../argument_invocation.dart'; +import '../argument_list.dart'; import '../callable_invocation.dart'; import '../interpolation.dart'; @@ -21,7 +21,7 @@ final class InterpolatedFunctionExpression extends Expression final Interpolation name; /// The arguments to pass to the function. - final ArgumentInvocation arguments; + final ArgumentList arguments; final FileSpan span; diff --git a/lib/src/ast/sass/argument.dart b/lib/src/ast/sass/parameter.dart similarity index 77% rename from lib/src/ast/sass/argument.dart rename to lib/src/ast/sass/parameter.dart index afd9e337c..0ddcdb748 100644 --- a/lib/src/ast/sass/argument.dart +++ b/lib/src/ast/sass/parameter.dart @@ -10,14 +10,14 @@ import 'expression.dart'; import 'declaration.dart'; import 'node.dart'; -/// An argument declared as part of an [ArgumentDeclaration]. +/// An parameter declared as part of an [ParameterList]. /// /// {@category AST} -final class Argument implements SassNode, SassDeclaration { - /// The argument name. +final class Parameter implements SassNode, SassDeclaration { + /// The parameter name. final String name; - /// The default value of this argument, or `null` if none was declared. + /// The default value of this parameter, or `null` if none was declared. final Expression? defaultValue; final FileSpan span; @@ -33,7 +33,7 @@ final class Argument implements SassNode, SassDeclaration { FileSpan get nameSpan => defaultValue == null ? span : span.initialIdentifier(includeLeading: 1); - Argument(this.name, this.span, {this.defaultValue}); + Parameter(this.name, this.span, {this.defaultValue}); String toString() => defaultValue == null ? name : "$name: $defaultValue"; } diff --git a/lib/src/ast/sass/argument_declaration.dart b/lib/src/ast/sass/parameter_list.dart similarity index 54% rename from lib/src/ast/sass/argument_declaration.dart rename to lib/src/ast/sass/parameter_list.dart index ed1951cad..ea5e3fae7 100644 --- a/lib/src/ast/sass/argument_declaration.dart +++ b/lib/src/ast/sass/parameter_list.dart @@ -9,20 +9,20 @@ import '../../parse/scss.dart'; import '../../util/character.dart'; import '../../util/span.dart'; import '../../utils.dart'; -import 'argument.dart'; +import 'parameter.dart'; import 'node.dart'; -/// An argument declaration, as for a function or mixin definition. +/// An parameter declaration, as for a function or mixin definition. /// /// {@category AST} /// {@category Parsing} -final class ArgumentDeclaration implements SassNode { - /// The arguments that are taken. - final List arguments; +final class ParameterList implements SassNode { + /// The parameters that are taken. + final List parameters; - /// The name of the rest argument (as in `$args...`), or `null` if none was + /// The name of the rest parameter (as in `$args...`), or `null` if none was /// declared. - final String? restArgument; + final String? restParameter; final FileSpan span; @@ -31,7 +31,7 @@ final class ArgumentDeclaration implements SassNode { FileSpan get spanWithName { var text = span.file.getText(0); - // Move backwards through any whitespace between the name and the arguments. + // Move backwards through any whitespace between the name and the parameters. var i = span.start.offset - 1; while (i > 0 && text.codeUnitAt(i).isWhitespace) { i--; @@ -48,60 +48,59 @@ final class ArgumentDeclaration implements SassNode { if (!text.codeUnitAt(i + 1).isNameStart) return span; // Trim because it's possible that this span is empty (for example, a mixin - // may be declared without an argument list). + // may be declared without an parameter list). return span.file.span(i + 1, span.end.offset).trim(); } - /// Returns whether this declaration takes no arguments. - bool get isEmpty => arguments.isEmpty && restArgument == null; + /// Returns whether this declaration takes no parameters. + bool get isEmpty => parameters.isEmpty && restParameter == null; - ArgumentDeclaration(Iterable arguments, this.span, - {this.restArgument}) - : arguments = List.unmodifiable(arguments); + ParameterList(Iterable parameters, this.span, {this.restParameter}) + : parameters = List.unmodifiable(parameters); - /// Creates a declaration that declares no arguments. - ArgumentDeclaration.empty(this.span) - : arguments = const [], - restArgument = null; + /// Creates a declaration that declares no parameters. + ParameterList.empty(this.span) + : parameters = const [], + restParameter = null; - /// Parses an argument declaration from [contents], which should be of the + /// Parses an parameter declaration from [contents], which should be of the /// form `@rule name(args) {`. /// /// If passed, [url] is the name of the file from which [contents] comes. /// /// Throws a [SassFormatException] if parsing fails. - factory ArgumentDeclaration.parse(String contents, {Object? url}) => - ScssParser(contents, url: url).parseArgumentDeclaration(); + factory ParameterList.parse(String contents, {Object? url}) => + ScssParser(contents, url: url).parseParameterList(); /// Throws a [SassScriptException] if [positional] and [names] aren't valid - /// for this argument declaration. + /// for this parameter declaration. void verify(int positional, Set names) { var namedUsed = 0; - for (var i = 0; i < arguments.length; i++) { - var argument = arguments[i]; + for (var i = 0; i < parameters.length; i++) { + var parameter = parameters[i]; if (i < positional) { - if (names.contains(argument.name)) { + if (names.contains(parameter.name)) { throw SassScriptException( - "Argument ${_originalArgumentName(argument.name)} was passed " + "Argument ${_originalParameterName(parameter.name)} was passed " "both by position and by name."); } - } else if (names.contains(argument.name)) { + } else if (names.contains(parameter.name)) { namedUsed++; - } else if (argument.defaultValue == null) { + } else if (parameter.defaultValue == null) { throw MultiSpanSassScriptException( - "Missing argument ${_originalArgumentName(argument.name)}.", + "Missing argument ${_originalParameterName(parameter.name)}.", "invocation", {spanWithName: "declaration"}); } } - if (restArgument != null) return; + if (restParameter != null) return; - if (positional > arguments.length) { + if (positional > parameters.length) { throw MultiSpanSassScriptException( - "Only ${arguments.length} " + "Only ${parameters.length} " "${names.isEmpty ? '' : 'positional '}" - "${pluralize('argument', arguments.length)} allowed, but " + "${pluralize('argument', parameters.length)} allowed, but " "$positional ${pluralize('was', positional, plural: 'were')} " "passed.", "invocation", @@ -110,54 +109,54 @@ final class ArgumentDeclaration implements SassNode { if (namedUsed < names.length) { var unknownNames = Set.of(names) - ..removeAll(arguments.map((argument) => argument.name)); + ..removeAll(parameters.map((parameter) => parameter.name)); throw MultiSpanSassScriptException( - "No ${pluralize('argument', unknownNames.length)} named " + "No ${pluralize('parameter', unknownNames.length)} named " "${toSentence(unknownNames.map((name) => "\$$name"), 'or')}.", "invocation", {spanWithName: "declaration"}); } } - /// Returns the argument named [name] with a leading `$` and its original + /// Returns the parameter named [name] with a leading `$` and its original /// underscores (which are otherwise converted to hyphens). - String _originalArgumentName(String name) { - if (name == restArgument) { + String _originalParameterName(String name) { + if (name == restParameter) { var text = span.text; var fromDollar = text.substring(text.lastIndexOf("\$")); return fromDollar.substring(0, text.indexOf(".")); } - for (var argument in arguments) { - if (argument.name == name) return argument.originalName; + for (var parameter in parameters) { + if (parameter.name == name) return parameter.originalName; } - throw ArgumentError('This declaration has no argument named "\$$name".'); + throw ArgumentError('This declaration has no parameter named "\$$name".'); } - /// Returns whether [positional] and [names] are valid for this argument + /// Returns whether [positional] and [names] are valid for this parameter /// declaration. bool matches(int positional, Set names) { var namedUsed = 0; - for (var i = 0; i < arguments.length; i++) { - var argument = arguments[i]; + for (var i = 0; i < parameters.length; i++) { + var parameter = parameters[i]; if (i < positional) { - if (names.contains(argument.name)) return false; - } else if (names.contains(argument.name)) { + if (names.contains(parameter.name)) return false; + } else if (names.contains(parameter.name)) { namedUsed++; - } else if (argument.defaultValue == null) { + } else if (parameter.defaultValue == null) { return false; } } - if (restArgument != null) return true; - if (positional > arguments.length) return false; + if (restParameter != null) return true; + if (positional > parameters.length) return false; if (namedUsed < names.length) return false; return true; } String toString() => [ - for (var arg in arguments) '\$$arg', - if (restArgument != null) '\$$restArgument...' + for (var arg in parameters) '\$$arg', + if (restParameter != null) '\$$restParameter...' ].join(', '); } diff --git a/lib/src/ast/sass/statement/callable_declaration.dart b/lib/src/ast/sass/statement/callable_declaration.dart index 3ce0ec9a0..1c2154065 100644 --- a/lib/src/ast/sass/statement/callable_declaration.dart +++ b/lib/src/ast/sass/statement/callable_declaration.dart @@ -4,7 +4,7 @@ import 'package:source_span/source_span.dart'; -import '../argument_declaration.dart'; +import '../parameter_list.dart'; import '../statement.dart'; import 'parent.dart'; import 'silent_comment.dart'; @@ -24,12 +24,12 @@ abstract base class CallableDeclaration /// The comment immediately preceding this declaration. final SilentComment? comment; - /// The declared arguments this callable accepts. - final ArgumentDeclaration arguments; + /// The declared parameters this callable accepts. + final ParameterList parameters; final FileSpan span; - CallableDeclaration(this.originalName, this.arguments, + CallableDeclaration(this.originalName, this.parameters, Iterable children, this.span, {this.comment}) : name = originalName.replaceAll('_', '-'), diff --git a/lib/src/ast/sass/statement/content_block.dart b/lib/src/ast/sass/statement/content_block.dart index 618a49ea5..d29a8290b 100644 --- a/lib/src/ast/sass/statement/content_block.dart +++ b/lib/src/ast/sass/statement/content_block.dart @@ -6,20 +6,20 @@ import 'package:source_span/source_span.dart'; import '../../../visitor/interface/statement.dart'; import '../statement.dart'; -import '../argument_declaration.dart'; +import '../parameter_list.dart'; import 'callable_declaration.dart'; /// An anonymous block of code that's invoked for a [ContentRule]. /// /// {@category AST} final class ContentBlock extends CallableDeclaration { - ContentBlock(ArgumentDeclaration arguments, Iterable children, - FileSpan span) - : super("@content", arguments, children, span); + ContentBlock( + ParameterList parameters, Iterable children, FileSpan span) + : super("@content", parameters, children, span); T accept(StatementVisitor visitor) => visitor.visitContentBlock(this); String toString() => - (arguments.isEmpty ? "" : " using ($arguments)") + + (parameters.isEmpty ? "" : " using ($parameters)") + " {${children.join(' ')}}"; } diff --git a/lib/src/ast/sass/statement/content_rule.dart b/lib/src/ast/sass/statement/content_rule.dart index 8d451207b..ba835de5a 100644 --- a/lib/src/ast/sass/statement/content_rule.dart +++ b/lib/src/ast/sass/statement/content_rule.dart @@ -5,7 +5,7 @@ import 'package:source_span/source_span.dart'; import '../../../visitor/interface/statement.dart'; -import '../argument_invocation.dart'; +import '../argument_list.dart'; import '../statement.dart'; /// A `@content` rule. @@ -18,7 +18,7 @@ final class ContentRule extends Statement { /// The arguments pass to this `@content` rule. /// /// This will be an empty invocation if `@content` has no arguments. - final ArgumentInvocation arguments; + final ArgumentList arguments; final FileSpan span; diff --git a/lib/src/ast/sass/statement/function_rule.dart b/lib/src/ast/sass/statement/function_rule.dart index 885bd4ef9..15741908f 100644 --- a/lib/src/ast/sass/statement/function_rule.dart +++ b/lib/src/ast/sass/statement/function_rule.dart @@ -18,10 +18,10 @@ final class FunctionRule extends CallableDeclaration implements SassDeclaration { FileSpan get nameSpan => span.withoutInitialAtRule().initialIdentifier(); - FunctionRule(super.name, super.arguments, super.children, super.span, + FunctionRule(super.name, super.parameters, super.children, super.span, {super.comment}); T accept(StatementVisitor visitor) => visitor.visitFunctionRule(this); - String toString() => "@function $name($arguments) {${children.join(' ')}}"; + String toString() => "@function $name($parameters) {${children.join(' ')}}"; } diff --git a/lib/src/ast/sass/statement/include_rule.dart b/lib/src/ast/sass/statement/include_rule.dart index 98151665e..5331a728e 100644 --- a/lib/src/ast/sass/statement/include_rule.dart +++ b/lib/src/ast/sass/statement/include_rule.dart @@ -6,7 +6,7 @@ import 'package:source_span/source_span.dart'; import '../../../util/span.dart'; import '../../../visitor/interface/statement.dart'; -import '../argument_invocation.dart'; +import '../argument_list.dart'; import '../callable_invocation.dart'; import '../reference.dart'; import '../statement.dart'; @@ -30,7 +30,7 @@ final class IncludeRule extends Statement final String originalName; /// The arguments to pass to the mixin. - final ArgumentInvocation arguments; + final ArgumentList arguments; /// The block that will be invoked for [ContentRule]s in the mixin being /// invoked, or `null` if this doesn't pass a content block. diff --git a/lib/src/ast/sass/statement/mixin_rule.dart b/lib/src/ast/sass/statement/mixin_rule.dart index 650e64b65..a4b5e4d2d 100644 --- a/lib/src/ast/sass/statement/mixin_rule.dart +++ b/lib/src/ast/sass/statement/mixin_rule.dart @@ -28,14 +28,14 @@ final class MixinRule extends CallableDeclaration implements SassDeclaration { return startSpan.initialIdentifier(); } - MixinRule(super.name, super.arguments, super.children, super.span, + MixinRule(super.name, super.parameters, super.children, super.span, {super.comment}); T accept(StatementVisitor visitor) => visitor.visitMixinRule(this); String toString() { var buffer = StringBuffer("@mixin $name"); - if (!arguments.isEmpty) buffer.write("($arguments)"); + if (!parameters.isEmpty) buffer.write("($parameters)"); buffer.write(" {${children.join(' ')}}"); return buffer.toString(); } diff --git a/lib/src/callable/async_built_in.dart b/lib/src/callable/async_built_in.dart index 4e479c148..3736f47a9 100644 --- a/lib/src/callable/async_built_in.dart +++ b/lib/src/callable/async_built_in.dart @@ -17,13 +17,13 @@ typedef Callback = FutureOr Function(List arguments); /// /// Unlike user-defined callables, built-in callables support overloads. They /// may declare multiple different callbacks with multiple different sets of -/// arguments. When the callable is invoked, the first callback with matching -/// arguments is invoked. +/// parameters. When the callable is invoked, the first callback with matching +/// parameters is invoked. class AsyncBuiltInCallable implements AsyncCallable { final String name; - /// This callable's arguments. - final ArgumentDeclaration _arguments; + /// This callable's parameters. + final ParameterList _parameters; /// The callback to run when executing this callable. final Callback _callback; @@ -33,35 +33,34 @@ class AsyncBuiltInCallable implements AsyncCallable { /// This can only be true for mixins. final bool acceptsContent; - /// Creates a function with a single [arguments] declaration and a single + /// Creates a function with a single [parameters] declaration and a single /// [callback]. /// - /// The argument declaration is parsed from [arguments], which should not + /// The parameter declaration is parsed from [parameters], which should not /// include parentheses. Throws a [SassFormatException] if parsing fails. /// /// If passed, [url] is the URL of the module in which the function is /// defined. - AsyncBuiltInCallable.function(String name, String arguments, - FutureOr callback(List arguments), {Object? url}) + AsyncBuiltInCallable.function(String name, String parameters, + FutureOr callback(List parameters), {Object? url}) : this.parsed( name, - ArgumentDeclaration.parse('@function $name($arguments) {', - url: url), + ParameterList.parse('@function $name($parameters) {', url: url), callback); - /// Creates a mixin with a single [arguments] declaration and a single + /// Creates a mixin with a single [parameters] declaration and a single /// [callback]. /// - /// The argument declaration is parsed from [arguments], which should not + /// The parameter declaration is parsed from [parameters], which should not /// include parentheses. Throws a [SassFormatException] if parsing fails. /// /// If passed, [url] is the URL of the module in which the mixin is /// defined. - AsyncBuiltInCallable.mixin(String name, String arguments, - FutureOr callback(List arguments), + AsyncBuiltInCallable.mixin(String name, String parameters, + FutureOr callback(List parameters), {Object? url, bool acceptsContent = false}) - : this.parsed(name, - ArgumentDeclaration.parse('@mixin $name($arguments) {', url: url), + : this.parsed( + name, ParameterList.parse('@mixin $name($parameters) {', url: url), (arguments) async { await callback(arguments); // We could encode the fact that functions return values and mixins @@ -71,25 +70,24 @@ class AsyncBuiltInCallable implements AsyncCallable { return sassNull; }); - /// Creates a callable with a single [arguments] declaration and a single + /// Creates a callable with a single [parameters] declaration and a single /// [callback]. - AsyncBuiltInCallable.parsed(this.name, this._arguments, this._callback, + AsyncBuiltInCallable.parsed(this.name, this._parameters, this._callback, {this.acceptsContent = false}); - /// Returns the argument declaration and Dart callback for the given - /// positional and named arguments. + /// Returns the parameter declaration and Dart callback for the given + /// positional and named parameters. /// /// If no exact match is found, finds the closest approximation. Note that this /// doesn't guarantee that [positional] and [names] are valid for the returned - /// [ArgumentDeclaration]. - (ArgumentDeclaration, Callback) callbackFor( - int positional, Set names) => - (_arguments, _callback); + /// [ParameterList]. + (ParameterList, Callback) callbackFor(int positional, Set names) => + (_parameters, _callback); /// Returns a copy of this callable that emits a deprecation warning. AsyncBuiltInCallable withDeprecationWarning(String module, [String? newName]) => - AsyncBuiltInCallable.parsed(name, _arguments, (args) { + AsyncBuiltInCallable.parsed(name, _parameters, (args) { warnForGlobalBuiltIn(module, newName ?? name); return _callback(args); }, acceptsContent: acceptsContent); diff --git a/lib/src/callable/built_in.dart b/lib/src/callable/built_in.dart index 5f646b2da..e78e05014 100644 --- a/lib/src/callable/built_in.dart +++ b/lib/src/callable/built_in.dart @@ -13,63 +13,62 @@ typedef Callback = Value Function(List arguments); /// /// Unlike user-defined callables, built-in callables support overloads. They /// may declare multiple different callbacks with multiple different sets of -/// arguments. When the callable is invoked, the first callback with matching -/// arguments is invoked. +/// parameters. When the callable is invoked, the first callback with matching +/// parameters is invoked. final class BuiltInCallable implements Callable, AsyncBuiltInCallable { final String name; /// The overloads declared for this callable. - final List<(ArgumentDeclaration, Callback)> _overloads; + final List<(ParameterList, Callback)> _overloads; final bool acceptsContent; - /// Creates a function with a single [arguments] declaration and a single + /// Creates a function with a single [parameters] declaration and a single /// [callback]. /// - /// The argument declaration is parsed from [arguments], which should not + /// The parameter declaration is parsed from [parameters], which should not /// include parentheses. Throws a [SassFormatException] if parsing fails. /// /// If passed, [url] is the URL of the module in which the function is /// defined. BuiltInCallable.function( - String name, String arguments, Value callback(List arguments), + String name, String parameters, Value callback(List arguments), {Object? url}) : this.parsed( name, - ArgumentDeclaration.parse('@function $name($arguments) {', - url: url), + ParameterList.parse('@function $name($parameters) {', url: url), callback); - /// Creates a mixin with a single [arguments] declaration and a single + /// Creates a mixin with a single [parameters] declaration and a single /// [callback]. /// - /// The argument declaration is parsed from [arguments], which should not + /// The parameter declaration is parsed from [parameters], which should not /// include parentheses. Throws a [SassFormatException] if parsing fails. /// /// If passed, [url] is the URL of the module in which the mixin is /// defined. BuiltInCallable.mixin( - String name, String arguments, void callback(List arguments), + String name, String parameters, void callback(List arguments), {Object? url, bool acceptsContent = false}) - : this.parsed(name, - ArgumentDeclaration.parse('@mixin $name($arguments) {', url: url), + : this.parsed( + name, ParameterList.parse('@mixin $name($parameters) {', url: url), (arguments) { callback(arguments); return sassNull; }, acceptsContent: acceptsContent); - /// Creates a callable with a single [arguments] declaration and a single + /// Creates a callable with a single [parameters] declaration and a single /// [callback]. - BuiltInCallable.parsed(this.name, ArgumentDeclaration arguments, + BuiltInCallable.parsed(this.name, ParameterList parameters, Value callback(List arguments), {this.acceptsContent = false}) - : _overloads = [(arguments, callback)]; + : _overloads = [(parameters, callback)]; /// Creates a function with multiple implementations. /// - /// Each key/value pair in [overloads] defines the argument declaration for + /// Each key/value pair in [overloads] defines the parameter declaration for /// the overload (which should not include parentheses), and the callback to - /// execute if that argument declaration matches. Throws a + /// execute if that parameter declaration matches. Throws a /// [SassFormatException] if parsing fails. /// /// If passed, [url] is the URL of the module in which the function is @@ -79,7 +78,7 @@ final class BuiltInCallable implements Callable, AsyncBuiltInCallable { : _overloads = [ for (var (args, callback) in overloads.pairs) ( - ArgumentDeclaration.parse('@function $name($args) {', url: url), + ParameterList.parse('@function $name($args) {', url: url), callback ) ], @@ -87,27 +86,26 @@ final class BuiltInCallable implements Callable, AsyncBuiltInCallable { BuiltInCallable._(this.name, this._overloads, this.acceptsContent); - /// Returns the argument declaration and Dart callback for the given - /// positional and named arguments. + /// Returns the parameter declaration and Dart callback for the given + /// positional and named parameters. /// /// If no exact match is found, finds the closest approximation. Note that this /// doesn't guarantee that [positional] and [names] are valid for the returned - /// [ArgumentDeclaration]. - (ArgumentDeclaration, Callback) callbackFor( - int positional, Set names) { - (ArgumentDeclaration, Callback)? fuzzyMatch; + /// [ParameterList]. + (ParameterList, Callback) callbackFor(int positional, Set names) { + (ParameterList, Callback)? fuzzyMatch; int? minMismatchDistance; for (var overload in _overloads) { // Ideally, find an exact match. if (overload.$1.matches(positional, names)) return overload; - var mismatchDistance = overload.$1.arguments.length - positional; + var mismatchDistance = overload.$1.parameters.length - positional; if (minMismatchDistance != null) { if (mismatchDistance.abs() > minMismatchDistance.abs()) continue; // If two overloads have the same mismatch distance, favor the overload - // that has more arguments. + // that has more parameters. if (mismatchDistance.abs() == minMismatchDistance.abs() && mismatchDistance < 0) { continue; diff --git a/lib/src/js/parser.dart b/lib/src/js/parser.dart index d641c7123..79d9a5cc9 100644 --- a/lib/src/js/parser.dart +++ b/lib/src/js/parser.dart @@ -88,13 +88,6 @@ void _updateAstPrototypes() { 'accept', (Expression self, ExpressionVisitor visitor) => self.accept(visitor)); - var arguments = ArgumentDeclaration([], bogusSpan); - getJSClass(arguments) - .defineGetter('arguments', (ArgumentDeclaration self) => self.arguments); - var function = FunctionRule('a', arguments, [], bogusSpan); - getJSClass(function) - .superclass - .defineGetter('arguments', (CallableDeclaration self) => self.arguments); _addSupportsConditionToInterpolation(); diff --git a/lib/src/parse/css.dart b/lib/src/parse/css.dart index 4fd9ae2df..4b28dd3e1 100644 --- a/lib/src/parse/css.dart +++ b/lib/src/parse/css.dart @@ -91,7 +91,7 @@ class CssParser extends ScssParser { StringExpression string => string.text, InterpolatedFunctionExpression( :var name, - arguments: ArgumentInvocation( + arguments: ArgumentList( positional: [StringExpression string], named: Map(isEmpty: true), rest: null, @@ -172,8 +172,7 @@ class CssParser extends ScssParser { return FunctionExpression( plain, - ArgumentInvocation( - arguments, const {}, scanner.spanFrom(beforeArguments)), + ArgumentList(arguments, const {}, scanner.spanFrom(beforeArguments)), scanner.spanFrom(start)); } diff --git a/lib/src/parse/stylesheet.dart b/lib/src/parse/stylesheet.dart index 56d63119f..1bfbca99e 100644 --- a/lib/src/parse/stylesheet.dart +++ b/lib/src/parse/stylesheet.dart @@ -105,15 +105,15 @@ abstract class StylesheetParser extends Parser { }); } - ArgumentDeclaration parseArgumentDeclaration() => _parseSingleProduction(() { + ParameterList parseParameterList() => _parseSingleProduction(() { scanner.expectChar($at, name: "@-rule"); identifier(); whitespace(); identifier(); - var arguments = _argumentDeclaration(); + var parameters = _parameterList(); whitespace(); scanner.expectChar($lbrace); - return arguments; + return parameters; }); (Expression, List) parseExpression() => @@ -155,15 +155,14 @@ abstract class StylesheetParser extends Parser { /// option and returns its name and declaration. /// /// If [requireParens] is `false`, this allows parentheses to be omitted. - (String name, ArgumentDeclaration) parseSignature( - {bool requireParens = true}) { + (String name, ParameterList) parseSignature({bool requireParens = true}) { return wrapSpanFormatException(() { var name = identifier(); - var arguments = requireParens || scanner.peekChar() == $lparen - ? _argumentDeclaration() - : ArgumentDeclaration.empty(scanner.emptySpan); + var parameters = requireParens || scanner.peekChar() == $lparen + ? _parameterList() + : ParameterList.empty(scanner.emptySpan); scanner.expectDone(); - return (name, arguments); + return (name, parameters); }); } @@ -790,12 +789,12 @@ abstract class StylesheetParser extends Parser { var beforeWhitespace = scanner.location; whitespace(); - ArgumentInvocation arguments; + ArgumentList arguments; if (scanner.peekChar() == $lparen) { arguments = _argumentInvocation(mixin: true); whitespace(); } else { - arguments = ArgumentInvocation.empty(beforeWhitespace.pointSpan()); + arguments = ArgumentList.empty(beforeWhitespace.pointSpan()); } expectStatementSeparator("@content rule"); @@ -888,7 +887,7 @@ abstract class StylesheetParser extends Parser { } whitespace(); - var arguments = _argumentDeclaration(); + var parameters = _parameterList(); if (_inMixin || _inContentBlock) { error("Mixins may not contain function declarations.", @@ -914,7 +913,7 @@ abstract class StylesheetParser extends Parser { return _withChildren( _functionChild, start, - (children, span) => FunctionRule(name, arguments, children, span, + (children, span) => FunctionRule(name, parameters, children, span, comment: precedingComment)); } @@ -1262,24 +1261,24 @@ abstract class StylesheetParser extends Parser { whitespace(); var arguments = scanner.peekChar() == $lparen ? _argumentInvocation(mixin: true) - : ArgumentInvocation.empty(scanner.emptySpan); + : ArgumentList.empty(scanner.emptySpan); whitespace(); - ArgumentDeclaration? contentArguments; + ParameterList? contentParameters; if (scanIdentifier("using")) { whitespace(); - contentArguments = _argumentDeclaration(); + contentParameters = _parameterList(); whitespace(); } ContentBlock? content; - if (contentArguments != null || lookingAtChildren()) { - var contentArguments_ = - contentArguments ?? ArgumentDeclaration.empty(scanner.emptySpan); + if (contentParameters != null || lookingAtChildren()) { + var contentParameters_ = + contentParameters ?? ParameterList.empty(scanner.emptySpan); var wasInContentBlock = _inContentBlock; _inContentBlock = true; content = _withChildren(_statement, start, - (children, span) => ContentBlock(contentArguments_, children, span)); + (children, span) => ContentBlock(contentParameters_, children, span)); _inContentBlock = wasInContentBlock; } else { expectStatementSeparator(); @@ -1323,9 +1322,9 @@ abstract class StylesheetParser extends Parser { } whitespace(); - var arguments = scanner.peekChar() == $lparen - ? _argumentDeclaration() - : ArgumentDeclaration.empty(scanner.emptySpan); + var parameters = scanner.peekChar() == $lparen + ? _parameterList() + : ParameterList.empty(scanner.emptySpan); if (_inMixin || _inContentBlock) { error("Mixins may not contain mixin declarations.", @@ -1340,7 +1339,7 @@ abstract class StylesheetParser extends Parser { return _withChildren(_statement, start, (children, span) { _inMixin = false; - return MixinRule(name, arguments, children, span, + return MixinRule(name, parameters, children, span, comment: precedingComment); }); } @@ -1611,14 +1610,14 @@ abstract class StylesheetParser extends Parser { error("This at-rule is not allowed here.", scanner.spanFrom(start)); } - /// Consumes an argument declaration. - ArgumentDeclaration _argumentDeclaration() { + /// Consumes a parameter list. + ParameterList _parameterList() { var start = scanner.state; scanner.expectChar($lparen); whitespace(); - var arguments = []; + var parameters = []; var named = {}; - String? restArgument; + String? restParameter; while (scanner.peekChar() == $dollar) { var variableStart = scanner.state; var name = variableName(); @@ -1633,22 +1632,22 @@ abstract class StylesheetParser extends Parser { scanner.expectChar($dot); whitespace(); if (scanner.scanChar($comma)) whitespace(); - restArgument = name; + restParameter = name; break; } - arguments.add(Argument(name, scanner.spanFrom(variableStart), + parameters.add(Parameter(name, scanner.spanFrom(variableStart), defaultValue: defaultValue)); if (!named.add(name)) { - error("Duplicate argument.", arguments.last.span); + error("Duplicate parameter.", parameters.last.span); } if (!scanner.scanChar($comma)) break; whitespace(); } scanner.expectChar($rparen); - return ArgumentDeclaration(arguments, scanner.spanFrom(start), - restArgument: restArgument); + return ParameterList(parameters, scanner.spanFrom(start), + restParameter: restParameter); } // ## Expressions @@ -1662,7 +1661,7 @@ abstract class StylesheetParser extends Parser { /// If [allowEmptySecondArg] is `true`, this allows the second argument to be /// omitted, in which case an unquoted empty string will be passed in its /// place. - ArgumentInvocation _argumentInvocation( + ArgumentList _argumentInvocation( {bool mixin = false, bool allowEmptySecondArg = false}) { var start = scanner.state; scanner.expectChar($lparen); @@ -1715,7 +1714,7 @@ abstract class StylesheetParser extends Parser { } scanner.expectChar($rparen); - return ArgumentInvocation(positional, named, scanner.spanFrom(start), + return ArgumentList(positional, named, scanner.spanFrom(start), rest: rest, keywordRest: keywordRest); } diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 2e04afd16..cafc81e51 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -452,7 +452,7 @@ StackTrace? getTrace(Object error) => /// If [requireParens] is `false`, this allows parentheses to be omitted. /// /// Throws a [SassFormatException] if parsing fails. -(String name, ArgumentDeclaration) parseSignature(String signature, +(String name, ParameterList) parseSignature(String signature, {bool requireParens = true}) { try { return ScssParser(signature).parseSignature(requireParens: requireParens); diff --git a/lib/src/visitor/ast_search.dart b/lib/src/visitor/ast_search.dart index d971afd23..72e45d499 100644 --- a/lib/src/visitor/ast_search.dart +++ b/lib/src/visitor/ast_search.dart @@ -30,8 +30,7 @@ mixin AstSearchVisitor on StatementSearchVisitor node.value.andThen(visitInterpolation) ?? super.visitAtRule(node); - T? visitContentRule(ContentRule node) => - visitArgumentInvocation(node.arguments); + T? visitContentRule(ContentRule node) => visitArgumentList(node.arguments); T? visitDebugRule(DebugRule node) => visitExpression(node.expression); @@ -69,7 +68,7 @@ mixin AstSearchVisitor on StatementSearchVisitor : null); T? visitIncludeRule(IncludeRule node) => - visitArgumentInvocation(node.arguments) ?? super.visitIncludeRule(node); + visitArgumentList(node.arguments) ?? super.visitIncludeRule(node); T? visitLoudComment(LoudComment node) => visitInterpolation(node.text); @@ -105,13 +104,12 @@ mixin AstSearchVisitor on StatementSearchVisitor T? visitColorExpression(ColorExpression node) => null; T? visitFunctionExpression(FunctionExpression node) => - visitArgumentInvocation(node.arguments); + visitArgumentList(node.arguments); T? visitInterpolatedFunctionExpression(InterpolatedFunctionExpression node) => - visitInterpolation(node.name) ?? visitArgumentInvocation(node.arguments); + visitInterpolation(node.name) ?? visitArgumentList(node.arguments); - T? visitIfExpression(IfExpression node) => - visitArgumentInvocation(node.arguments); + T? visitIfExpression(IfExpression node) => visitArgumentList(node.arguments); T? visitListExpression(ListExpression node) => node.contents.search((item) => item.accept(this)); @@ -143,8 +141,8 @@ mixin AstSearchVisitor on StatementSearchVisitor @protected T? visitCallableDeclaration(CallableDeclaration node) => - node.arguments.arguments.search( - (argument) => argument.defaultValue.andThen(visitExpression)) ?? + node.parameters.parameters.search( + (parameter) => parameter.defaultValue.andThen(visitExpression)) ?? super.visitCallableDeclaration(node); /// Visits each expression in an [invocation]. @@ -152,7 +150,7 @@ mixin AstSearchVisitor on StatementSearchVisitor /// The default implementation of the visit methods calls this to visit any /// argument invocation in a statement. @protected - T? visitArgumentInvocation(ArgumentInvocation invocation) => + T? visitArgumentList(ArgumentList invocation) => invocation.positional .search((expression) => visitExpression(expression)) ?? invocation.named.values diff --git a/lib/src/visitor/async_evaluate.dart b/lib/src/visitor/async_evaluate.dart index 803d60fe8..bc33c51d1 100644 --- a/lib/src/visitor/async_evaluate.dart +++ b/lib/src/visitor/async_evaluate.dart @@ -477,7 +477,7 @@ final class _EvaluateVisitor var args = arguments[1] as SassArgumentList; var callableNode = _callableNode!; - var invocation = ArgumentInvocation([], {}, callableNode.span, + var invocation = ArgumentList([], {}, callableNode.span, rest: ValueExpression(args, callableNode.span), keywordRest: args.keywords.isEmpty ? null @@ -551,7 +551,7 @@ final class _EvaluateVisitor var args = arguments[1] as SassArgumentList; var callableNode = _callableNode!; - var invocation = ArgumentInvocation( + var invocation = ArgumentList( const [], const {}, callableNode.span, @@ -1851,7 +1851,7 @@ final class _EvaluateVisitor Future _applyMixin( AsyncCallable? mixin, UserDefinedCallable? contentCallable, - ArgumentInvocation arguments, + ArgumentList arguments, AstNode nodeWithSpan, AstNode nodeWithSpanWithoutContent) async { switch (mixin) { @@ -1887,7 +1887,7 @@ final class _EvaluateVisitor "Mixin doesn't accept a content block.", nodeWithSpanWithoutContent.span, "invocation", - {mixin.declaration.arguments.spanWithName: "declaration"}, + {mixin.declaration.parameters.spanWithName: "declaration"}, _stackTrace(nodeWithSpanWithoutContent.span)); case UserDefinedCallable(): @@ -2934,7 +2934,7 @@ final class _EvaluateVisitor /// Evaluates the arguments in [arguments] as applied to [callable], and /// invokes [run] in a scope with those arguments defined. Future _runUserDefinedCallable( - ArgumentInvocation arguments, + ArgumentList arguments, UserDefinedCallable callable, AstNode nodeWithSpan, Future run()) async { @@ -2953,36 +2953,36 @@ final class _EvaluateVisitor return _withEnvironment(callable.environment.closure(), () { return _environment.scope(() async { _verifyArguments(evaluated.positional.length, evaluated.named, - callable.declaration.arguments, nodeWithSpan); + callable.declaration.parameters, nodeWithSpan); - var declaredArguments = callable.declaration.arguments.arguments; + var parameters = callable.declaration.parameters.parameters; var minLength = - math.min(evaluated.positional.length, declaredArguments.length); + math.min(evaluated.positional.length, parameters.length); for (var i = 0; i < minLength; i++) { - _environment.setLocalVariable(declaredArguments[i].name, + _environment.setLocalVariable(parameters[i].name, evaluated.positional[i], evaluated.positionalNodes[i]); } for (var i = evaluated.positional.length; - i < declaredArguments.length; + i < parameters.length; i++) { - var argument = declaredArguments[i]; - var value = evaluated.named.remove(argument.name) ?? + var parameter = parameters[i]; + var value = evaluated.named.remove(parameter.name) ?? _withoutSlash( - await argument.defaultValue!.accept>(this), - _expressionNode(argument.defaultValue!)); + await parameter.defaultValue!.accept>(this), + _expressionNode(parameter.defaultValue!)); _environment.setLocalVariable( - argument.name, + parameter.name, value, - evaluated.namedNodes[argument.name] ?? - _expressionNode(argument.defaultValue!)); + evaluated.namedNodes[parameter.name] ?? + _expressionNode(parameter.defaultValue!)); } SassArgumentList? argumentList; - var restArgument = callable.declaration.arguments.restArgument; - if (restArgument != null) { - var rest = evaluated.positional.length > declaredArguments.length - ? evaluated.positional.sublist(declaredArguments.length) + var restParameter = callable.declaration.parameters.restParameter; + if (restParameter != null) { + var rest = evaluated.positional.length > parameters.length + ? evaluated.positional.sublist(parameters.length) : const []; argumentList = SassArgumentList( rest, @@ -2991,7 +2991,7 @@ final class _EvaluateVisitor ? ListSeparator.comma : evaluated.separator); _environment.setLocalVariable( - restArgument, argumentList, nodeWithSpan); + restParameter, argumentList, nodeWithSpan); } var result = await run(); @@ -3000,14 +3000,15 @@ final class _EvaluateVisitor if (evaluated.named.isEmpty) return result; if (argumentList.wereKeywordsAccessed) return result; - var argumentWord = pluralize('argument', evaluated.named.keys.length); - var argumentNames = + var parameterWord = + pluralize('parameter', evaluated.named.keys.length); + var parameterNames = toSentence(evaluated.named.keys.map((name) => "\$$name"), 'or'); throw MultiSpanSassRuntimeException( - "No $argumentWord named $argumentNames.", + "No $parameterWord named $parameterNames.", nodeWithSpan.span, "invocation", - {callable.declaration.arguments.spanWithName: "declaration"}, + {callable.declaration.parameters.spanWithName: "declaration"}, _stackTrace(nodeWithSpan.span)); }); }); @@ -3017,7 +3018,7 @@ final class _EvaluateVisitor } /// Evaluates [arguments] as applied to [callable]. - Future _runFunctionCallable(ArgumentInvocation arguments, + Future _runFunctionCallable(ArgumentList arguments, AsyncCallable? callable, AstNode nodeWithSpan) async { if (callable is AsyncBuiltInCallable) { return _withoutSlash( @@ -3078,7 +3079,7 @@ final class _EvaluateVisitor /// Evaluates [invocation] as applied to [callable], and invokes [callable]'s /// body. - Future _runBuiltInCallable(ArgumentInvocation arguments, + Future _runBuiltInCallable(ArgumentList arguments, AsyncBuiltInCallable callable, AstNode nodeWithSpan) async { var evaluated = await _evaluateArguments(arguments); @@ -3091,23 +3092,21 @@ final class _EvaluateVisitor _addExceptionSpan(nodeWithSpan, () => overload.verify(evaluated.positional.length, namedSet)); - var declaredArguments = overload.arguments; - for (var i = evaluated.positional.length; - i < declaredArguments.length; - i++) { - var argument = declaredArguments[i]; - evaluated.positional.add(evaluated.named.remove(argument.name) ?? - _withoutSlash(await argument.defaultValue!.accept(this), - argument.defaultValue!)); + var parameters = overload.parameters; + for (var i = evaluated.positional.length; i < parameters.length; i++) { + var parameter = parameters[i]; + evaluated.positional.add(evaluated.named.remove(parameter.name) ?? + _withoutSlash(await parameter.defaultValue!.accept(this), + parameter.defaultValue!)); } SassArgumentList? argumentList; - if (overload.restArgument != null) { + if (overload.restParameter != null) { var rest = const []; - if (evaluated.positional.length > declaredArguments.length) { - rest = evaluated.positional.sublist(declaredArguments.length); + if (evaluated.positional.length > parameters.length) { + rest = evaluated.positional.sublist(parameters.length); evaluated.positional - .removeRange(declaredArguments.length, evaluated.positional.length); + .removeRange(parameters.length, evaluated.positional.length); } argumentList = SassArgumentList( @@ -3136,7 +3135,7 @@ final class _EvaluateVisitor if (argumentList.wereKeywordsAccessed) return result; throw MultiSpanSassRuntimeException( - "No ${pluralize('argument', evaluated.named.keys.length)} named " + "No ${pluralize('parameter', evaluated.named.keys.length)} named " "${toSentence(evaluated.named.keys.map((name) => "\$$name"), 'or')}.", nodeWithSpan.span, "invocation", @@ -3145,8 +3144,7 @@ final class _EvaluateVisitor } /// Returns the evaluated values of the given [arguments]. - Future<_ArgumentResults> _evaluateArguments( - ArgumentInvocation arguments) async { + Future<_ArgumentResults> _evaluateArguments(ArgumentList arguments) async { // TODO(nweiz): This used to avoid tracking source spans for arguments if // [_sourceMap]s was false or it was being called from // [_runBuiltInCallable]. We always have to track them now to produce better @@ -3322,11 +3320,11 @@ final class _EvaluateVisitor } /// Throws a [SassRuntimeException] if [positional] and [named] aren't valid - /// when applied to [arguments]. + /// when applied to [parameters]. void _verifyArguments(int positional, Map named, - ArgumentDeclaration arguments, AstNode nodeWithSpan) => + ParameterList parameters, AstNode nodeWithSpan) => _addExceptionSpan( - nodeWithSpan, () => arguments.verify(positional, MapKeySet(named))); + nodeWithSpan, () => parameters.verify(positional, MapKeySet(named))); Future visitSelectorExpression(SelectorExpression node) async => _styleRuleIgnoringAtRoot?.originalSelector.asSassList ?? sassNull; diff --git a/lib/src/visitor/evaluate.dart b/lib/src/visitor/evaluate.dart index c06185708..a0d0eb7a9 100644 --- a/lib/src/visitor/evaluate.dart +++ b/lib/src/visitor/evaluate.dart @@ -5,7 +5,7 @@ // DO NOT EDIT. This file was generated from async_evaluate.dart. // See tool/grind/synchronize.dart for details. // -// Checksum: afc541c7e8bbec53a7a076341b1afff290cb0e45 +// Checksum: e47d81d6a53ba17bf1f6bf37e431c47fc82195e5 // // ignore_for_file: unused_import @@ -484,7 +484,7 @@ final class _EvaluateVisitor var args = arguments[1] as SassArgumentList; var callableNode = _callableNode!; - var invocation = ArgumentInvocation([], {}, callableNode.span, + var invocation = ArgumentList([], {}, callableNode.span, rest: ValueExpression(args, callableNode.span), keywordRest: args.keywords.isEmpty ? null @@ -555,7 +555,7 @@ final class _EvaluateVisitor var args = arguments[1] as SassArgumentList; var callableNode = _callableNode!; - var invocation = ArgumentInvocation( + var invocation = ArgumentList( const [], const {}, callableNode.span, @@ -1847,7 +1847,7 @@ final class _EvaluateVisitor void _applyMixin( Callable? mixin, UserDefinedCallable? contentCallable, - ArgumentInvocation arguments, + ArgumentList arguments, AstNode nodeWithSpan, AstNode nodeWithSpanWithoutContent) { switch (mixin) { @@ -1881,7 +1881,7 @@ final class _EvaluateVisitor "Mixin doesn't accept a content block.", nodeWithSpanWithoutContent.span, "invocation", - {mixin.declaration.arguments.spanWithName: "declaration"}, + {mixin.declaration.parameters.spanWithName: "declaration"}, _stackTrace(nodeWithSpanWithoutContent.span)); case UserDefinedCallable(): @@ -2912,7 +2912,7 @@ final class _EvaluateVisitor /// Evaluates the arguments in [arguments] as applied to [callable], and /// invokes [run] in a scope with those arguments defined. V _runUserDefinedCallable( - ArgumentInvocation arguments, + ArgumentList arguments, UserDefinedCallable callable, AstNode nodeWithSpan, V run()) { @@ -2931,35 +2931,35 @@ final class _EvaluateVisitor return _withEnvironment(callable.environment.closure(), () { return _environment.scope(() { _verifyArguments(evaluated.positional.length, evaluated.named, - callable.declaration.arguments, nodeWithSpan); + callable.declaration.parameters, nodeWithSpan); - var declaredArguments = callable.declaration.arguments.arguments; + var parameters = callable.declaration.parameters.parameters; var minLength = - math.min(evaluated.positional.length, declaredArguments.length); + math.min(evaluated.positional.length, parameters.length); for (var i = 0; i < minLength; i++) { - _environment.setLocalVariable(declaredArguments[i].name, + _environment.setLocalVariable(parameters[i].name, evaluated.positional[i], evaluated.positionalNodes[i]); } for (var i = evaluated.positional.length; - i < declaredArguments.length; + i < parameters.length; i++) { - var argument = declaredArguments[i]; - var value = evaluated.named.remove(argument.name) ?? - _withoutSlash(argument.defaultValue!.accept(this), - _expressionNode(argument.defaultValue!)); + var parameter = parameters[i]; + var value = evaluated.named.remove(parameter.name) ?? + _withoutSlash(parameter.defaultValue!.accept(this), + _expressionNode(parameter.defaultValue!)); _environment.setLocalVariable( - argument.name, + parameter.name, value, - evaluated.namedNodes[argument.name] ?? - _expressionNode(argument.defaultValue!)); + evaluated.namedNodes[parameter.name] ?? + _expressionNode(parameter.defaultValue!)); } SassArgumentList? argumentList; - var restArgument = callable.declaration.arguments.restArgument; - if (restArgument != null) { - var rest = evaluated.positional.length > declaredArguments.length - ? evaluated.positional.sublist(declaredArguments.length) + var restParameter = callable.declaration.parameters.restParameter; + if (restParameter != null) { + var rest = evaluated.positional.length > parameters.length + ? evaluated.positional.sublist(parameters.length) : const []; argumentList = SassArgumentList( rest, @@ -2968,7 +2968,7 @@ final class _EvaluateVisitor ? ListSeparator.comma : evaluated.separator); _environment.setLocalVariable( - restArgument, argumentList, nodeWithSpan); + restParameter, argumentList, nodeWithSpan); } var result = run(); @@ -2977,14 +2977,15 @@ final class _EvaluateVisitor if (evaluated.named.isEmpty) return result; if (argumentList.wereKeywordsAccessed) return result; - var argumentWord = pluralize('argument', evaluated.named.keys.length); - var argumentNames = + var parameterWord = + pluralize('parameter', evaluated.named.keys.length); + var parameterNames = toSentence(evaluated.named.keys.map((name) => "\$$name"), 'or'); throw MultiSpanSassRuntimeException( - "No $argumentWord named $argumentNames.", + "No $parameterWord named $parameterNames.", nodeWithSpan.span, "invocation", - {callable.declaration.arguments.spanWithName: "declaration"}, + {callable.declaration.parameters.spanWithName: "declaration"}, _stackTrace(nodeWithSpan.span)); }); }); @@ -2995,7 +2996,7 @@ final class _EvaluateVisitor /// Evaluates [arguments] as applied to [callable]. Value _runFunctionCallable( - ArgumentInvocation arguments, Callable? callable, AstNode nodeWithSpan) { + ArgumentList arguments, Callable? callable, AstNode nodeWithSpan) { if (callable is BuiltInCallable) { return _withoutSlash( _runBuiltInCallable(arguments, callable, nodeWithSpan), nodeWithSpan); @@ -3053,8 +3054,8 @@ final class _EvaluateVisitor /// Evaluates [invocation] as applied to [callable], and invokes [callable]'s /// body. - Value _runBuiltInCallable(ArgumentInvocation arguments, - BuiltInCallable callable, AstNode nodeWithSpan) { + Value _runBuiltInCallable( + ArgumentList arguments, BuiltInCallable callable, AstNode nodeWithSpan) { var evaluated = _evaluateArguments(arguments); var oldCallableNode = _callableNode; @@ -3066,23 +3067,21 @@ final class _EvaluateVisitor _addExceptionSpan(nodeWithSpan, () => overload.verify(evaluated.positional.length, namedSet)); - var declaredArguments = overload.arguments; - for (var i = evaluated.positional.length; - i < declaredArguments.length; - i++) { - var argument = declaredArguments[i]; - evaluated.positional.add(evaluated.named.remove(argument.name) ?? + var parameters = overload.parameters; + for (var i = evaluated.positional.length; i < parameters.length; i++) { + var parameter = parameters[i]; + evaluated.positional.add(evaluated.named.remove(parameter.name) ?? _withoutSlash( - argument.defaultValue!.accept(this), argument.defaultValue!)); + parameter.defaultValue!.accept(this), parameter.defaultValue!)); } SassArgumentList? argumentList; - if (overload.restArgument != null) { + if (overload.restParameter != null) { var rest = const []; - if (evaluated.positional.length > declaredArguments.length) { - rest = evaluated.positional.sublist(declaredArguments.length); + if (evaluated.positional.length > parameters.length) { + rest = evaluated.positional.sublist(parameters.length); evaluated.positional - .removeRange(declaredArguments.length, evaluated.positional.length); + .removeRange(parameters.length, evaluated.positional.length); } argumentList = SassArgumentList( @@ -3111,7 +3110,7 @@ final class _EvaluateVisitor if (argumentList.wereKeywordsAccessed) return result; throw MultiSpanSassRuntimeException( - "No ${pluralize('argument', evaluated.named.keys.length)} named " + "No ${pluralize('parameter', evaluated.named.keys.length)} named " "${toSentence(evaluated.named.keys.map((name) => "\$$name"), 'or')}.", nodeWithSpan.span, "invocation", @@ -3120,7 +3119,7 @@ final class _EvaluateVisitor } /// Returns the evaluated values of the given [arguments]. - _ArgumentResults _evaluateArguments(ArgumentInvocation arguments) { + _ArgumentResults _evaluateArguments(ArgumentList arguments) { // TODO(nweiz): This used to avoid tracking source spans for arguments if // [_sourceMap]s was false or it was being called from // [_runBuiltInCallable]. We always have to track them now to produce better @@ -3296,11 +3295,11 @@ final class _EvaluateVisitor } /// Throws a [SassRuntimeException] if [positional] and [named] aren't valid - /// when applied to [arguments]. + /// when applied to [parameters]. void _verifyArguments(int positional, Map named, - ArgumentDeclaration arguments, AstNode nodeWithSpan) => + ParameterList parameters, AstNode nodeWithSpan) => _addExceptionSpan( - nodeWithSpan, () => arguments.verify(positional, MapKeySet(named))); + nodeWithSpan, () => parameters.verify(positional, MapKeySet(named))); Value visitSelectorExpression(SelectorExpression node) => _styleRuleIgnoringAtRoot?.originalSelector.asSassList ?? sassNull; diff --git a/lib/src/visitor/expression_to_calc.dart b/lib/src/visitor/expression_to_calc.dart index aca554355..497aafd6c 100644 --- a/lib/src/visitor/expression_to_calc.dart +++ b/lib/src/visitor/expression_to_calc.dart @@ -13,7 +13,7 @@ import 'replace_expression.dart'; FunctionExpression expressionToCalc(Expression expression) => FunctionExpression( "calc", - ArgumentInvocation( + ArgumentList( [expression.accept(const _MakeExpressionCalculationSafe())], const {}, expression.span), @@ -31,7 +31,7 @@ class _MakeExpressionCalculationSafe with ReplaceExpressionVisitor { // `mod()` calculation function because there's no browser support, so we have // to work around it by wrapping the call in a Sass function. ? FunctionExpression( - 'max', ArgumentInvocation([node], const {}, node.span), node.span, + 'max', ArgumentList([node], const {}, node.span), node.span, namespace: 'math') : super.visitBinaryOperationExpression(node); diff --git a/lib/src/visitor/recursive_ast.dart b/lib/src/visitor/recursive_ast.dart index 290572697..f2ac25fec 100644 --- a/lib/src/visitor/recursive_ast.dart +++ b/lib/src/visitor/recursive_ast.dart @@ -15,7 +15,7 @@ import 'recursive_statement.dart'; /// This extends [RecursiveStatementVisitor] to traverse each expression in /// addition to each statement. It adds even more protected methods: /// -/// * [visitArgumentInvocation] +/// * [visitArgumentList] /// * [visitSupportsCondition] /// * [visitInterpolation] /// @@ -34,7 +34,7 @@ mixin RecursiveAstVisitor on RecursiveStatementVisitor } void visitContentRule(ContentRule node) { - visitArgumentInvocation(node.arguments); + visitArgumentList(node.arguments); } void visitDebugRule(DebugRule node) { @@ -91,7 +91,7 @@ mixin RecursiveAstVisitor on RecursiveStatementVisitor } void visitIncludeRule(IncludeRule node) { - visitArgumentInvocation(node.arguments); + visitArgumentList(node.arguments); super.visitIncludeRule(node); } @@ -157,17 +157,17 @@ mixin RecursiveAstVisitor on RecursiveStatementVisitor } void visitFunctionExpression(FunctionExpression node) { - visitArgumentInvocation(node.arguments); + visitArgumentList(node.arguments); } void visitInterpolatedFunctionExpression( InterpolatedFunctionExpression node) { visitInterpolation(node.name); - visitArgumentInvocation(node.arguments); + visitArgumentList(node.arguments); } void visitIfExpression(IfExpression node) { - visitArgumentInvocation(node.arguments); + visitArgumentList(node.arguments); } void visitListExpression(ListExpression node) { @@ -211,8 +211,8 @@ mixin RecursiveAstVisitor on RecursiveStatementVisitor @protected void visitCallableDeclaration(CallableDeclaration node) { - for (var argument in node.arguments.arguments) { - argument.defaultValue.andThen(visitExpression); + for (var parameter in node.parameters.parameters) { + parameter.defaultValue.andThen(visitExpression); } super.visitCallableDeclaration(node); } @@ -222,7 +222,7 @@ mixin RecursiveAstVisitor on RecursiveStatementVisitor /// The default implementation of the visit methods calls this to visit any /// argument invocation in a statement. @protected - void visitArgumentInvocation(ArgumentInvocation invocation) { + void visitArgumentList(ArgumentList invocation) { for (var expression in invocation.positional) { visitExpression(expression); } diff --git a/lib/src/visitor/replace_expression.dart b/lib/src/visitor/replace_expression.dart index 8c06423de..f32184b8b 100644 --- a/lib/src/visitor/replace_expression.dart +++ b/lib/src/visitor/replace_expression.dart @@ -16,7 +16,7 @@ import 'interface/expression.dart'; /// protected methods that can be overridden to add behavior for a wide variety /// of AST nodes: /// -/// * [visitArgumentInvocation] +/// * [visitArgumentList] /// * [visitSupportsCondition] /// * [visitInterpolation] /// @@ -33,16 +33,16 @@ mixin ReplaceExpressionVisitor implements ExpressionVisitor { Expression visitFunctionExpression( FunctionExpression node) => FunctionExpression( - node.originalName, visitArgumentInvocation(node.arguments), node.span, + node.originalName, visitArgumentList(node.arguments), node.span, namespace: node.namespace); Expression visitInterpolatedFunctionExpression( InterpolatedFunctionExpression node) => InterpolatedFunctionExpression(visitInterpolation(node.name), - visitArgumentInvocation(node.arguments), node.span); + visitArgumentList(node.arguments), node.span); Expression visitIfExpression(IfExpression node) => - IfExpression(visitArgumentInvocation(node.arguments), node.span); + IfExpression(visitArgumentList(node.arguments), node.span); Expression visitListExpression(ListExpression node) => ListExpression( node.contents.map((item) => item.accept(this)), node.separator, node.span, @@ -81,16 +81,15 @@ mixin ReplaceExpressionVisitor implements ExpressionVisitor { /// The default implementation of the visit methods calls this to replace any /// argument invocation in an expression. @protected - ArgumentInvocation visitArgumentInvocation(ArgumentInvocation invocation) => - ArgumentInvocation( - invocation.positional.map((expression) => expression.accept(this)), - { - for (var (name, value) in invocation.named.pairs) - name: value.accept(this) - }, - invocation.span, - rest: invocation.rest?.accept(this), - keywordRest: invocation.keywordRest?.accept(this)); + ArgumentList visitArgumentList(ArgumentList invocation) => ArgumentList( + invocation.positional.map((expression) => expression.accept(this)), + { + for (var (name, value) in invocation.named.pairs) + name: value.accept(this) + }, + invocation.span, + rest: invocation.rest?.accept(this), + keywordRest: invocation.keywordRest?.accept(this)); /// Replaces each expression in [condition]. /// diff --git a/lib/src/visitor/source_interpolation.dart b/lib/src/visitor/source_interpolation.dart index aadb3e1e5..9a8e70634 100644 --- a/lib/src/visitor/source_interpolation.dart +++ b/lib/src/visitor/source_interpolation.dart @@ -37,7 +37,7 @@ class SourceInterpolationVisitor implements ExpressionVisitor { /// Visits the positional arguments in [arguments] with [visitor], if it's /// valid interpolated plain CSS. - void _visitArguments(ArgumentInvocation arguments, + void _visitArguments(ArgumentList arguments, [ExpressionVisitor? visitor]) { if (arguments.named.isNotEmpty || arguments.rest != null) return; diff --git a/pkg/sass-parser/lib/src/parameter-list.ts b/pkg/sass-parser/lib/src/parameter-list.ts index bf9561adc..0f78b9738 100644 --- a/pkg/sass-parser/lib/src/parameter-list.ts +++ b/pkg/sass-parser/lib/src/parameter-list.ts @@ -94,19 +94,19 @@ export class ParameterList constructor(defaults?: ParameterListProps); /** @hidden */ - constructor(_: undefined, inner: sassInternal.ArgumentDeclaration); - constructor(defaults?: object, inner?: sassInternal.ArgumentDeclaration) { + constructor(_: undefined, inner: sassInternal.ParameterList); + constructor(defaults?: object, inner?: sassInternal.ParameterList) { super(Array.isArray(defaults) ? {nodes: defaults} : defaults); if (inner) { this.source = new LazySource(inner); // TODO: set lazy raws here to use when stringifying this._nodes = []; - for (const argument of inner.arguments) { - this.append(new Parameter(undefined, argument)); + for (const parameter of inner.parameters) { + this.append(new Parameter(undefined, parameter)); } - if (inner.restArgument) { - // TODO: Provide source information for this argument. - this.append({name: inner.restArgument, rest: true}); + if (inner.restParameter) { + // TODO: Provide source information for this parameter. + this.append({name: inner.restParameter, rest: true}); } } if (this._nodes === undefined) this._nodes = []; diff --git a/pkg/sass-parser/lib/src/parameter.ts b/pkg/sass-parser/lib/src/parameter.ts index a3a869027..b40eb6526 100644 --- a/pkg/sass-parser/lib/src/parameter.ts +++ b/pkg/sass-parser/lib/src/parameter.ts @@ -149,8 +149,8 @@ export class Parameter extends Node { constructor(defaults: ParameterProps); /** @hidden */ - constructor(_: undefined, inner: sassInternal.Argument); - constructor(defaults?: ParameterProps, inner?: sassInternal.Argument) { + constructor(_: undefined, inner: sassInternal.Parameter); + constructor(defaults?: ParameterProps, inner?: sassInternal.Parameter) { if (typeof defaults === 'string') { defaults = {name: defaults}; } else if (Array.isArray(defaults)) { diff --git a/pkg/sass-parser/lib/src/sass-internal.ts b/pkg/sass-parser/lib/src/sass-internal.ts index 325eddb2b..205dcb55d 100644 --- a/pkg/sass-parser/lib/src/sass-internal.ts +++ b/pkg/sass-parser/lib/src/sass-internal.ts @@ -66,19 +66,19 @@ declare namespace SassInternal { readonly span: FileSpan; } - class ArgumentDeclaration extends SassNode { - readonly arguments: Argument[]; - readonly restArgument?: string; + class Interpolation extends SassNode { + contents: (string | Expression)[]; + get asPlain(): string | undefined; } - class Argument extends SassNode { - readonly name: string; - readonly defaultValue?: Expression; + class ParameterList extends SassNode { + readonly parameters: Parameter[]; + readonly restParameter?: string; } - class Interpolation extends SassNode { - contents: (string | Expression)[]; - get asPlain(): string | undefined; + class Parameter extends SassNode { + readonly name: string; + readonly defaultValue?: Expression; } class Statement extends SassNode { @@ -136,7 +136,7 @@ declare namespace SassInternal { class FunctionRule extends ParentStatement { readonly name: string; - readonly arguments: ArgumentDeclaration; + readonly parameters: ParameterList; } class LoudComment extends Statement { @@ -149,7 +149,7 @@ declare namespace SassInternal { class MixinRule extends ParentStatement { readonly name: string; - readonly arguments: ArgumentDeclaration; + readonly parameters: ParameterList; } class ReturnRule extends Statement { @@ -304,8 +304,8 @@ export type UseRule = SassInternal.UseRule; export type VariableDeclaration = SassInternal.VariableDeclaration; export type WarnRule = SassInternal.WarnRule; export type WhileRule = SassInternal.WhileRule; -export type Argument = SassInternal.Argument; -export type ArgumentDeclaration = SassInternal.ArgumentDeclaration; +export type Parameter = SassInternal.Parameter; +export type ParameterList = SassInternal.ParameterList; export type ConfiguredVariable = SassInternal.ConfiguredVariable; export type Interpolation = SassInternal.Interpolation; export type Expression = SassInternal.Expression; diff --git a/pkg/sass-parser/lib/src/statement/function-rule.ts b/pkg/sass-parser/lib/src/statement/function-rule.ts index 4b87811d8..95b6db714 100644 --- a/pkg/sass-parser/lib/src/statement/function-rule.ts +++ b/pkg/sass-parser/lib/src/statement/function-rule.ts @@ -115,7 +115,7 @@ export class FunctionRule if (inner) { this.source = new LazySource(inner); this.functionName = inner.name; - this.parameters = new ParameterList(undefined, inner.arguments); + this.parameters = new ParameterList(undefined, inner.parameters); appendInternalChildren(this, inner.children); } } diff --git a/pkg/sass-parser/lib/src/statement/mixin-rule.ts b/pkg/sass-parser/lib/src/statement/mixin-rule.ts index 8020f5fb4..90712d090 100644 --- a/pkg/sass-parser/lib/src/statement/mixin-rule.ts +++ b/pkg/sass-parser/lib/src/statement/mixin-rule.ts @@ -115,7 +115,7 @@ export class MixinRule if (inner) { this.source = new LazySource(inner); this.mixinName = inner.name; - this.parameters = new ParameterList(undefined, inner.arguments); + this.parameters = new ParameterList(undefined, inner.parameters); appendInternalChildren(this, inner.children); } } diff --git a/pkg/sass_api/CHANGELOG.md b/pkg/sass_api/CHANGELOG.md index 0907ed221..e905cf315 100644 --- a/pkg/sass_api/CHANGELOG.md +++ b/pkg/sass_api/CHANGELOG.md @@ -1,6 +1,12 @@ -## 14.5.0 +## 15.0.0 -* No user-visible changes. +* Rename `ArgumentInvocation` to `ArgumentList`, `ArgumentDeclaration` to + `ParameterList`, and `Argument` to `Parameter` to better match the + conventional distinction between "arugments" and "parameters". + +* Rename `ArgumentDeclaration.arguments` to `ParameterList.parameters`, + `ArgumentDeclaration.restArgument` to `ParameterList.restParameter`, + `CallableDeclaration.arguments` to `.parameters`. ## 14.4.1-dev diff --git a/pkg/sass_api/pubspec.yaml b/pkg/sass_api/pubspec.yaml index a129337a4..cd149d3a8 100644 --- a/pkg/sass_api/pubspec.yaml +++ b/pkg/sass_api/pubspec.yaml @@ -2,7 +2,7 @@ name: sass_api # Note: Every time we add a new Sass AST node, we need to bump the *major* # version because it's a breaking change for anyone who's implementing the # visitor interface(s). -version: 14.5.0 +version: 15.0.0 description: Additional APIs for Dart Sass. homepage: https://github.com/sass/dart-sass diff --git a/test/embedded/function_test.dart b/test/embedded/function_test.dart index 694341405..584151e79 100644 --- a/test/embedded/function_test.dart +++ b/test/embedded/function_test.dart @@ -165,7 +165,7 @@ void main() { ..success = _true)); var failure = await getCompileFailure(_process); - expect(failure.message, equals(r"No argument named $arg.")); + expect(failure.message, equals(r"No parameter named $arg.")); await _process.close(); });