Add scanner languageVersionChanged callback
Change-Id: I64835e303efd83ac1f7cb0015407be8c196a5249
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/100925
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Dan Rubel <danrubel@google.com>
diff --git a/pkg/front_end/lib/src/fasta/scanner.dart b/pkg/front_end/lib/src/fasta/scanner.dart
index a6e262a..f9f1741 100644
--- a/pkg/front_end/lib/src/fasta/scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner.dart
@@ -8,7 +8,8 @@
import '../scanner/token.dart' show Token;
-import 'scanner/abstract_scanner.dart' show ScannerConfiguration;
+import 'scanner/abstract_scanner.dart'
+ show LanguageVersionChanged, ScannerConfiguration;
import 'scanner/string_scanner.dart' show StringScanner;
@@ -18,7 +19,8 @@
import 'scanner/recover.dart' show defaultRecoveryStrategy;
-export 'scanner/abstract_scanner.dart' show ScannerConfiguration;
+export 'scanner/abstract_scanner.dart'
+ show LanguageVersionChanged, ScannerConfiguration;
export 'scanner/token.dart'
show
@@ -33,6 +35,8 @@
export 'scanner/error_token.dart'
show ErrorToken, buildUnexpectedCharacterToken;
+export 'scanner/token.dart' show LanguageVersionToken;
+
export 'scanner/token_constants.dart' show EOF_TOKEN;
export 'scanner/utf8_bytes_scanner.dart' show Utf8BytesScanner;
@@ -55,6 +59,9 @@
List<int> get lineStarts;
+ /// Configure which tokens are produced.
+ set configuration(ScannerConfiguration config);
+
Token tokenize();
}
@@ -71,14 +78,17 @@
/// Scan/tokenize the given UTF8 [bytes].
/// If [recover] is null, then the [defaultRecoveryStrategy] is used.
ScannerResult scan(List<int> bytes,
- {bool includeComments: false,
- ScannerConfiguration configuration,
+ {ScannerConfiguration configuration,
+ bool includeComments: false,
+ LanguageVersionChanged languageVersionChanged,
Recover recover}) {
if (bytes.last != 0) {
throw new ArgumentError("[bytes]: the last byte must be null.");
}
Scanner scanner = new Utf8BytesScanner(bytes,
- configuration: configuration, includeComments: includeComments);
+ configuration: configuration,
+ includeComments: includeComments,
+ languageVersionChanged: languageVersionChanged);
return _tokenizeAndRecover(scanner, recover, bytes: bytes);
}
@@ -87,11 +97,14 @@
ScannerResult scanString(String source,
{ScannerConfiguration configuration,
bool includeComments: false,
+ LanguageVersionChanged languageVersionChanged,
bool scanLazyAssignmentOperators: false,
Recover recover}) {
assert(source != null, 'source must not be null');
StringScanner scanner = new StringScanner(source,
- configuration: configuration, includeComments: includeComments);
+ configuration: configuration,
+ includeComments: includeComments,
+ languageVersionChanged: languageVersionChanged);
return _tokenizeAndRecover(scanner, recover, source: source);
}
diff --git a/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
index fd29cd4..79ba63d 100644
--- a/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
@@ -32,6 +32,9 @@
import 'characters.dart';
+typedef void LanguageVersionChanged(
+ Scanner scanner, LanguageVersionToken languageVersion);
+
abstract class AbstractScanner implements Scanner {
/**
* A flag indicating whether character sequences `&&=` and `||=`
@@ -43,6 +46,11 @@
final bool includeComments;
+ /// Called when the scanner detects a language version comment
+ /// so that the listener can update the scanner configuration
+ /// based upon the specified language version.
+ final LanguageVersionChanged languageVersionChanged;
+
/// Experimental flag for enabling scanning of `>>>`.
/// See https://github.com/dart-lang/language/issues/61
/// and https://github.com/dart-lang/language/issues/60
@@ -98,15 +106,14 @@
final List<int> lineStarts;
AbstractScanner(ScannerConfiguration config, this.includeComments,
+ this.languageVersionChanged,
{int numberOfBytesHint})
: lineStarts = new LineStarts(numberOfBytesHint) {
this.tail = this.tokens;
this.configuration = config;
}
- /**
- * Configure which tokens are produced.
- */
+ @override
set configuration(ScannerConfiguration config) {
if (config != null) {
_enableNonNullable = config.enableNonNullable;
@@ -320,7 +327,7 @@
}
int bigHeaderSwitch(int next) {
- if (languageVersion != null || !identical(next, $SLASH)) {
+ if (!identical(next, $SLASH)) {
return bigSwitch(next);
}
beginToken();
@@ -970,7 +977,14 @@
}
languageVersion = createLanguageVersionToken(start, major, minor);
- configuration = ScannerConfiguration.from(languageVersion);
+ if (languageVersionChanged != null) {
+ // TODO(danrubel): make this required and remove the languageVersion field
+ languageVersionChanged(this, languageVersion);
+ } else {
+ // TODO(danrubel): remove this hack and require listener to update
+ // the scanner's configuration.
+ configuration = ScannerConfiguration.classic;
+ }
if (includeComments) {
_appendToCommentStream(languageVersion);
}
@@ -1528,12 +1542,6 @@
static const classic = ScannerConfiguration();
static const nonNullable = ScannerConfiguration(enableNonNullable: true);
- /// Return the scanner configuration for the given language version.
- static ScannerConfiguration from(LanguageVersionToken languageVersion) {
- // TODO(danrubel): update this to return config for new releases
- return classic;
- }
-
/// Experimental flag for enabling scanning of NNBD tokens
/// such as 'required' and 'late'
final bool enableNonNullable;
diff --git a/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
index 66e7e39..22df483 100644
--- a/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart
@@ -21,7 +21,11 @@
import 'characters.dart' show $LF, $STX;
import 'abstract_scanner.dart'
- show AbstractScanner, ScannerConfiguration, closeBraceInfoFor;
+ show
+ AbstractScanner,
+ LanguageVersionChanged,
+ ScannerConfiguration,
+ closeBraceInfoFor;
import '../util/link.dart' show Link;
@@ -29,8 +33,9 @@
bool hasErrors = false;
ArrayBasedScanner(ScannerConfiguration config, bool includeComments,
- {int numberOfBytesHint})
- : super(config, includeComments, numberOfBytesHint: numberOfBytesHint);
+ LanguageVersionChanged languageVersionChanged, {int numberOfBytesHint})
+ : super(config, includeComments, languageVersionChanged,
+ numberOfBytesHint: numberOfBytesHint);
/**
* The stack of open groups, e.g [: { ... ( .. :]
diff --git a/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
index 2b5c472..7fa5203 100644
--- a/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
@@ -8,7 +8,8 @@
import '../../scanner/token.dart' as analyzer show StringToken;
-import 'abstract_scanner.dart' show ScannerConfiguration;
+import 'abstract_scanner.dart'
+ show LanguageVersionChanged, ScannerConfiguration;
import 'array_based_scanner.dart' show ArrayBasedScanner;
@@ -29,9 +30,11 @@
int scanOffset = -1;
StringScanner(String string,
- {ScannerConfiguration configuration, bool includeComments: false})
+ {ScannerConfiguration configuration,
+ bool includeComments: false,
+ LanguageVersionChanged languageVersionChanged})
: string = ensureZeroTermination(string),
- super(configuration, includeComments);
+ super(configuration, includeComments, languageVersionChanged);
static String ensureZeroTermination(String string) {
return (string.isEmpty || string.codeUnitAt(string.length - 1) != 0)
diff --git a/pkg/front_end/lib/src/fasta/scanner/utf8_bytes_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/utf8_bytes_scanner.dart
index 9aabe30..e847390 100644
--- a/pkg/front_end/lib/src/fasta/scanner/utf8_bytes_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/utf8_bytes_scanner.dart
@@ -12,7 +12,8 @@
import '../scanner.dart' show unicodeReplacementCharacter;
-import 'abstract_scanner.dart' show ScannerConfiguration;
+import 'abstract_scanner.dart'
+ show LanguageVersionChanged, ScannerConfiguration;
import 'token.dart'
show CommentToken, DartDocToken, LanguageVersionToken, StringToken;
@@ -85,8 +86,11 @@
* is not the case, the entire array is copied before scanning.
*/
Utf8BytesScanner(this.bytes,
- {ScannerConfiguration configuration, bool includeComments: false})
- : super(configuration, includeComments, numberOfBytesHint: bytes.length) {
+ {ScannerConfiguration configuration,
+ bool includeComments: false,
+ LanguageVersionChanged languageVersionChanged})
+ : super(configuration, includeComments, languageVersionChanged,
+ numberOfBytesHint: bytes.length) {
assert(bytes.last == 0);
// Skip a leading BOM.
if (containsBomAt(0)) byteOffset += 3;
diff --git a/pkg/front_end/test/scanner_fasta_test.dart b/pkg/front_end/test/scanner_fasta_test.dart
index d4f785b..914ae8c 100644
--- a/pkg/front_end/test/scanner_fasta_test.dart
+++ b/pkg/front_end/test/scanner_fasta_test.dart
@@ -717,15 +717,26 @@
ScannerResult scanSource(source, {includeComments: true}) {
List<int> encoded = utf8.encode(source).toList(growable: true);
encoded.add(0); // Ensure 0 terminted bytes for UTF8 scanner
- return usedForFuzzTesting.scan(encoded, includeComments: includeComments);
+ return usedForFuzzTesting.scan(encoded,
+ includeComments: includeComments,
+ languageVersionChanged: languageVersionChanged);
}
}
/// Scanner tests that exercise the Fasta scanner directly.
@reflectiveTest
class ScannerTest_Fasta_Direct extends ScannerTest_Fasta_Base {
+ LanguageVersionToken languageVersion;
+
+ void languageVersionChanged(
+ Scanner scanner, LanguageVersionToken languageVersion) {
+ this.languageVersion = languageVersion;
+ }
+
ScannerResult scanSource(source, {includeComments: true}) =>
- scanString(source, includeComments: includeComments);
+ scanString(source,
+ includeComments: includeComments,
+ languageVersionChanged: languageVersionChanged);
@override
Token scan(String source) {