Properly indicate the error location in the REPL

Previously, errors in variable assignment lines would be reported
incorrectly.
This commit is contained in:
Natalie Weizenbaum 2019-07-16 01:35:37 +01:00
parent 83cf390406
commit 7b3a2adc12
3 changed files with 31 additions and 5 deletions

View File

@ -12,6 +12,7 @@ import '../ast/sass.dart';
import '../exception.dart';
import '../executable/options.dart';
import '../logger/tracking.dart';
import '../parse/parser.dart';
import '../value.dart' as internal;
import '../visitor/evaluate.dart';
@ -23,14 +24,12 @@ Future<void> repl(ExecutableOptions options) async {
if (line.trim().isEmpty) continue;
var logger = TrackingLogger(options.logger);
try {
Expression expression;
VariableDeclaration declaration;
try {
Expression expression;
if (Parser.isVariableDeclarationLike(line)) {
declaration = VariableDeclaration.parse(line, logger: logger);
expression = declaration.expression;
} on SassFormatException {
// TODO(nweiz): If [line] looks like a variable assignment, rethrow the
// original exception.
} else {
expression = Expression.parse(line, logger: logger);
}

View File

@ -41,6 +41,12 @@ class Parser {
}
}
/// Returns whether [text] starts like a variable declaration.
///
/// Ignores everything after the `:`.
static bool isVariableDeclarationLike(String text, {Logger logger}) =>
Parser(text, logger: logger)._isVariableDeclarationLike();
@protected
Parser(String contents, {url, Logger logger})
: scanner = SpanScanner(contents, sourceUrl: url),
@ -54,6 +60,14 @@ class Parser {
});
}
bool _isVariableDeclarationLike() {
if (!scanner.scanChar($dollar)) return false;
if (!lookingAtIdentifier()) return false;
identifier();
whitespace();
return scanner.scanChar($colon);
}
// ## Tokens
/// Consumes whitespace, including any comments.

View File

@ -89,6 +89,19 @@ void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
await sass.kill();
});
test("a parse error in a variable declaration", () async {
var sass = await runSass(["--interactive"]);
sass.stdin.writeln("\$foo: 1 + 2;");
await expectLater(
sass.stdout,
emitsInOrder([
">> \$foo: 1 + 2;",
" ^",
"Error: expected no more input."
]));
await sass.kill();
});
test("a parse error after the end of the input", () async {
var sass = await runSass(["--interactive"]);
sass.stdin.writeln("foo(");