[CFE] Update parser ast and utils
Change-Id: I616b597826903dce4d4b38144eb8b729f5699bbc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/354229
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
diff --git a/pkg/front_end/lib/src/fasta/util/parser_ast.dart b/pkg/front_end/lib/src/fasta/util/parser_ast.dart
index a19dd7a..ae43e2d 100644
--- a/pkg/front_end/lib/src/fasta/util/parser_ast.dart
+++ b/pkg/front_end/lib/src/fasta/util/parser_ast.dart
@@ -410,7 +410,86 @@
MetadataEnd node, Token startInclusive, Token endInclusive) {}
}
+enum MemberContentType {
+ ClassConstructor,
+ ClassFactoryMethod,
+ ClassFields,
+ ClassMethod,
+ ClassRecoverableError,
+ EnumConstructor,
+ EnumFactoryMethod,
+ EnumFields,
+ EnumMethod,
+ ExperimentNotEnabled,
+ ExtensionConstructor,
+ ExtensionFactoryMethod,
+ ExtensionFields,
+ ExtensionMethod,
+ ExtensionTypeConstructor,
+ ExtensionTypeFactoryMethod,
+ ExtensionTypeFields,
+ ExtensionTypeMethod,
+ MixinConstructor,
+ MixinFactoryMethod,
+ MixinFields,
+ MixinMethod,
+ Unknown,
+}
+
+enum GeneralAstContentType {
+ Class,
+ Import,
+ Export,
+ Unknown,
+ Enum,
+ Typedef,
+ Script,
+ Extension,
+ ExtensionType,
+ InvalidTopLevelDeclaration,
+ RecoverableError,
+ RecoverImport,
+ MixinDeclaration,
+ NamedMixinDeclaration,
+ TopLevelMethod,
+ TopLevelFields,
+ LibraryName,
+ Part,
+ PartOf,
+ Metadata,
+ FunctionBody,
+}
+
extension GeneralASTContentExtension on ParserAstNode {
+ GeneralAstContentType getType() {
+ if (isClass()) return GeneralAstContentType.Class;
+ if (isImport()) return GeneralAstContentType.Import;
+ if (isExport()) return GeneralAstContentType.Export;
+ if (isExport()) return GeneralAstContentType.Export;
+ if (isEnum()) return GeneralAstContentType.Enum;
+ if (isTypedef()) return GeneralAstContentType.Typedef;
+ if (isScript()) return GeneralAstContentType.Script;
+ if (isExtension()) return GeneralAstContentType.Extension;
+ if (isExtensionType()) return GeneralAstContentType.ExtensionType;
+ if (isInvalidTopLevelDeclaration()) {
+ return GeneralAstContentType.InvalidTopLevelDeclaration;
+ }
+ if (isRecoverableError()) return GeneralAstContentType.RecoverableError;
+ if (isRecoverImport()) return GeneralAstContentType.RecoverImport;
+ if (isMixinDeclaration()) return GeneralAstContentType.MixinDeclaration;
+ if (isNamedMixinDeclaration()) {
+ return GeneralAstContentType.NamedMixinDeclaration;
+ }
+ if (isTopLevelMethod()) return GeneralAstContentType.TopLevelMethod;
+ if (isTopLevelFields()) return GeneralAstContentType.TopLevelFields;
+ if (isLibraryName()) return GeneralAstContentType.LibraryName;
+ if (isPart()) return GeneralAstContentType.Part;
+ if (isPartOf()) return GeneralAstContentType.PartOf;
+ if (isMetadata()) return GeneralAstContentType.Metadata;
+ if (isFunctionBody()) return GeneralAstContentType.FunctionBody;
+ return GeneralAstContentType.Unknown;
+ }
+
bool isClass() {
if (this is! TopLevelDeclarationEnd) {
return false;
@@ -539,6 +618,25 @@
return children!.last as ExtensionDeclarationEnd;
}
+ bool isExtensionType() {
+ if (this is! TopLevelDeclarationEnd) {
+ return false;
+ }
+ if (children!.first is! ExtensionDeclarationPreludeBegin) {
+ return false;
+ }
+ if (children!.last is! ExtensionTypeDeclarationEnd) {
+ return false;
+ }
+
+ return true;
+ }
+
+ ExtensionTypeDeclarationEnd asExtensionType() {
+ if (!isExtensionType()) throw "Not extension type";
+ return children!.last as ExtensionTypeDeclarationEnd;
+ }
+
bool isInvalidTopLevelDeclaration() {
if (this is! TopLevelDeclarationEnd) {
return false;
@@ -782,6 +880,18 @@
}
}
+extension MetadataExtension on MetadataEnd {
+ List<IdentifierHandle> getIdentifiers() {
+ List<IdentifierHandle> result = [];
+ for (ParserAstNode child in children!) {
+ if (child is IdentifierHandle) {
+ result.add(child);
+ }
+ }
+ return result;
+ }
+}
+
extension CompilationUnitExtension on CompilationUnitEnd {
List<TopLevelDeclarationEnd> getClasses() {
List<TopLevelDeclarationEnd> result = [];
@@ -899,6 +1009,20 @@
}
throw "Not found.";
}
+
+ IdentifierHandle getMixinIdentifier() {
+ ParserAstNode? parent = this.parent;
+ if (parent is! TopLevelDeclarationEnd) throw "Now nested as expected";
+ return parent.getIdentifier();
+ }
+}
+
+extension NamedMixinApplicationExtension on NamedMixinApplicationEnd {
+ IdentifierHandle getMixinIdentifier() {
+ ParserAstNode? parent = this.parent;
+ if (parent is! TopLevelDeclarationEnd) throw "Now nested as expected";
+ return parent.getIdentifier();
+ }
}
extension ClassDeclarationExtension on ClassDeclarationEnd {
@@ -935,6 +1059,12 @@
}
return null;
}
+
+ IdentifierHandle getClassIdentifier() {
+ ParserAstNode? parent = this.parent;
+ if (parent is! TopLevelDeclarationEnd) throw "Now nested as expected";
+ return parent.getIdentifier();
+ }
}
extension ClassOrMixinBodyExtension on ClassOrMixinOrExtensionBodyEnd {
@@ -950,6 +1080,46 @@
}
extension MemberExtension on MemberEnd {
+ MemberContentType getMemberType() {
+ if (isClassConstructor()) return MemberContentType.ClassConstructor;
+ if (isClassFactoryMethod()) return MemberContentType.ClassFactoryMethod;
+ if (isClassFields()) return MemberContentType.ClassFields;
+ if (isClassMethod()) return MemberContentType.ClassMethod;
+
+ if (isMixinConstructor()) return MemberContentType.MixinConstructor;
+ if (isMixinFactoryMethod()) return MemberContentType.MixinFactoryMethod;
+ if (isMixinFields()) return MemberContentType.MixinFields;
+ if (isMixinMethod()) return MemberContentType.MixinMethod;
+
+ if (isExtensionConstructor()) return MemberContentType.ExtensionConstructor;
+ if (isExtensionFactoryMethod()) {
+ return MemberContentType.ExtensionFactoryMethod;
+ }
+ if (isExtensionFields()) return MemberContentType.ExtensionFields;
+ if (isExtensionMethod()) return MemberContentType.ExtensionMethod;
+
+ if (isExtensionTypeConstructor()) {
+ return MemberContentType.ExtensionTypeConstructor;
+ }
+ if (isExtensionTypeFactoryMethod()) {
+ return MemberContentType.ExtensionTypeFactoryMethod;
+ }
+ if (isExtensionTypeFields()) return MemberContentType.ExtensionTypeFields;
+ if (isExtensionTypeMethod()) return MemberContentType.ExtensionTypeMethod;
+
+ if (isEnumConstructor()) return MemberContentType.EnumConstructor;
+ if (isEnumFactoryMethod()) return MemberContentType.EnumFactoryMethod;
+ if (isEnumFields()) return MemberContentType.EnumFields;
+ if (isEnumMethod()) return MemberContentType.EnumMethod;
+
+ if (isClassRecoverableError()) {
+ return MemberContentType.ClassRecoverableError;
+ }
+ if (isExperimentNotEnabled()) return MemberContentType.ExperimentNotEnabled;
+
+ return MemberContentType.Unknown;
+ }
+
bool isClassConstructor() {
ParserAstNode child = children![1];
if (child is ClassConstructorEnd) return true;
@@ -1051,6 +1221,156 @@
if (child is RecoverableErrorHandle) return true;
return false;
}
+
+ bool isExperimentNotEnabled() {
+ ParserAstNode child = children![1];
+ if (child is ExperimentNotEnabledHandle) return true;
+ return false;
+ }
+
+ bool isExtensionMethod() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionMethodEnd) return true;
+ return false;
+ }
+
+ ExtensionMethodEnd getExtensionMethod() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionMethodEnd) return child;
+ throw "Not found";
+ }
+
+ bool isExtensionFields() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionFieldsEnd) return true;
+ return false;
+ }
+
+ ExtensionFieldsEnd getExtensionFields() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionFieldsEnd) return child;
+ throw "Not found";
+ }
+
+ bool isExtensionConstructor() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionConstructorEnd) return true;
+ return false;
+ }
+
+ ExtensionConstructorEnd getExtensionConstructor() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionConstructorEnd) return child;
+ throw "Not found";
+ }
+
+ bool isExtensionFactoryMethod() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionFactoryMethodEnd) return true;
+ return false;
+ }
+
+ ExtensionFactoryMethodEnd getExtensionFactoryMethod() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionFactoryMethodEnd) return child;
+ throw "Not found";
+ }
+
+ bool isExtensionTypeMethod() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionTypeMethodEnd) return true;
+ return false;
+ }
+
+ ExtensionTypeMethodEnd getExtensionTypeMethod() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionTypeMethodEnd) return child;
+ throw "Not found";
+ }
+
+ bool isExtensionTypeFields() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionTypeFieldsEnd) return true;
+ return false;
+ }
+
+ ExtensionTypeFieldsEnd getExtensionTypeFields() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionTypeFieldsEnd) return child;
+ throw "Not found";
+ }
+
+ bool isExtensionTypeConstructor() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionTypeConstructorEnd) return true;
+ return false;
+ }
+
+ ExtensionTypeConstructorEnd getExtensionTypeConstructor() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionTypeConstructorEnd) return child;
+ throw "Not found";
+ }
+
+ bool isExtensionTypeFactoryMethod() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionTypeFactoryMethodEnd) return true;
+ return false;
+ }
+
+ ExtensionTypeFactoryMethodEnd getExtensionTypeFactoryMethod() {
+ ParserAstNode child = children![1];
+ if (child is ExtensionTypeFactoryMethodEnd) return child;
+ throw "Not found";
+ }
+
+ bool isEnumMethod() {
+ ParserAstNode child = children![1];
+ if (child is EnumMethodEnd) return true;
+ return false;
+ }
+
+ EnumMethodEnd getEnumMethod() {
+ ParserAstNode child = children![1];
+ if (child is EnumMethodEnd) return child;
+ throw "Not found";
+ }
+
+ bool isEnumFields() {
+ ParserAstNode child = children![1];
+ if (child is EnumFieldsEnd) return true;
+ return false;
+ }
+
+ EnumFieldsEnd getEnumFields() {
+ ParserAstNode child = children![1];
+ if (child is EnumFieldsEnd) return child;
+ throw "Not found";
+ }
+
+ bool isEnumConstructor() {
+ ParserAstNode child = children![1];
+ if (child is EnumConstructorEnd) return true;
+ return false;
+ }
+
+ EnumConstructorEnd getEnumConstructor() {
+ ParserAstNode child = children![1];
+ if (child is EnumConstructorEnd) return child;
+ throw "Not found";
+ }
+
+ bool isEnumFactoryMethod() {
+ ParserAstNode child = children![1];
+ if (child is EnumFactoryMethodEnd) return true;
+ return false;
+ }
+
+ EnumFactoryMethodEnd getEnumFactoryMethod() {
+ ParserAstNode child = children![1];
+ if (child is EnumFactoryMethodEnd) return child;
+ throw "Not found";
+ }
}
extension MixinFieldsExtension on MixinFieldsEnd {
@@ -1097,6 +1417,50 @@
}
}
+extension ExtensionTypeFieldsExtension on ExtensionTypeFieldsEnd {
+ List<IdentifierHandle> getFieldIdentifiers() {
+ int countLeft = count;
+ List<IdentifierHandle>? identifiers;
+ for (int i = children!.length - 1; i >= 0; i--) {
+ ParserAstNode child = children![i];
+ if (child is IdentifierHandle &&
+ child.context == IdentifierContext.fieldDeclaration) {
+ countLeft--;
+ if (identifiers == null) {
+ identifiers = new List<IdentifierHandle>.filled(count, child);
+ } else {
+ identifiers[countLeft] = child;
+ }
+ if (countLeft == 0) break;
+ }
+ }
+ if (countLeft != 0) throw "Didn't find the expected number of identifiers";
+ return identifiers ?? [];
+ }
+}
+
+extension EnumFieldsExtension on EnumFieldsEnd {
+ List<IdentifierHandle> getFieldIdentifiers() {
+ int countLeft = count;
+ List<IdentifierHandle>? identifiers;
+ for (int i = children!.length - 1; i >= 0; i--) {
+ ParserAstNode child = children![i];
+ if (child is IdentifierHandle &&
+ child.context == IdentifierContext.fieldDeclaration) {
+ countLeft--;
+ if (identifiers == null) {
+ identifiers = new List<IdentifierHandle>.filled(count, child);
+ } else {
+ identifiers[countLeft] = child;
+ }
+ if (countLeft == 0) break;
+ }
+ }
+ if (countLeft != 0) throw "Didn't find the expected number of identifiers";
+ return identifiers ?? [];
+ }
+}
+
extension ClassFieldsExtension on ClassFieldsEnd {
List<IdentifierHandle> getFieldIdentifiers() {
int countLeft = count;
@@ -1141,6 +1505,22 @@
}
return ids;
}
+
+ IdentifierHandle getEnumIdentifier() {
+ ParserAstNode? parent = this.parent;
+ if (parent is! TopLevelDeclarationEnd) throw "Now nested as expected";
+ return parent.getIdentifier();
+ }
+
+ List<MemberEnd> getMembers() {
+ List<MemberEnd> members = [];
+ for (ParserAstNode child in children!) {
+ if (child is MemberEnd) {
+ members.add(child);
+ }
+ }
+ return members;
+ }
}
extension ExtensionDeclarationExtension on ExtensionDeclarationEnd {
@@ -1151,6 +1531,38 @@
}
return ids;
}
+
+ Token? getExtensionName() {
+ ExtensionDeclarationBegin begin =
+ children!.first as ExtensionDeclarationBegin;
+ return begin.name;
+ }
+
+ ClassOrMixinOrExtensionBodyEnd getClassOrMixinOrExtensionBody() {
+ for (ParserAstNode child in children!) {
+ if (child is ClassOrMixinOrExtensionBodyEnd) {
+ return child;
+ }
+ }
+ throw "Not found.";
+ }
+}
+
+extension ExtensionTypeDeclarationExtension on ExtensionTypeDeclarationEnd {
+ Token? getExtensionTypeName() {
+ ExtensionTypeDeclarationBegin begin =
+ children!.first as ExtensionTypeDeclarationBegin;
+ return begin.name;
+ }
+
+ ClassOrMixinOrExtensionBodyEnd getClassOrMixinOrExtensionBody() {
+ for (ParserAstNode child in children!) {
+ if (child is ClassOrMixinOrExtensionBodyEnd) {
+ return child;
+ }
+ }
+ throw "Not found.";
+ }
}
extension TopLevelMethodExtension on TopLevelMethodEnd {
@@ -1362,6 +1774,7 @@
bool foundType = false;
for (ParserAstNode child in children!) {
if (child is TypeHandle ||
+ child is RecordTypeEnd ||
child is NoTypeHandle ||
child is VoidKeywordHandle ||
child is FunctionTypeEnd) {
@@ -1382,6 +1795,7 @@
bool foundType = false;
for (ParserAstNode child in children!) {
if (child is TypeHandle ||
+ child is RecordTypeEnd ||
child is NoTypeHandle ||
child is VoidKeywordHandle ||
child is FunctionTypeEnd) {
@@ -1402,6 +1816,49 @@
bool foundType = false;
for (ParserAstNode child in children!) {
if (child is TypeHandle ||
+ child is RecordTypeEnd ||
+ child is NoTypeHandle ||
+ child is VoidKeywordHandle ||
+ child is FunctionTypeEnd) {
+ foundType = true;
+ }
+ if (foundType && child is IdentifierHandle) {
+ return child.token.lexeme;
+ } else if (foundType && child is OperatorNameHandle) {
+ return child.token.lexeme;
+ }
+ }
+ throw "No identifier found: $children";
+ }
+}
+
+extension ExtensionTypeMethodExtension on ExtensionTypeMethodEnd {
+ String getNameIdentifier() {
+ bool foundType = false;
+ for (ParserAstNode child in children!) {
+ if (child is TypeHandle ||
+ child is RecordTypeEnd ||
+ child is NoTypeHandle ||
+ child is VoidKeywordHandle ||
+ child is FunctionTypeEnd) {
+ foundType = true;
+ }
+ if (foundType && child is IdentifierHandle) {
+ return child.token.lexeme;
+ } else if (foundType && child is OperatorNameHandle) {
+ return child.token.lexeme;
+ }
+ }
+ throw "No identifier found: $children";
+ }
+}
+
+extension EnumMethodExtension on EnumMethodEnd {
+ String getNameIdentifier() {
+ bool foundType = false;
+ for (ParserAstNode child in children!) {
+ if (child is TypeHandle ||
+ child is RecordTypeEnd ||
child is NoTypeHandle ||
child is VoidKeywordHandle ||
child is FunctionTypeEnd) {
@@ -1431,6 +1888,62 @@
}
}
+extension MixinFactoryMethodExtension on MixinFactoryMethodEnd {
+ List<IdentifierHandle> getIdentifiers() {
+ List<IdentifierHandle> result = [];
+ for (ParserAstNode child in children!) {
+ if (child is IdentifierHandle) {
+ result.add(child);
+ } else if (child is FormalParametersEnd) {
+ break;
+ }
+ }
+ return result;
+ }
+}
+
+extension ExtensionFactoryMethodExtension on ExtensionFactoryMethodEnd {
+ List<IdentifierHandle> getIdentifiers() {
+ List<IdentifierHandle> result = [];
+ for (ParserAstNode child in children!) {
+ if (child is IdentifierHandle) {
+ result.add(child);
+ } else if (child is FormalParametersEnd) {
+ break;
+ }
+ }
+ return result;
+ }
+}
+
+extension ExtensionTypeFactoryMethodExtension on ExtensionTypeFactoryMethodEnd {
+ List<IdentifierHandle> getIdentifiers() {
+ List<IdentifierHandle> result = [];
+ for (ParserAstNode child in children!) {
+ if (child is IdentifierHandle) {
+ result.add(child);
+ } else if (child is FormalParametersEnd) {
+ break;
+ }
+ }
+ return result;
+ }
+}
+
+extension EnumFactoryMethodExtension on EnumFactoryMethodEnd {
+ List<IdentifierHandle> getIdentifiers() {
+ List<IdentifierHandle> result = [];
+ for (ParserAstNode child in children!) {
+ if (child is IdentifierHandle) {
+ result.add(child);
+ } else if (child is FormalParametersEnd) {
+ break;
+ }
+ }
+ return result;
+ }
+}
+
extension ClassConstructorExtension on ClassConstructorEnd {
FormalParametersEnd getFormalParameters() {
for (ParserAstNode child in children!) {
@@ -1470,6 +1983,54 @@
}
}
+extension ExtensionConstructorExtension on ExtensionConstructorEnd {
+ List<IdentifierHandle> getIdentifiers() {
+ List<IdentifierHandle> result = [];
+ for (ParserAstNode child in children!) {
+ if (child is IdentifierHandle) {
+ result.add(child);
+ }
+ }
+ return result;
+ }
+}
+
+extension ExtensionTypeConstructorExtension on ExtensionTypeConstructorEnd {
+ List<IdentifierHandle> getIdentifiers() {
+ List<IdentifierHandle> result = [];
+ for (ParserAstNode child in children!) {
+ if (child is IdentifierHandle) {
+ result.add(child);
+ }
+ }
+ return result;
+ }
+}
+
+extension EnumConstructorExtension on EnumConstructorEnd {
+ List<IdentifierHandle> getIdentifiers() {
+ List<IdentifierHandle> result = [];
+ for (ParserAstNode child in children!) {
+ if (child is IdentifierHandle) {
+ result.add(child);
+ }
+ }
+ return result;
+ }
+}
+
+extension MixinConstructorExtension on MixinConstructorEnd {
+ List<IdentifierHandle> getIdentifiers() {
+ List<IdentifierHandle> result = [];
+ for (ParserAstNode child in children!) {
+ if (child is IdentifierHandle) {
+ result.add(child);
+ }
+ }
+ return result;
+ }
+}
+
extension FormalParametersExtension on FormalParametersEnd {
List<FormalParameterEnd> getFormalParameters() {
List<FormalParameterEnd> result = [];
diff --git a/pkg/front_end/test/fasta/util/parser_ast_test.dart b/pkg/front_end/test/fasta/util/parser_ast_test.dart
index 2fd7170..e000031 100644
--- a/pkg/front_end/test/fasta/util/parser_ast_test.dart
+++ b/pkg/front_end/test/fasta/util/parser_ast_test.dart
@@ -24,6 +24,7 @@
}
void canParseTopLevelIshOfAllFrontendFiles() {
+ Stopwatch stopwatch = new Stopwatch()..start();
Directory directory = new Directory.fromUri(base.resolve("../../../"));
int processed = 0;
int errors = 0;
@@ -33,11 +34,14 @@
try {
processed++;
List<int> data = entry.readAsBytesSync();
- CompilationUnitEnd ast = getAST(data,
- includeBody: true,
- includeComments: true,
- enableExtensionMethods: true,
- enableNonNullable: false);
+ CompilationUnitEnd ast = getAST(
+ data,
+ includeBody: true,
+ includeComments: true,
+ enableExtensionMethods: true,
+ enableNonNullable: true,
+ enableTripleShift: true,
+ );
splitIntoChunks(ast, data);
for (ParserAstNode child in ast.children!) {
if (child.isClass()) {
@@ -47,6 +51,16 @@
splitIntoChunks(
child.asMixinDeclaration().getClassOrMixinOrExtensionBody(),
data);
+ } else if (child.isExtension()) {
+ splitIntoChunks(
+ child.asExtension().getClassOrMixinOrExtensionBody(), data);
+ } else if (child.isExtensionType()) {
+ splitIntoChunks(
+ child.asExtensionType().getClassOrMixinOrExtensionBody(), data);
+ } else if (child.isEnum()) {
+ for (MemberEnd member in child.asEnum().getMembers()) {
+ processItem(member, data);
+ }
}
}
} catch (e, st) {
@@ -55,8 +69,11 @@
}
}
}
- print("Processed $processed files in $directory. "
+ print("Processed $processed files in $directory in ${stopwatch.elapsed}. "
"Encountered $errors errors.");
+ if (errors != 0) {
+ throw "Got errors.";
+ }
}
void testTopLevelStuff() {
@@ -72,7 +89,7 @@
expect(2, ast.getExports().length);
List<String> foundChunks = splitIntoChunks(ast, data);
- expect(22, foundChunks.length);
+ expect(23, foundChunks.length);
expect("library top_level_stuff;", foundChunks[0]);
expect('import "top_level_stuff_helper.dart";', foundChunks[1]);
expect('export "top_level_stuff_helper.dart";', foundChunks[2]);
@@ -87,34 +104,35 @@
expect("part 'top_level_stuff_helper.dart';", foundChunks[5]);
expect('@metadataOneOnThisOne("bla")\n', foundChunks[6]);
expect("@metadataTwoOnThisOne\n", foundChunks[7]);
+ expect('@metadataThree.OnThisOne<int>("hello")\n', foundChunks[8]);
expect("""void toplevelMethod() {
// no content
-}""", foundChunks[8]);
+}""", foundChunks[9]);
expect("""List<E> anotherTopLevelMethod<E>() {
return null;
-}""", foundChunks[9]);
- expect("enum FooEnum { A, B, Bla }", foundChunks[10]);
+}""", foundChunks[10]);
+ expect("enum FooEnum { A, B, Bla }", foundChunks[11]);
expect("""class FooClass {
// no content.
-}""", foundChunks[11]);
+}""", foundChunks[12]);
expect("""mixin FooMixin {
// no content.
-}""", foundChunks[12]);
+}""", foundChunks[13]);
expect("""class A<T> {
// no content.
-}""", foundChunks[13]);
- expect("typedef B = Function();", foundChunks[14]);
+}""", foundChunks[14]);
+ expect("typedef B = Function();", foundChunks[15]);
expect("""mixin C<T> on A<T> {
// no content.
-}""", foundChunks[15]);
+}""", foundChunks[16]);
expect("""extension D<T> on A<T> {
// no content.
-}""", foundChunks[16]);
- expect("class E = A with FooClass;", foundChunks[17]);
- expect("int field1;", foundChunks[18]);
- expect("int field2, field3;", foundChunks[19]);
- expect("int field4 = 42;", foundChunks[20]);
- expect("@AnnotationAtEOF", foundChunks[21]);
+}""", foundChunks[17]);
+ expect("class E = A with FooClass;", foundChunks[18]);
+ expect("int field1;", foundChunks[19]);
+ expect("int field2, field3;", foundChunks[20]);
+ expect("int field4 = 42;", foundChunks[21]);
+ expect("@AnnotationAtEOF", foundChunks[22]);
file = new File.fromUri(
base.resolve("parser_ast_test_data/top_level_stuff_helper.txt"));
@@ -277,6 +295,8 @@
List<String> processItem(ParserAstNode item, List<int> data) {
if (item.isClass()) {
ClassDeclarationEnd cls = item.asClass();
+ // Check that we can get the identifier without throwing.
+ cls.getClassIdentifier();
return [
getCutContent(data, cls.beginToken.offset,
cls.endToken.offset + cls.endToken.length)
@@ -287,6 +307,8 @@
if (entries.isNotEmpty) {
List<String> chunks = [];
for (MetadataEnd metadata in entries) {
+ // Check that we can get the identifiers without throwing.
+ metadata.getIdentifiers();
chunks.add(getCutContent(
data, metadata.beginToken.offset, metadata.endToken.offset));
}
@@ -325,18 +347,24 @@
];
} else if (item.isTopLevelMethod()) {
TopLevelMethodEnd method = item.asTopLevelMethod();
+ // Check that we can get the identifier without throwing.
+ method.getNameIdentifier();
return [
getCutContent(data, method.beginToken.offset,
method.endToken.offset + method.endToken.length)
];
} else if (item.isTopLevelFields()) {
TopLevelFieldsEnd fields = item.asTopLevelFields();
+ // Check that we can get the identifiers without throwing.
+ fields.getFieldIdentifiers();
return [
getCutContent(data, fields.beginToken.offset,
fields.endToken.offset + fields.endToken.length)
];
} else if (item.isEnum()) {
EnumEnd declaration = item.asEnum();
+ // Check that we can get the identifier without throwing.
+ declaration.getEnumIdentifier();
return [
getCutContent(
data,
@@ -346,28 +374,44 @@
];
} else if (item.isMixinDeclaration()) {
MixinDeclarationEnd mixinDecl = item.asMixinDeclaration();
+ // Check that we can get the identifier without throwing.
+ mixinDecl.getMixinIdentifier();
return [
getCutContent(data, mixinDecl.beginToken.offset,
mixinDecl.endToken.offset + mixinDecl.endToken.length)
];
} else if (item.isNamedMixinDeclaration()) {
NamedMixinApplicationEnd namedMixinDecl = item.asNamedMixinDeclaration();
+ // Check that we can get the identifier without throwing.
+ namedMixinDecl.getMixinIdentifier();
return [
getCutContent(data, namedMixinDecl.begin.offset,
namedMixinDecl.endToken.offset + namedMixinDecl.endToken.length)
];
} else if (item.isTypedef()) {
TypedefEnd typedefDecl = item.asTypedef();
+ // Check that we can get the identifier without throwing.
+ typedefDecl.getNameIdentifier();
return [
getCutContent(data, typedefDecl.typedefKeyword.offset,
typedefDecl.endToken.offset + typedefDecl.endToken.length)
];
} else if (item.isExtension()) {
ExtensionDeclarationEnd extensionDecl = item.asExtension();
+ // Check that we can get the identifier without throwing.
+ extensionDecl.getExtensionName();
return [
getCutContent(data, extensionDecl.extensionKeyword.offset,
extensionDecl.endToken.offset + extensionDecl.endToken.length)
];
+ } else if (item.isExtensionType()) {
+ ExtensionTypeDeclarationEnd extensionTypeDecl = item.asExtensionType();
+ // Check that we can get the identifier without throwing.
+ extensionTypeDecl.getExtensionTypeName();
+ return [
+ getCutContent(data, extensionTypeDecl.extensionKeyword.offset,
+ extensionTypeDecl.endToken.offset + extensionTypeDecl.endToken.length)
+ ];
} else if (item.isScript()) {
ScriptHandle script = item.asScript();
return [
@@ -377,54 +421,160 @@
} else if (item is MemberEnd) {
if (item.isClassConstructor()) {
ClassConstructorEnd decl = item.getClassConstructor();
+ // Check that we can get the identifiers without throwing.
+ decl.getIdentifiers();
return [
getCutContent(data, decl.beginToken.offset,
decl.endToken.offset + decl.endToken.length)
];
} else if (item.isClassFactoryMethod()) {
ClassFactoryMethodEnd decl = item.getClassFactoryMethod();
+ // Check that we can get the identifiers without throwing.
+ decl.getIdentifiers();
return [
getCutContent(data, decl.beginToken.offset,
decl.endToken.offset + decl.endToken.length)
];
} else if (item.isClassMethod()) {
ClassMethodEnd decl = item.getClassMethod();
+ // Check that we can get the identifier without throwing.
+ decl.getNameIdentifier();
return [
getCutContent(data, decl.beginToken.offset,
decl.endToken.offset + decl.endToken.length)
];
} else if (item.isClassFields()) {
ClassFieldsEnd decl = item.getClassFields();
- return [
- getCutContent(data, decl.beginToken.offset,
- decl.endToken.offset + decl.endToken.length)
- ];
- } else if (item.isClassFields()) {
- ClassFieldsEnd decl = item.getClassFields();
+ // Check that we can get the identifiers without throwing.
+ decl.getFieldIdentifiers();
return [
getCutContent(data, decl.beginToken.offset,
decl.endToken.offset + decl.endToken.length)
];
} else if (item.isMixinFields()) {
MixinFieldsEnd decl = item.getMixinFields();
+ // Check that we can get the identifiers without throwing.
+ decl.getFieldIdentifiers();
return [
getCutContent(data, decl.beginToken.offset,
decl.endToken.offset + decl.endToken.length)
];
} else if (item.isMixinMethod()) {
MixinMethodEnd decl = item.getMixinMethod();
+ // Check that we can get the identifier without throwing.
+ decl.getNameIdentifier();
return [
getCutContent(data, decl.beginToken.offset,
decl.endToken.offset + decl.endToken.length)
];
} else if (item.isMixinFactoryMethod()) {
MixinFactoryMethodEnd decl = item.getMixinFactoryMethod();
+ // Check that we can get the identifiers without throwing.
+ decl.getIdentifiers();
return [
getCutContent(data, decl.beginToken.offset,
decl.endToken.offset + decl.endToken.length)
];
} else if (item.isMixinConstructor()) {
MixinConstructorEnd decl = item.getMixinConstructor();
+ // Check that we can get the identifiers without throwing.
+ decl.getIdentifiers();
+ return [
+ getCutContent(data, decl.beginToken.offset,
+ decl.endToken.offset + decl.endToken.length)
+ ];
+ } else if (item.isExtensionMethod()) {
+ ExtensionMethodEnd decl = item.getExtensionMethod();
+ // Check that we can get the identifier without throwing.
+ decl.getNameIdentifier();
+ return [
+ getCutContent(data, decl.beginToken.offset,
+ decl.endToken.offset + decl.endToken.length)
+ ];
+ } else if (item.isExtensionFields()) {
+ ExtensionFieldsEnd decl = item.getExtensionFields();
+ // Check that we can get the identifiers without throwing.
+ decl.getFieldIdentifiers();
+ return [
+ getCutContent(data, decl.beginToken.offset,
+ decl.endToken.offset + decl.endToken.length)
+ ];
+ } else if (item.isExtensionConstructor()) {
+ ExtensionConstructorEnd decl = item.getExtensionConstructor();
+ // Check that we can get the identifiers without throwing.
+ decl.getIdentifiers();
+ return [
+ getCutContent(data, decl.beginToken.offset,
+ decl.endToken.offset + decl.endToken.length)
+ ];
+ } else if (item.isExtensionFactoryMethod()) {
+ ExtensionFactoryMethodEnd decl = item.getExtensionFactoryMethod();
+ // Check that we can get the identifiers without throwing.
+ decl.getIdentifiers();
+ return [
+ getCutContent(data, decl.beginToken.offset,
+ decl.endToken.offset + decl.endToken.length)
+ ];
+ } else if (item.isExtensionTypeMethod()) {
+ ExtensionTypeMethodEnd decl = item.getExtensionTypeMethod();
+ // Check that we can get the identifier without throwing.
+ decl.getNameIdentifier();
+ return [
+ getCutContent(data, decl.beginToken.offset,
+ decl.endToken.offset + decl.endToken.length)
+ ];
+ } else if (item.isExtensionTypeFields()) {
+ ExtensionTypeFieldsEnd decl = item.getExtensionTypeFields();
+ // Check that we can get the identifiers without throwing.
+ decl.getFieldIdentifiers();
+ return [
+ getCutContent(data, decl.beginToken.offset,
+ decl.endToken.offset + decl.endToken.length)
+ ];
+ } else if (item.isExtensionTypeConstructor()) {
+ ExtensionTypeConstructorEnd decl = item.getExtensionTypeConstructor();
+ // Check that we can get the identifiers without throwing.
+ decl.getIdentifiers();
+ return [
+ getCutContent(data, decl.beginToken.offset,
+ decl.endToken.offset + decl.endToken.length)
+ ];
+ } else if (item.isExtensionTypeFactoryMethod()) {
+ ExtensionTypeFactoryMethodEnd decl = item.getExtensionTypeFactoryMethod();
+ // Check that we can get the identifiers without throwing.
+ decl.getIdentifiers();
+ return [
+ getCutContent(data, decl.beginToken.offset,
+ decl.endToken.offset + decl.endToken.length)
+ ];
+ } else if (item.isEnumMethod()) {
+ EnumMethodEnd decl = item.getEnumMethod();
+ // Check that we can get the identifier without throwing.
+ decl.getNameIdentifier();
+ return [
+ getCutContent(data, decl.beginToken.offset,
+ decl.endToken.offset + decl.endToken.length)
+ ];
+ } else if (item.isEnumFields()) {
+ EnumFieldsEnd decl = item.getEnumFields();
+ // Check that we can get the identifiers without throwing.
+ decl.getFieldIdentifiers();
+ return [
+ getCutContent(data, decl.beginToken.offset,
+ decl.endToken.offset + decl.endToken.length)
+ ];
+ } else if (item.isEnumConstructor()) {
+ EnumConstructorEnd decl = item.getEnumConstructor();
+ // Check that we can get the identifiers without throwing.
+ decl.getIdentifiers();
+ return [
+ getCutContent(data, decl.beginToken.offset,
+ decl.endToken.offset + decl.endToken.length)
+ ];
+ } else if (item.isEnumFactoryMethod()) {
+ EnumFactoryMethodEnd decl = item.getEnumFactoryMethod();
+ // Check that we can get the identifiers without throwing.
+ decl.getIdentifiers();
return [
getCutContent(data, decl.beginToken.offset,
decl.endToken.offset + decl.endToken.length)
@@ -433,9 +583,10 @@
if (item.type == ParserAstType.BEGIN) return const [];
if (item.type == ParserAstType.HANDLE) return const [];
if (item.isClassRecoverableError()) return const [];
+ if (item.isExperimentNotEnabled()) return const [];
if (item.isRecoverableError()) return const [];
if (item.isRecoverImport()) return const [];
- throw "Unknown: $item --- ${item.children}";
+ throw "Unknown member: $item --- ${item.children}";
}
} else if (item.isFunctionBody()) {
BlockFunctionBodyEnd decl = item.asFunctionBody();
diff --git a/pkg/front_end/test/fasta/util/parser_ast_test_data/top_level_stuff.txt b/pkg/front_end/test/fasta/util/parser_ast_test_data/top_level_stuff.txt
index 3cd024b..666ad80 100644
--- a/pkg/front_end/test/fasta/util/parser_ast_test_data/top_level_stuff.txt
+++ b/pkg/front_end/test/fasta/util/parser_ast_test_data/top_level_stuff.txt
@@ -12,6 +12,7 @@
@metadataOneOnThisOne("bla")
@metadataTwoOnThisOne
+@metadataThree.OnThisOne<int>("hello")
void toplevelMethod() {
// no content
}
diff --git a/pkg/front_end/tool/parser_direct_ast/console_helper.dart b/pkg/front_end/tool/parser_direct_ast/console_helper.dart
index ad90ce7..c0b8b8f 100644
--- a/pkg/front_end/tool/parser_direct_ast/console_helper.dart
+++ b/pkg/front_end/tool/parser_direct_ast/console_helper.dart
@@ -63,6 +63,8 @@
void quit() {
_gotoMainScreenBuffer();
_showCursor();
+ stdin.echoMode = true;
+ stdin.lineMode = true;
_timer!.cancel();
_preventClose.close();
_stdinListen.cancel();
diff --git a/pkg/front_end/tool/parser_direct_ast/viewer.dart b/pkg/front_end/tool/parser_direct_ast/viewer.dart
index 627cac1..9a3f8bc 100644
--- a/pkg/front_end/tool/parser_direct_ast/viewer.dart
+++ b/pkg/front_end/tool/parser_direct_ast/viewer.dart
@@ -80,10 +80,19 @@
"${element.deprecatedArguments.toString()}${extra}";
}
+ int printLineFrom = 0;
+
@override
void print(WriteOnlyOutput output) {
- for (int row = 0; row < shown.length; row++) {
- if (row >= output.rows) break;
+ if (selected - printLineFrom >= output.rows) {
+ // going down -- "scroll" so the selected line is at the bottom.
+ printLineFrom = selected - output.rows + 1;
+ } else if (selected - printLineFrom < 0) {
+ // going up -- "scroll" so the selected line is at the top.
+ printLineFrom = selected;
+ }
+ for (int row = printLineFrom; row < shown.length; row++) {
+ if ((row - printLineFrom) >= output.rows) break;
PrintedLine element = shown[row];
String line = element.text;
@@ -91,7 +100,8 @@
if (selected == row) {
// Mark line with blue background.
for (int column = 0; column < output.columns; column++) {
- output.setCell(row, column, backgroundColor: BackgroundColor.Blue);
+ output.setCell(row - printLineFrom, column,
+ backgroundColor: BackgroundColor.Blue);
}
}
@@ -101,7 +111,7 @@
length = output.columns;
}
for (int column = 0; column < length; column++) {
- output.setCell(row, column, char: line[column]);
+ output.setCell(row - printLineFrom, column, char: line[column]);
}
}
}