Add featureSet parameter to Parser constructor.

And deprecate old parser configuration setters.

Change-Id: Ib1507b8d2b20be7c883061e2a92ec9205d6a378f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/100664
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Dan Rubel <danrubel@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Paul Berry 2019-04-29 16:42:19 +00:00 committed by commit-bot@chromium.org
parent b378eef54a
commit e2d0f5a50b
25 changed files with 132 additions and 94 deletions

View file

@ -67,12 +67,14 @@ class CompilationUnitParser {
var reader = new CharSequenceReader(contents);
var stringSource = new StringSource(contents, name);
var errorListener = new _ErrorListener();
var featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
var scanner = new Scanner(stringSource, reader, errorListener)
..configureFeatures(FeatureSet.forTesting(sdkVersion: '2.2.2'));
..configureFeatures(featureSet);
var startToken = scanner.tokenize();
errorListener.throwIfErrors();
var parser = new Parser(stringSource, errorListener);
var parser =
new Parser(stringSource, errorListener, featureSet: featureSet);
var cu = parser.parseCompilationUnit(startToken);
errorListener.throwIfErrors();

View file

@ -3,6 +3,10 @@
method will be changed so that all its parameters are named parameters.
Clients wishing to prepare for this should switch to using
`AstFactory.compilationUnit2`.
* Deprecated Parser setters `enableControlFlowCollections`, `enableNonNullable`,
`enableSpreadCollections`, and `enableTripleShift`, as well as the
recently-introduced method `configureFeatures`. Parsers should now be
configured by passing a FeatureSet object to the Parser constructor.
## 0.36.2
* Bug fixes: #36724.

View file

@ -102,8 +102,7 @@ CompilationUnit parseDirectives(String contents,
var scanner = new Scanner(source, reader, errorCollector)
..configureFeatures(featureSet);
var token = scanner.tokenize();
var parser = new Parser(source, errorCollector)
..configureFeatures(featureSet);
var parser = new Parser(source, errorCollector, featureSet: featureSet);
var unit = parser.parseDirectives(token);
unit.lineInfo = new LineInfo(scanner.lineStarts);
@ -125,9 +124,8 @@ CompilationUnit _parseSource(
var scanner = new Scanner(source, reader, errorCollector)
..configureFeatures(featureSet);
var token = scanner.tokenize();
var parser = new Parser(source, errorCollector)
..parseFunctionBodies = parseFunctionBodies
..configureFeatures(featureSet);
var parser = new Parser(source, errorCollector, featureSet: featureSet)
..parseFunctionBodies = parseFunctionBodies;
var unit = parser.parseCompilationUnit(token)
..lineInfo = new LineInfo(scanner.lineStarts);

View file

@ -718,8 +718,8 @@ class FileState {
LineInfo lineInfo = new LineInfo(scanner.lineStarts);
bool useFasta = analysisOptions.useFastaParser;
Parser parser = new Parser(source, errorListener, useFasta: useFasta)
..configureFeatures(featureSet);
Parser parser = new Parser(source, errorListener,
featureSet: featureSet, useFasta: useFasta);
parser.enableOptionalNewAndConst = true;
CompilationUnit unit = parser.parseCompilationUnit(token);
unit.lineInfo = lineInfo;

View file

@ -417,8 +417,7 @@ class SdkPatcher {
Token token = scanner.tokenize();
LineInfo lineInfo = new LineInfo(scanner.lineStarts);
Parser parser = new Parser(source, errorListener)
..configureFeatures(featureSet);
Parser parser = new Parser(source, errorListener, featureSet: featureSet);
CompilationUnit unit = parser.parseCompilationUnit(token);
unit.lineInfo = lineInfo;
return unit;

View file

@ -904,8 +904,7 @@ class SdkLibrariesReader {
Scanner scanner = new Scanner(
source, new CharSequenceReader(libraryFileContents), errorListener)
..configureFeatures(featureSet);
Parser parser = new Parser(source, errorListener)
..configureFeatures(featureSet);
Parser parser = new Parser(source, errorListener, featureSet: featureSet);
CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
SdkLibrariesReader_LibraryBuilder libraryBuilder =
new SdkLibrariesReader_LibraryBuilder(_useDart2jsPaths);

View file

@ -291,7 +291,7 @@ class AstBuilder extends StackListener {
/// TODO(paulberry): stop exposing `enableNonNullable`,
/// `enableSpreadCollections`, `enableControlFlowCollections`, and
/// `enableTripleShift` so that callers are forced to use this API. Note that
/// this would be a breaking change.
/// this will not be a breaking change, because this code is in `lib/src`.
void configureFeatures(FeatureSet featureSet) {
enableNonNullable = featureSet.isEnabled(Feature.non_nullable);
enableSpreadCollections = featureSet.isEnabled(Feature.spread_collections);

View file

@ -199,16 +199,33 @@ class Parser {
/// Initialize a newly created parser to parse tokens in the given [_source]
/// and to report any errors that are found to the given [_errorListener].
///
/// In a future major version release of the analyzer, the [featureSet]
/// argument will be required.
factory Parser(Source source, AnalysisErrorListener errorListener,
{bool useFasta}) {
{bool useFasta, FeatureSet featureSet}) {
if (useFasta ?? Parser.useFasta) {
return new _Parser2(source, errorListener, allowNativeClause: true);
var parser = new _Parser2(source, errorListener, allowNativeClause: true);
if (featureSet != null) {
parser.configureFeatures(featureSet);
}
return parser;
} else {
return new Parser.withoutFasta(source, errorListener);
return new Parser.withoutFasta(source, errorListener,
featureSet: featureSet);
}
}
Parser.withoutFasta(this._source, this._errorListener);
/// Creates a parser using the old (legacy) analyzer parsing logic.
///
/// In a future major version release of the analyzer, the [featureSet]
/// argument will be required.
Parser.withoutFasta(this._source, this._errorListener,
{FeatureSet featureSet}) {
if (featureSet != null) {
_configureFeatures(featureSet);
}
}
/// Return the current token.
Token get currentToken => _currentToken;
@ -229,6 +246,7 @@ class Parser {
void set enableAssertInitializer(bool enable) {}
/// Enables or disables parsing of control flow collections.
@Deprecated('Pass a FeatureSet to the constructor instead')
void set enableControlFlowCollections(bool value) {
if (value) {
throw new UnimplementedError('control_flow_collections experiment'
@ -237,6 +255,7 @@ class Parser {
}
/// Enables or disables non-nullable by default.
@Deprecated('Pass a FeatureSet to the constructor instead')
void set enableNonNullable(bool value) {
if (value) {
throw new UnimplementedError(
@ -261,6 +280,7 @@ class Parser {
}
/// Enables or disables parsing of spread collections.
@Deprecated('Pass a FeatureSet to the constructor instead')
void set enableSpreadCollections(bool value) {
if (value) {
throw new UnimplementedError(
@ -269,6 +289,7 @@ class Parser {
}
/// Enables or disables parsing of the triple shift operators.
@Deprecated('Pass a FeatureSet to the constructor instead')
void set enableTripleShift(bool value) {
if (value) {
throw new UnimplementedError('triple_shift experiment'
@ -343,29 +364,9 @@ class Parser {
}
/// Configures the parser appropriately for the given [featureSet].
///
/// TODO(paulberry): stop exposing `enableNonNullable`,
/// `enableSpreadCollections`, `enableControlFlowCollections`, and
/// `enableTripleShift` so that callers are forced to use this API. Note that
/// this would be a breaking change.
@Deprecated('Pass a FeatureSet to the constructor instead')
void configureFeatures(FeatureSet featureSet) {
if (featureSet.isEnabled(Feature.control_flow_collections)) {
throw new UnimplementedError('control_flow_collections experiment'
' not supported by analyzer parser');
}
if (featureSet.isEnabled(Feature.non_nullable)) {
throw new UnimplementedError(
'non-nullable experiment not supported by analyzer parser');
}
if (featureSet.isEnabled(Feature.spread_collections)) {
throw new UnimplementedError(
'spread_collections experiment not supported by analyzer parser');
}
if (featureSet.isEnabled(Feature.triple_shift)) {
throw new UnimplementedError('triple_shift experiment'
' not supported by analyzer parser');
}
_featureSet = featureSet;
_configureFeatures(featureSet);
}
/// Return a synthetic identifier.
@ -5595,6 +5596,26 @@ class Parser {
return false;
}
void _configureFeatures(FeatureSet featureSet) {
if (featureSet.isEnabled(Feature.control_flow_collections)) {
throw new UnimplementedError('control_flow_collections experiment'
' not supported by analyzer parser');
}
if (featureSet.isEnabled(Feature.non_nullable)) {
throw new UnimplementedError(
'non-nullable experiment not supported by analyzer parser');
}
if (featureSet.isEnabled(Feature.spread_collections)) {
throw new UnimplementedError(
'spread_collections experiment not supported by analyzer parser');
}
if (featureSet.isEnabled(Feature.triple_shift)) {
throw new UnimplementedError('triple_shift experiment'
' not supported by analyzer parser');
}
_featureSet = featureSet;
}
/// Convert the given [method] declaration into the nearest valid top-level
/// function declaration (that is, the function declaration that most closely
/// captures the components of the given method declaration).

View file

@ -284,8 +284,7 @@ class SdkLibrariesReader {
Scanner scanner = new Scanner(
source, new CharSequenceReader(libraryFileContents), errorListener)
..configureFeatures(featureSet);
Parser parser = new Parser(source, errorListener)
..configureFeatures(featureSet);
Parser parser = new Parser(source, errorListener, featureSet: featureSet);
CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
SdkLibrariesReader_LibraryBuilder libraryBuilder =
new SdkLibrariesReader_LibraryBuilder(_useDart2jsPaths);

View file

@ -90,6 +90,7 @@ bool isUpperCase(int c) => c >= 0x40 && c <= 0x5A;
class Spelunker {
final String path;
final IOSink sink;
Spelunker(this.path, {IOSink sink}) : this.sink = sink ?? stdout;
void spelunk() {
@ -107,8 +108,8 @@ class Spelunker {
errorListener.throwIfErrors();
var parser = new Parser(stringSource, errorListener)
..configureFeatures(featureSet);
var parser =
new Parser(stringSource, errorListener, featureSet: featureSet);
var node = parser.parseCompilationUnit(startToken);
errorListener.throwIfErrors();
@ -137,6 +138,7 @@ class _SourceVisitor extends GeneralizingAstVisitor {
int indent = 0;
final IOSink sink;
_SourceVisitor(this.sink);
String asString(AstNode node) =>

View file

@ -1622,8 +1622,8 @@ class _File {
..configureFeatures(featureSet);
var token = scanner.tokenize();
var parser = new Parser(source, errorListener, useFasta: true)
..configureFeatures(featureSet);
var parser = new Parser(source, errorListener,
featureSet: featureSet, useFasta: true);
var unit = parser.parseCompilationUnit(token);
unit.lineInfo = LineInfo(scanner.lineStarts);

View file

@ -137,9 +137,9 @@ class _Builder {
Token token = scanner.tokenize();
LineInfo lineInfo = new LineInfo(scanner.lineStarts);
Parser parser = new Parser(source, errorListener,
featureSet: featureSet,
useFasta: context.analysisOptions.useFastaParser);
parser.enableOptionalNewAndConst = true;
parser.configureFeatures(featureSet);
CompilationUnit unit = parser.parseCompilationUnit(token);
unit.lineInfo = lineInfo;
return unit;

View file

@ -1,5 +1,5 @@
name: analyzer
version: 0.36.2
version: 0.36.3-dev
author: Dart Team <misc@dartlang.org>
description: Static analyzer for Dart.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer

View file

@ -629,8 +629,9 @@ E f() => g;
var scanner = new Scanner.fasta(source, listener)
..configureFeatures(featureSet);
Token tokens = scanner.tokenize();
_unit = new Parser(source, listener, useFasta: true)
.parseCompilationUnit(tokens);
_unit =
new Parser(source, listener, featureSet: featureSet, useFasta: true)
.parseCompilationUnit(tokens);
}
return _unit;
}

View file

@ -1520,10 +1520,9 @@ class FastaParserTestCase
scanner.enableNonNullable = featureSet.isEnabled(Feature.non_nullable);
}
_fastaTokens = scanner.tokenize();
_parserProxy = new ParserProxy(_fastaTokens,
_parserProxy = new ParserProxy(_fastaTokens, featureSet,
allowNativeClause: allowNativeClause,
expectedEndOffset: expectedEndOffset,
featureSet: featureSet);
expectedEndOffset: expectedEndOffset);
}
@override
@ -1667,13 +1666,11 @@ class FastaParserTestCase
// Run parser
ErrorReporter errorReporter = new ErrorReporter(listener, source);
fasta.Parser parser = new fasta.Parser(null);
AstBuilder astBuilder = new AstBuilder(errorReporter, source.uri, true);
AstBuilder astBuilder = new AstBuilder(errorReporter, source.uri, true)
..configureFeatures(featureSet);
parser.listener = astBuilder;
astBuilder.parser = parser;
astBuilder.allowNativeClause = allowNativeClause;
if (featureSet != null) {
astBuilder.configureFeatures(featureSet);
}
parser.parseUnit(_fastaTokens);
CompilationUnitImpl unit = astBuilder.pop();
unit.localDeclarations = astBuilder.localDeclarations;
@ -2488,26 +2485,23 @@ class ParserProxy extends analyzer.ParserAdapter {
* Creates a [ParserProxy] which is prepared to begin parsing at the given
* Fasta token.
*/
factory ParserProxy(analyzer.Token firstToken,
{bool allowNativeClause: false,
int expectedEndOffset,
FeatureSet featureSet}) {
factory ParserProxy(analyzer.Token firstToken, FeatureSet featureSet,
{bool allowNativeClause: false, int expectedEndOffset}) {
TestSource source = new TestSource();
var errorListener = new GatheringErrorListener(checkRanges: true);
var errorReporter = new ErrorReporter(errorListener, source);
return new ParserProxy._(firstToken, errorReporter, null, errorListener,
return new ParserProxy._(
firstToken, errorReporter, null, errorListener, featureSet,
allowNativeClause: allowNativeClause,
expectedEndOffset: expectedEndOffset,
featureSet: featureSet);
expectedEndOffset: expectedEndOffset);
}
ParserProxy._(analyzer.Token firstToken, ErrorReporter errorReporter,
Uri fileUri, this._errorListener,
{bool allowNativeClause: false,
this.expectedEndOffset,
FeatureSet featureSet})
Uri fileUri, this._errorListener, FeatureSet featureSet,
{bool allowNativeClause: false, this.expectedEndOffset})
: super(firstToken, errorReporter, fileUri,
allowNativeClause: allowNativeClause, featureSet: featureSet) {
allowNativeClause: allowNativeClause) {
configureFeatures(featureSet);
_eventListener = new ForwardingTestListener(astBuilder);
fastaParser.listener = _eventListener;
}

View file

@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/dart/ast/token.dart';
@ -9429,7 +9430,7 @@ class ParserTestCase extends EngineTestCase
//
// Create and initialize the parser.
//
parser = new Parser(source, listener);
parser = new Parser(source, listener, featureSet: FeatureSet.forTesting());
parser.allowNativeClause = allowNativeClause;
parser.parseFunctionBodies = parseFunctionBodies;
parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
@ -9577,7 +9578,8 @@ class ParserTestCase extends EngineTestCase
}
listener.setLineInfo(source, result.lineStarts);
Parser parser = new Parser(source, listener);
Parser parser =
new Parser(source, listener, featureSet: FeatureSet.forTesting());
parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
CompilationUnit unit = parser.parseCompilationUnit(token);
expect(unit, isNotNull);
@ -9621,7 +9623,8 @@ class ParserTestCase extends EngineTestCase
}
}
Parser parser = new Parser(source, listener);
Parser parser =
new Parser(source, listener, featureSet: FeatureSet.forTesting());
parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
CompilationUnit unit = parser.parseCompilationUnit(token);
unit.lineInfo = new LineInfo(result.lineStarts);
@ -9978,7 +9981,8 @@ class ParserTestCase extends EngineTestCase
}
listener.setLineInfo(source, result.lineStarts);
Parser parser = new Parser(source, listener);
Parser parser =
new Parser(source, listener, featureSet: FeatureSet.forTesting());
parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
Statement statement = parser.parseStatement(token);
expect(statement, isNotNull);
@ -10023,7 +10027,8 @@ class ParserTestCase extends EngineTestCase
}
listener.setLineInfo(source, result.lineStarts);
Parser parser = new Parser(source, listener);
Parser parser =
new Parser(source, listener, featureSet: FeatureSet.forTesting());
parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
List<Statement> statements = parser.parseStatements(token);
expect(statements, hasLength(expectedCount));
@ -12420,7 +12425,10 @@ class SimpleParserTest extends ParserTestCase with SimpleParserTestMixin {
}
void test_Parser() {
expect(new Parser(NonExistingSource.unknown, null), isNotNull);
expect(
new Parser(NonExistingSource.unknown, null,
featureSet: FeatureSet.forTesting()),
isNotNull);
}
void test_skipPrefixedIdentifier_invalid() {

View file

@ -1186,10 +1186,12 @@ library l;''');
CompilationUnit _parseUnit(String code) {
GatheringErrorListener listener = new GatheringErrorListener();
CharSequenceReader reader = new CharSequenceReader(code);
var featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
Scanner scanner = new Scanner(null, reader, listener)
..configureFeatures(FeatureSet.forTesting(sdkVersion: '2.2.2'));
..configureFeatures(featureSet);
Token token = scanner.tokenize();
Parser parser = new Parser(NonExistingSource.unknown, listener);
Parser parser =
new Parser(NonExistingSource.unknown, listener, featureSet: featureSet);
CompilationUnit unit = parser.parseCompilationUnit(token);
expect(unit, isNotNull);
listener.assertNoErrors();

View file

@ -33,9 +33,9 @@ class ParseBase with ResourceProviderMixin {
var token = scanner.tokenize();
var useFasta = analysisOptions.useFastaParser;
var parser = Parser(source, errorListener, useFasta: useFasta);
var parser = Parser(source, errorListener,
featureSet: featureSet, useFasta: useFasta);
parser.enableOptionalNewAndConst = true;
parser.configureFeatures(featureSet);
var unit = parser.parseCompilationUnit(token);
unit.lineInfo = LineInfo(scanner.lineStarts);

View file

@ -896,8 +896,8 @@ class TokensToStringTest {
var scanner = new Scanner(stringSource, reader, errorListener)
..configureFeatures(featureSet);
var startToken = scanner.tokenize();
var parser = new Parser(stringSource, errorListener)
..configureFeatures(featureSet);
var parser =
new Parser(stringSource, errorListener, featureSet: featureSet);
var compilationUnit = parser.parseCompilationUnit(startToken);
var f = compilationUnit.declarations[0] as FunctionDeclaration;
var body = f.functionExpression.body as ExpressionFunctionBody;

View file

@ -66,8 +66,8 @@ UnlinkedPublicNamespace computePublicNamespaceFromText(
Scanner scanner =
new Scanner(source, reader, AnalysisErrorListener.NULL_LISTENER)
..configureFeatures(featureSet);
Parser parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER)
..configureFeatures(featureSet);
Parser parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER,
featureSet: featureSet);
CompilationUnit unit = parser.parseCompilationUnit(scanner.tokenize());
UnlinkedPublicNamespace namespace = new UnlinkedPublicNamespace.fromBuffer(
public_namespace.computePublicNamespace(unit).toBuffer());
@ -11948,8 +11948,8 @@ final v = $expr;
var scanner = new Scanner(stringSource, reader, errorListener)
..configureFeatures(experimentStatus);
var startToken = scanner.tokenize();
var parser = new Parser(stringSource, errorListener)
..configureFeatures(experimentStatus);
var parser =
new Parser(stringSource, errorListener, featureSet: experimentStatus);
var compilationUnit = parser.parseCompilationUnit(startToken);
var f = compilationUnit.declarations[0] as FunctionDeclaration;
var body = f.functionExpression.body as ExpressionFunctionBody;

View file

@ -44,9 +44,9 @@ CompilationUnit parseText(
new Scanner(null, reader, AnalysisErrorListener.NULL_LISTENER)
..configureFeatures(experimentStatus);
Token token = scanner.tokenize();
Parser parser =
new Parser(NonExistingSource.unknown, AnalysisErrorListener.NULL_LISTENER)
..configureFeatures(experimentStatus);
Parser parser = new Parser(
NonExistingSource.unknown, AnalysisErrorListener.NULL_LISTENER,
featureSet: experimentStatus);
CompilationUnit unit = parser.parseCompilationUnit(token);
unit.lineInfo = new LineInfo(scanner.lineStarts);
return unit;

View file

@ -78,7 +78,9 @@ void collectSources(Source start, Set<Source> files) {
/// Uses the diet-parser to parse only directives in [source].
CompilationUnit parseDirectives(Source source) {
var token = tokenize(source);
var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER);
var featureSet = FeatureSet.fromEnableFlags([]);
var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER,
featureSet: featureSet);
return parser.parseDirectives(token);
}
@ -108,7 +110,9 @@ void parseFiles(Set<Source> files) {
/// Parse the full body of [source] and return it's compilation unit.
CompilationUnit parseFull(Source source) {
var token = tokenize(source);
var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER);
var featureSet = FeatureSet.fromEnableFlags([]);
var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER,
featureSet: featureSet);
return parser.parseCompilationUnit(token);
}

View file

@ -30,7 +30,7 @@ class LocalDeclarationVisitorTest {
..configureFeatures(featureSet);
Token token = scanner.tokenize();
var source = new StringSource(content, '/test.dart');
Parser parser = new Parser(source, listener)..configureFeatures(featureSet);
Parser parser = new Parser(source, listener, featureSet: featureSet);
CompilationUnit unit = parser.parseCompilationUnit(token);
expect(unit, isNotNull);
return unit;

View file

@ -35,7 +35,7 @@ class CompletionTargetTest {
..configureFeatures(featureSet);
final source = new StringSource(code, 'test.dart');
final listener = new _ErrorCollector();
final parser = new Parser(source, listener)..configureFeatures(featureSet);
final parser = new Parser(source, listener, featureSet: featureSet);
return parser.parseExpression(scanner.tokenize());
}

View file

@ -18,6 +18,7 @@ library front_end.tool.perf;
import 'dart:async';
import 'dart:io' show Directory, File, Platform, exit;
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/physical_file_system.dart'
@ -100,7 +101,9 @@ void collectSources(Source start, Set<Source> files) {
/// Uses the diet-parser to parse only directives in [source].
CompilationUnit parseDirectives(Source source) {
var token = tokenize(source);
var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER);
var featureSet = FeatureSet.fromEnableFlags([]);
var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER,
featureSet: featureSet);
return parser.parseDirectives(token);
}
@ -120,7 +123,9 @@ void parseFiles(Set<Source> files) {
CompilationUnit parseFull(Source source) {
var token = tokenize(source);
parseTimer.start();
var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER);
var featureSet = FeatureSet.fromEnableFlags([]);
var parser = new Parser(source, AnalysisErrorListener.NULL_LISTENER,
featureSet: featureSet);
var unit = parser.parseCompilationUnit(token);
parseTimer.stop();
return unit;