Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(704)

Unified Diff: pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart

Issue 2703863003: Add AstBuilder support for class declarations and named mixin applications. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart
diff --git a/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart b/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart
index 1f9ca9de5881d0ae533a1df161302bb7472159fa..1a7f4ec81153be35a995e586469131b5cf92fae3 100644
--- a/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart
+++ b/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart
@@ -729,4 +729,162 @@ class AstBuilder extends ScopeListener {
List<SimpleIdentifier> hiddenNames = pop();
push(ast.hideCombinator(toAnalyzerToken(hideKeyword), hiddenNames));
}
+
+ @override
+ void endTypeList(int count) {
+ debugEvent("TypeList");
+ push(popList(count) ?? NullValue.TypeList);
+ }
+
+ @override
+ void endClassBody(int memberCount, Token beginToken, Token endToken) {
+ debugEvent("ClassBody");
+ push(new _ClassBody(
+ beginToken, popList(memberCount) ?? <ClassMember>[], endToken));
+ }
+
+ @override
+ void endClassDeclaration(int interfacesCount, Token beginToken,
+ Token extendsKeyword, Token implementsKeyword, Token endToken) {
+ debugEvent("ClassDeclaration");
+ _ClassBody body = pop();
+ ImplementsClause implementsClause;
+ if (implementsKeyword != null) {
+ List<TypeName> interfaces = popList(interfacesCount);
+ implementsClause =
+ ast.implementsClause(toAnalyzerToken(implementsKeyword), interfaces);
+ }
+ ExtendsClause extendsClause;
+ WithClause withClause;
+ var supertype = pop();
+ if (supertype == null) {
+ // No extends clause
+ } else if (supertype is TypeName) {
+ extendsClause =
+ ast.extendsClause(toAnalyzerToken(extendsKeyword), supertype);
+ } else if (supertype is _MixinApplication) {
+ extendsClause = ast.extendsClause(
+ toAnalyzerToken(extendsKeyword), supertype.supertype);
+ withClause = ast.withClause(
+ toAnalyzerToken(supertype.withKeyword), supertype.mixinTypes);
+ } else {
+ internalError('Unexpected kind of supertype ${supertype.runtimeType}');
+ }
+ TypeParameterList typeParameters = pop();
+ SimpleIdentifier name = pop();
+ Token classKeyword;
+ // TODO(paulberry,ahe): This is a hack. The parser should give us the class
+ // keyword.
ahe 2017/02/20 13:04:39 No problem. If you file bugs with lack of token in
Paul Berry 2017/02/20 14:25:10 Ok. I'm still planning to go through all my CLs c
+ if (identical(beginToken.value, 'abstract')) {
ahe 2017/02/20 13:04:39 I suggest using optional like this: if (optional(
Paul Berry 2017/02/20 14:25:10 Acknowledged.
+ classKeyword = beginToken.next;
+ } else {
+ classKeyword = beginToken;
+ }
+ var modifiers = pop();
+ assert(modifiers == null); // TODO(paulberry)
+ analyzer.Token abstractKeyword;
+ List<Annotation> metadata = pop();
+ Comment comment = null; // TODO(paulberry)
+ push(ast.classDeclaration(
+ comment,
+ metadata,
+ abstractKeyword,
+ toAnalyzerToken(classKeyword),
+ name,
+ typeParameters,
+ extendsClause,
+ withClause,
+ implementsClause,
+ toAnalyzerToken(body.beginToken),
+ body.members,
+ toAnalyzerToken(body.endToken)));
+ }
+
+ @override
+ void endMixinApplication() {
+ debugEvent("MixinApplication");
+ List<TypeName> mixinTypes = pop();
+ // TODO(paulberry,ahe): the parser doesn't give us enough information to
+ // locate the "with" keyword.
+ Token withKeyword;
+ TypeName supertype = pop();
+ push(new _MixinApplication(supertype, withKeyword, mixinTypes));
+ }
+
+ @override
+ void endNamedMixinApplication(
+ Token beginToken, Token implementsKeyword, Token endToken) {
+ debugEvent("NamedMixinApplication");
+ ImplementsClause implementsClause;
+ if (implementsKeyword != null) {
+ List<TypeName> interfaces = pop();
+ implementsClause =
+ ast.implementsClause(toAnalyzerToken(implementsKeyword), interfaces);
+ }
+ _MixinApplication mixinApplication = pop();
+ var superclass = mixinApplication.supertype;
+ var withClause = ast.withClause(
+ toAnalyzerToken(mixinApplication.withKeyword),
+ mixinApplication.mixinTypes);
+ // TODO(paulberry,ahe): the parser should give us the "=" token.
+ analyzer.Token equals;
+ TypeParameterList typeParameters = pop();
+ SimpleIdentifier name = pop();
+ Token classKeyword;
+ // TODO(paulberry,ahe): This is a hack. The parser should give us the class
+ // keyword.
ahe 2017/02/20 13:04:39 I agree with all these comments about the parser g
+ if (identical(beginToken.value, 'abstract')) {
+ classKeyword = beginToken.next;
+ } else {
+ classKeyword = beginToken;
+ }
+ var modifiers = pop();
+ assert(modifiers == null); // TODO(paulberry)
+ analyzer.Token abstractKeyword;
+ List<Annotation> metadata = pop();
+ Comment comment = null; // TODO(paulberry)
+ push(ast.classTypeAlias(
+ comment,
+ metadata,
+ toAnalyzerToken(classKeyword),
+ name,
+ typeParameters,
+ equals,
+ abstractKeyword,
+ superclass,
+ withClause,
+ implementsClause,
+ toAnalyzerToken(endToken)));
+ }
+}
+
+/// Data structure placed on the stack to represent a class body.
+///
+/// This is needed because analyzer has no separate AST representation of a
+/// class body; it simply stores all of the relevant data in the
+/// [ClassDeclaration] object.
ahe 2017/02/20 13:04:39 An alternative implementation is to simply push mo
Paul Berry 2017/02/20 14:25:10 Acknowledged. I think I prefer using the temporar
+class _ClassBody {
+ final Token beginToken;
+
+ final List<ClassMember> members;
+
+ final Token endToken;
+
+ _ClassBody(this.beginToken, this.members, this.endToken);
+}
+
+/// Data structure placed on the stack to represent a mixin application (a
+/// structure of the form "A with B, C").
+///
+/// This is needed because analyzer has no separate AST representation of a
+/// mixin application; it simply stores all of the relevant data in the
+/// [ClassDeclaration] or [ClassTypeAlias] object.
+class _MixinApplication {
+ final TypeName supertype;
+
+ final Token withKeyword;
+
+ final List<TypeName> mixinTypes;
+
+ _MixinApplication(this.supertype, this.withKeyword, this.mixinTypes);
}

Powered by Google App Engine
This is Rietveld 408576698