mirror of
https://github.com/danog/dart-sass.git
synced 2024-11-27 04:34:59 +01:00
Merge pull request #593 from sass/merge-use
Merge branch 'feature.use' into master
This commit is contained in:
commit
4c7b6cc0e5
@ -53,6 +53,7 @@ export 'sass/statement/silent_comment.dart';
|
||||
export 'sass/statement/style_rule.dart';
|
||||
export 'sass/statement/stylesheet.dart';
|
||||
export 'sass/statement/supports_rule.dart';
|
||||
export 'sass/statement/use_rule.dart';
|
||||
export 'sass/statement/variable_declaration.dart';
|
||||
export 'sass/statement/warn_rule.dart';
|
||||
export 'sass/statement/while_rule.dart';
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../../../utils.dart';
|
||||
import '../../../visitor/interface/expression.dart';
|
||||
import '../expression.dart';
|
||||
import '../argument_invocation.dart';
|
||||
@ -15,6 +14,10 @@ import '../interpolation.dart';
|
||||
///
|
||||
/// This may be a plain CSS function or a Sass function.
|
||||
class FunctionExpression implements Expression, CallableInvocation {
|
||||
/// The namespace of the function being invoked, or `null` if it's invoked
|
||||
/// without a namespace.
|
||||
final String namespace;
|
||||
|
||||
/// The name of the function being invoked.
|
||||
///
|
||||
/// If this is interpolated, the function will be interpreted as plain CSS,
|
||||
@ -24,12 +27,17 @@ class FunctionExpression implements Expression, CallableInvocation {
|
||||
/// The arguments to pass to the function.
|
||||
final ArgumentInvocation arguments;
|
||||
|
||||
FileSpan get span => spanForList([name, arguments]);
|
||||
final FileSpan span;
|
||||
|
||||
FunctionExpression(this.name, this.arguments);
|
||||
FunctionExpression(this.name, this.arguments, this.span, {this.namespace});
|
||||
|
||||
T accept<T>(ExpressionVisitor<T> visitor) =>
|
||||
visitor.visitFunctionExpression(this);
|
||||
|
||||
String toString() => "$name$arguments";
|
||||
String toString() {
|
||||
var buffer = StringBuffer();
|
||||
if (namespace != null) buffer.write("$namespace.");
|
||||
buffer.write("$name$arguments");
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
@ -9,15 +9,24 @@ import '../expression.dart';
|
||||
|
||||
/// A Sass variable.
|
||||
class VariableExpression implements Expression {
|
||||
/// The namespace of the variable being referenced, or `null` if it's
|
||||
/// referenced without a namespace.
|
||||
final String namespace;
|
||||
|
||||
/// The name of this variable.
|
||||
final String name;
|
||||
|
||||
final FileSpan span;
|
||||
|
||||
VariableExpression(this.name, this.span);
|
||||
VariableExpression(this.name, this.span, {this.namespace});
|
||||
|
||||
T accept<T>(ExpressionVisitor<T> visitor) =>
|
||||
visitor.visitVariableExpression(this);
|
||||
|
||||
String toString() => "\$$name";
|
||||
String toString() {
|
||||
var buffer = StringBuffer("\$");
|
||||
if (namespace != null) buffer.write("$namespace.");
|
||||
buffer.write(name);
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,10 @@ import 'content_block.dart';
|
||||
|
||||
/// A mixin invocation.
|
||||
class IncludeRule implements Statement, CallableInvocation {
|
||||
/// The namespace of the mixin being invoked, or `null` if it's invoked
|
||||
/// without a namespace.
|
||||
final String namespace;
|
||||
|
||||
/// The name of the mixin being invoked.
|
||||
final String name;
|
||||
|
||||
@ -24,12 +28,15 @@ class IncludeRule implements Statement, CallableInvocation {
|
||||
|
||||
final FileSpan span;
|
||||
|
||||
IncludeRule(this.name, this.arguments, this.span, {this.content});
|
||||
IncludeRule(this.name, this.arguments, this.span,
|
||||
{this.namespace, this.content});
|
||||
|
||||
T accept<T>(StatementVisitor<T> visitor) => visitor.visitIncludeRule(this);
|
||||
|
||||
String toString() {
|
||||
var buffer = StringBuffer("@include $name");
|
||||
var buffer = StringBuffer("@include ");
|
||||
if (namespace != null) buffer.write("$namespace.");
|
||||
buffer.write(name);
|
||||
if (!arguments.isEmpty) buffer.write("($arguments)");
|
||||
buffer.write(content == null ? ";" : " $content");
|
||||
return buffer.toString();
|
||||
|
30
lib/src/ast/sass/statement/use_rule.dart
Normal file
30
lib/src/ast/sass/statement/use_rule.dart
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2016 Google Inc. Use of this source code is governed by an
|
||||
// MIT-style license that can be found in the LICENSE file or at
|
||||
// https://opensource.org/licenses/MIT.
|
||||
|
||||
import 'package:source_span/source_span.dart';
|
||||
|
||||
import '../../../visitor/interface/statement.dart';
|
||||
import '../expression/string.dart';
|
||||
import '../statement.dart';
|
||||
|
||||
/// A `@use` rule.
|
||||
class UseRule implements Statement {
|
||||
/// The URI of the module to use.
|
||||
///
|
||||
/// If this is relative, it's relative to the containing file.
|
||||
final Uri url;
|
||||
|
||||
/// The namespace for members of the used module, or `null` if the members
|
||||
/// can be accessed without a namespace.
|
||||
final String namespace;
|
||||
|
||||
final FileSpan span;
|
||||
|
||||
UseRule(this.url, this.namespace, this.span);
|
||||
|
||||
T accept<T>(StatementVisitor<T> visitor) => visitor.visitUseRule(this);
|
||||
|
||||
String toString() => "@use ${StringExpression.quoteText(url.toString())} as "
|
||||
"${namespace ?? "*"};";
|
||||
}
|
@ -15,6 +15,10 @@ import 'silent_comment.dart';
|
||||
///
|
||||
/// This defines or sets a variable.
|
||||
class VariableDeclaration implements Statement {
|
||||
/// The namespace of the variable being set, or `null` if it's defined or set
|
||||
/// without a namespace.
|
||||
final String namespace;
|
||||
|
||||
/// The name of the variable.
|
||||
final String name;
|
||||
|
||||
@ -37,10 +41,18 @@ class VariableDeclaration implements Statement {
|
||||
final FileSpan span;
|
||||
|
||||
VariableDeclaration(this.name, this.expression, this.span,
|
||||
{bool guarded = false, bool global = false, SilentComment comment})
|
||||
{this.namespace,
|
||||
bool guarded = false,
|
||||
bool global = false,
|
||||
SilentComment comment})
|
||||
: isGuarded = guarded,
|
||||
isGlobal = global,
|
||||
comment = comment;
|
||||
comment = comment {
|
||||
if (namespace != null && global) {
|
||||
throw ArgumentError(
|
||||
"Other modules' members can't be defined with !global.");
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a variable declaration from [contents].
|
||||
///
|
||||
@ -53,5 +65,10 @@ class VariableDeclaration implements Statement {
|
||||
T accept<T>(StatementVisitor<T> visitor) =>
|
||||
visitor.visitVariableDeclaration(this);
|
||||
|
||||
String toString() => "\$$name: $expression;";
|
||||
String toString() {
|
||||
var buffer = StringBuffer("\$");
|
||||
if (namespace != null) buffer.write("$namespace.");
|
||||
buffer.write("$name: $expression;");
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
@ -139,6 +139,7 @@ class CssParser extends ScssParser {
|
||||
// as plain CSS, rather than calling a user-defined function.
|
||||
Interpolation([StringExpression(identifier)], identifier.span),
|
||||
ArgumentInvocation(
|
||||
arguments, const {}, scanner.spanFrom(beforeArguments)));
|
||||
arguments, const {}, scanner.spanFrom(beforeArguments)),
|
||||
scanner.spanFrom(start));
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import '../utils.dart';
|
||||
/// This provides utility methods and common token parsing. Unless specified
|
||||
/// otherwise, a parse method throws a [SassFormatException] if it fails to
|
||||
/// parse.
|
||||
abstract class Parser {
|
||||
class Parser {
|
||||
/// The scanner that scans through the text being parsed.
|
||||
final SpanScanner scanner;
|
||||
|
||||
@ -25,10 +25,25 @@ abstract class Parser {
|
||||
@protected
|
||||
final Logger logger;
|
||||
|
||||
/// Parses [text] as a CSS identifier and returns the result.
|
||||
///
|
||||
/// Throws a [SassFormatException] if parsing fails.
|
||||
static String parseIdentifier(String text, {Logger logger}) =>
|
||||
Parser(text, logger: logger)._parseIdentifier();
|
||||
|
||||
@protected
|
||||
Parser(String contents, {url, Logger logger})
|
||||
: scanner = SpanScanner(contents, sourceUrl: url),
|
||||
logger = logger ?? const Logger.stderr();
|
||||
|
||||
String _parseIdentifier() {
|
||||
return wrapSpanFormatException(() {
|
||||
var result = identifier();
|
||||
scanner.expectDone();
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
// ## Tokens
|
||||
|
||||
/// Consumes whitespace, including any comments.
|
||||
@ -114,8 +129,8 @@ abstract class Parser {
|
||||
@protected
|
||||
String identifier({bool unit = false}) {
|
||||
// NOTE: this logic is largely duplicated in
|
||||
// StylesheetParser._interpolatedIdentifier. Most changes here should be
|
||||
// mirrored there.
|
||||
// StylesheetParser._interpolatedIdentifier and isIdentifier in utils.dart.
|
||||
// Most changes here should be mirrored there.
|
||||
|
||||
var text = StringBuffer();
|
||||
while (scanner.scanChar($dash)) {
|
||||
|
@ -13,6 +13,7 @@ import 'package:tuple/tuple.dart';
|
||||
|
||||
import '../ast/sass.dart';
|
||||
import '../color_names.dart';
|
||||
import '../exception.dart';
|
||||
import '../interpolation_buffer.dart';
|
||||
import '../logger.dart';
|
||||
import '../util/character.dart';
|
||||
@ -21,6 +22,14 @@ import '../value.dart';
|
||||
import '../value/color.dart';
|
||||
import 'parser.dart';
|
||||
|
||||
/// Whether to parse `@use` rules.
|
||||
///
|
||||
/// This is set to `false` on Dart Sass's master branch and `true` on the
|
||||
/// `feature.use` branch. It allows us to avoid having separate development
|
||||
/// tracks as much as possible without shipping `@use` support until we're
|
||||
/// ready.
|
||||
const _parseUse = false;
|
||||
|
||||
/// The base class for both the SCSS and indented syntax parsers.
|
||||
///
|
||||
/// Having a base class that's separate from both parsers allows us to make
|
||||
@ -33,6 +42,10 @@ import 'parser.dart';
|
||||
/// private, except where they have to be public for subclasses to refer to
|
||||
/// them.
|
||||
abstract class StylesheetParser extends Parser {
|
||||
/// Whether we've consumed a rule other than `@charset`, `@forward`, or
|
||||
/// `@use`.
|
||||
var _isUseAllowed = true;
|
||||
|
||||
/// Whether the parser is currently parsing the contents of a mixin
|
||||
/// declaration.
|
||||
var _inMixin = false;
|
||||
@ -131,18 +144,21 @@ abstract class StylesheetParser extends Parser {
|
||||
|
||||
case $plus:
|
||||
if (!indented || !lookingAtIdentifier(1)) return _styleRule();
|
||||
_isUseAllowed = false;
|
||||
var start = scanner.state;
|
||||
scanner.readChar();
|
||||
return _includeRule(start);
|
||||
|
||||
case $equal:
|
||||
if (!indented) return _styleRule();
|
||||
_isUseAllowed = false;
|
||||
var start = scanner.state;
|
||||
scanner.readChar();
|
||||
whitespace();
|
||||
return _mixinRule(start);
|
||||
|
||||
default:
|
||||
_isUseAllowed = false;
|
||||
return _inStyleRule || _inUnknownAtRule || _inMixin || _inContentBlock
|
||||
? _declarationOrStyleRule()
|
||||
: _styleRule();
|
||||
@ -155,7 +171,13 @@ abstract class StylesheetParser extends Parser {
|
||||
var precedingComment = lastSilentComment;
|
||||
lastSilentComment = null;
|
||||
var start = scanner.state;
|
||||
|
||||
String namespace;
|
||||
var name = variableName();
|
||||
if (scanner.scanChar($dot)) {
|
||||
namespace = name;
|
||||
name = _publicIdentifier();
|
||||
}
|
||||
|
||||
if (plainCss) {
|
||||
error("Sass variables aren't allowed in plain CSS.",
|
||||
@ -170,23 +192,32 @@ abstract class StylesheetParser extends Parser {
|
||||
|
||||
var guarded = false;
|
||||
var global = false;
|
||||
var flagStart = scanner.state;
|
||||
while (scanner.scanChar($exclamation)) {
|
||||
var flagStart = scanner.state;
|
||||
var flag = identifier();
|
||||
if (flag == 'default') {
|
||||
guarded = true;
|
||||
} else if (flag == 'global') {
|
||||
if (namespace != null) {
|
||||
error("!global isn't allowed for variables in other modules.",
|
||||
scanner.spanFrom(flagStart));
|
||||
}
|
||||
|
||||
global = true;
|
||||
} else {
|
||||
error("Invalid flag name.", scanner.spanFrom(flagStart));
|
||||
}
|
||||
|
||||
whitespace();
|
||||
flagStart = scanner.state;
|
||||
}
|
||||
|
||||
expectStatementSeparator("variable declaration");
|
||||
return VariableDeclaration(name, value, scanner.spanFrom(start),
|
||||
guarded: guarded, global: global, comment: precedingComment);
|
||||
namespace: namespace,
|
||||
guarded: guarded,
|
||||
global: global,
|
||||
comment: precedingComment);
|
||||
}
|
||||
|
||||
/// Consumes a style rule.
|
||||
@ -455,10 +486,18 @@ abstract class StylesheetParser extends Parser {
|
||||
var name = interpolatedIdentifier();
|
||||
whitespace();
|
||||
|
||||
// We want to set [_isUseAllowed] to `false` *unless* we're parsing
|
||||
// `@charset`, `@forward`, or `@use`. To avoid double-comparing the rule
|
||||
// name, we always set it to `false` and then set it back to its previous
|
||||
// value if we're parsing an allowed rule.
|
||||
var wasUseAllowed = _isUseAllowed;
|
||||
_isUseAllowed = false;
|
||||
|
||||
switch (name.asPlain) {
|
||||
case "at-root":
|
||||
return _atRootRule(start);
|
||||
case "charset":
|
||||
_isUseAllowed = wasUseAllowed;
|
||||
if (!root) _disallowedAtRule(start);
|
||||
string();
|
||||
return null;
|
||||
@ -494,6 +533,10 @@ abstract class StylesheetParser extends Parser {
|
||||
return _disallowedAtRule(start);
|
||||
case "supports":
|
||||
return supportsRule(start);
|
||||
case "use":
|
||||
_isUseAllowed = wasUseAllowed;
|
||||
if (!root) _disallowedAtRule(start);
|
||||
return _useRule(start);
|
||||
case "warn":
|
||||
return _warnRule(start);
|
||||
case "while":
|
||||
@ -933,7 +976,13 @@ abstract class StylesheetParser extends Parser {
|
||||
///
|
||||
/// [start] should point before the `@`.
|
||||
IncludeRule _includeRule(LineScannerState start) {
|
||||
String namespace;
|
||||
var name = identifier();
|
||||
if (scanner.scanChar($dot)) {
|
||||
namespace = name;
|
||||
name = _publicIdentifier();
|
||||
}
|
||||
|
||||
whitespace();
|
||||
var arguments = scanner.peekChar() == $lparen
|
||||
? _argumentInvocation(mixin: true)
|
||||
@ -965,7 +1014,8 @@ abstract class StylesheetParser extends Parser {
|
||||
|
||||
var span =
|
||||
scanner.spanFrom(start, start).expand((content ?? arguments).span);
|
||||
return IncludeRule(name, arguments, span, content: content);
|
||||
return IncludeRule(name, arguments, span,
|
||||
namespace: namespace, content: content);
|
||||
}
|
||||
|
||||
/// Consumes a `@media` rule.
|
||||
@ -1115,6 +1165,49 @@ relase. For details, see http://bit.ly/moz-document.
|
||||
(children, span) => SupportsRule(condition, children, span));
|
||||
}
|
||||
|
||||
/// Consumes a `@use` rule.
|
||||
///
|
||||
/// [start] should point before the `@`.
|
||||
UseRule _useRule(LineScannerState start) {
|
||||
var urlString = string();
|
||||
Uri url;
|
||||
try {
|
||||
url = Uri.parse(urlString);
|
||||
} on FormatException catch (innerError) {
|
||||
error("Invalid URL: ${innerError.message}", scanner.spanFrom(start));
|
||||
}
|
||||
whitespace();
|
||||
|
||||
String namespace;
|
||||
if (scanIdentifier("as")) {
|
||||
whitespace();
|
||||
namespace = scanner.scanChar($asterisk) ? null : identifier();
|
||||
} else {
|
||||
var basename = url.pathSegments.isEmpty ? "" : url.pathSegments.last;
|
||||
var dot = basename.indexOf(".");
|
||||
namespace = basename.substring(0, dot == -1 ? basename.length : dot);
|
||||
|
||||
try {
|
||||
namespace = Parser.parseIdentifier(namespace, logger: logger);
|
||||
} on SassFormatException {
|
||||
error('Invalid Sass identifier "$namespace"', scanner.spanFrom(start));
|
||||
}
|
||||
}
|
||||
expectStatementSeparator("@use rule");
|
||||
|
||||
var span = scanner.spanFrom(start);
|
||||
if (!_parseUse) {
|
||||
error(
|
||||
"@use is coming soon, but it's not supported in this version of "
|
||||
"Dart Sass.",
|
||||
span);
|
||||
} else if (!_isUseAllowed) {
|
||||
error("@use rules must be written before any other rules.", span);
|
||||
}
|
||||
|
||||
return UseRule(url, namespace, span);
|
||||
}
|
||||
|
||||
/// Consumes a `@warn` rule.
|
||||
///
|
||||
/// [start] should point before the `@`.
|
||||
@ -2143,11 +2236,22 @@ relase. For details, see http://bit.ly/moz-document.
|
||||
/// Consumes a variable expression.
|
||||
VariableExpression _variable() {
|
||||
var start = scanner.state;
|
||||
var name = variableName();
|
||||
if (!plainCss) return VariableExpression(name, scanner.spanFrom(start));
|
||||
|
||||
error(
|
||||
"Sass variables aren't allowed in plain CSS.", scanner.spanFrom(start));
|
||||
String namespace;
|
||||
var name = variableName();
|
||||
if (scanner.peekChar() == $dot && scanner.peekChar(1) != $dot) {
|
||||
scanner.readChar();
|
||||
namespace = name;
|
||||
name = _publicIdentifier();
|
||||
}
|
||||
|
||||
if (plainCss) {
|
||||
error("Sass variables aren't allowed in plain CSS.",
|
||||
scanner.spanFrom(start));
|
||||
}
|
||||
|
||||
return VariableExpression(name, scanner.spanFrom(start),
|
||||
namespace: namespace);
|
||||
}
|
||||
|
||||
/// Consumes a selector expression.
|
||||
@ -2254,9 +2358,31 @@ relase. For details, see http://bit.ly/moz-document.
|
||||
if (specialFunction != null) return specialFunction;
|
||||
}
|
||||
|
||||
return scanner.peekChar() == $lparen
|
||||
? FunctionExpression(identifier, _argumentInvocation())
|
||||
: StringExpression(identifier);
|
||||
switch (scanner.peekChar()) {
|
||||
case $dot:
|
||||
if (scanner.peekChar(1) == $dot) return StringExpression(identifier);
|
||||
|
||||
var namespace = identifier.asPlain;
|
||||
scanner.readChar();
|
||||
var beforeName = scanner.state;
|
||||
var name = Interpolation(
|
||||
[this._publicIdentifier()], scanner.spanFrom(beforeName));
|
||||
|
||||
if (namespace == null) {
|
||||
error("Interpolation isn't allowed in namespaces.", identifier.span);
|
||||
}
|
||||
|
||||
return FunctionExpression(
|
||||
name, _argumentInvocation(), scanner.spanFrom(start),
|
||||
namespace: namespace);
|
||||
|
||||
case $lparen:
|
||||
return FunctionExpression(
|
||||
identifier, _argumentInvocation(), scanner.spanFrom(start));
|
||||
|
||||
default:
|
||||
return StringExpression(identifier);
|
||||
}
|
||||
}
|
||||
|
||||
/// If [name] is the name of a function with special syntax, consumes it.
|
||||
@ -2510,8 +2636,8 @@ relase. For details, see http://bit.ly/moz-document.
|
||||
var contents = _tryUrlContents(start);
|
||||
if (contents != null) return StringExpression(contents);
|
||||
|
||||
return FunctionExpression(
|
||||
Interpolation(["url"], scanner.spanFrom(start)), _argumentInvocation());
|
||||
return FunctionExpression(Interpolation(["url"], scanner.spanFrom(start)),
|
||||
_argumentInvocation(), scanner.spanFrom(start));
|
||||
}
|
||||
|
||||
/// Consumes tokens up to "{", "}", ";", or "!".
|
||||
@ -2620,8 +2746,8 @@ relase. For details, see http://bit.ly/moz-document.
|
||||
///
|
||||
/// Unlike [declarationValue], this allows interpolation.
|
||||
StringExpression _interpolatedDeclarationValue({bool allowEmpty = false}) {
|
||||
// NOTE: this logic is largely duplicated in Parser.declarationValue. Most
|
||||
// changes here should be mirrored there.
|
||||
// NOTE: this logic is largely duplicated in Parser.declarationValue and
|
||||
// isIdentifier in utils.dart. Most changes here should be mirrored there.
|
||||
|
||||
var start = scanner.state;
|
||||
var buffer = InterpolationBuffer();
|
||||
@ -3088,6 +3214,20 @@ relase. For details, see http://bit.ly/moz-document.
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Like [identifier], but rejects identifiers that begin with `_` or `-`.
|
||||
String _publicIdentifier() {
|
||||
var start = scanner.state;
|
||||
var result = identifier();
|
||||
|
||||
var first = result.codeUnitAt(0);
|
||||
if (first == $dash || first == $underscore) {
|
||||
error("Private members can't be accessed from outside their modules.",
|
||||
scanner.spanFrom(start));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ## Abstract Methods
|
||||
|
||||
/// Whether this is parsing the indented syntax.
|
||||
|
@ -290,7 +290,9 @@ class _EvaluateVisitor
|
||||
deprecation: true);
|
||||
|
||||
var expression = FunctionExpression(
|
||||
Interpolation([function.text], _callableNode.span), invocation);
|
||||
Interpolation([function.text], _callableNode.span),
|
||||
invocation,
|
||||
_callableNode.span);
|
||||
return await expression.accept(this);
|
||||
}
|
||||
|
||||
@ -1130,6 +1132,10 @@ class _EvaluateVisitor
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<Value> visitUseRule(UseRule node) async {
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<Value> visitWarnRule(WarnRule node) async {
|
||||
var value =
|
||||
await _addExceptionSpanAsync(node, () => node.expression.accept(this));
|
||||
|
@ -5,7 +5,7 @@
|
||||
// DO NOT EDIT. This file was generated from async_evaluate.dart.
|
||||
// See tool/synchronize.dart for details.
|
||||
//
|
||||
// Checksum: 262c642b0cda0a5ed4984e763e9970422405efaa
|
||||
// Checksum: 08c3aaa09f3be71dd315bf36665e249983ce3d53
|
||||
//
|
||||
// ignore_for_file: unused_import
|
||||
|
||||
@ -297,7 +297,9 @@ class _EvaluateVisitor
|
||||
deprecation: true);
|
||||
|
||||
var expression = FunctionExpression(
|
||||
Interpolation([function.text], _callableNode.span), invocation);
|
||||
Interpolation([function.text], _callableNode.span),
|
||||
invocation,
|
||||
_callableNode.span);
|
||||
return expression.accept(this);
|
||||
}
|
||||
|
||||
@ -1125,6 +1127,10 @@ class _EvaluateVisitor
|
||||
return null;
|
||||
}
|
||||
|
||||
Value visitUseRule(UseRule node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Value visitWarnRule(WarnRule node) {
|
||||
var value = _addExceptionSpan(node, () => node.expression.accept(this));
|
||||
_logger.warn(
|
||||
|
@ -28,6 +28,10 @@ class _FindImportsVisitor extends RecursiveStatementVisitor {
|
||||
void visitInterpolation(Interpolation interpolation) {}
|
||||
void visitSupportsCondition(SupportsCondition condition) {}
|
||||
|
||||
void visitUseRule(UseRule node) {
|
||||
_imports.add(DynamicImport(node.url.toString(), node.span));
|
||||
}
|
||||
|
||||
void visitImportRule(ImportRule node) {
|
||||
for (var import in node.imports) {
|
||||
if (import is DynamicImport) _imports.add(import);
|
||||
|
@ -30,6 +30,7 @@ abstract class StatementVisitor<T> {
|
||||
T visitStyleRule(StyleRule node);
|
||||
T visitStylesheet(Stylesheet node);
|
||||
T visitSupportsRule(SupportsRule node);
|
||||
T visitUseRule(UseRule node);
|
||||
T visitVariableDeclaration(VariableDeclaration node);
|
||||
T visitWarnRule(WarnRule node);
|
||||
T visitWhileRule(WhileRule node);
|
||||
|
Loading…
Reference in New Issue
Block a user