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

Unified Diff: pkg/analyzer/tool/summary/mini_ast.dart

Issue 2748803003: Change summary code generator to use Fasta parser. (Closed)
Patch Set: Created 3 years, 9 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
« no previous file with comments | « pkg/analyzer/tool/summary/generate.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/tool/summary/mini_ast.dart
diff --git a/pkg/analyzer/tool/summary/mini_ast.dart b/pkg/analyzer/tool/summary/mini_ast.dart
new file mode 100644
index 0000000000000000000000000000000000000000..3d6a09a73f5058c28e78dae69be63fbaaa9ed371
--- /dev/null
+++ b/pkg/analyzer/tool/summary/mini_ast.dart
@@ -0,0 +1,481 @@
+// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// 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:front_end/src/fasta/errors.dart';
+import 'package:front_end/src/fasta/parser/identifier_context.dart';
+import 'package:front_end/src/fasta/parser/parser.dart';
+import 'package:front_end/src/fasta/scanner/token.dart';
+import 'package:front_end/src/fasta/source/stack_listener.dart';
+
+/// "Mini AST" representation of a declaration which can accept annotations.
+class AnnotatedNode {
+ final Comment documentationComment;
+
+ final List<Annotation> metadata;
+
+ AnnotatedNode(this.documentationComment, List<Annotation> metadata)
+ : metadata = metadata ?? const [];
+}
+
+/// "Mini AST" representation of an annotation.
+class Annotation {
+ final String name;
+
+ final String constructorName;
+
+ final List<Expression> arguments;
+
+ Annotation(this.name, this.constructorName, this.arguments);
+}
+
+/// "Mini AST" representation of a class declaration.
+class ClassDeclaration extends CompilationUnitMember {
+ final String name;
+
+ final TypeName superclass;
+
+ final List<ClassMember> members;
+
+ ClassDeclaration(Comment documentationComment, List<Annotation> metadata,
+ this.name, this.superclass, this.members)
+ : super(documentationComment, metadata);
+}
+
+/// "Mini AST" representation of a class member.
+class ClassMember extends AnnotatedNode {
+ ClassMember(Comment documentationComment, List<Annotation> metadata)
+ : super(documentationComment, metadata);
+}
+
+/// "Mini AST" representation of a comment.
+class Comment {
+ final bool isDocumentation;
+
+ final List<Token> tokens;
+
+ factory Comment(Token commentToken) {
+ var tokens = <Token>[];
+ bool isDocumentation = false;
+ while (commentToken != null) {
+ if (commentToken.lexeme.startsWith('/**') ||
+ commentToken.lexeme.startsWith('///')) {
+ isDocumentation = true;
+ }
+ tokens.add(commentToken);
+ commentToken = commentToken.next;
+ }
+ return new Comment._(isDocumentation, tokens);
+ }
+
+ Comment._(this.isDocumentation, this.tokens);
+}
+
+/// "Mini AST" representation of a CompilationUnit.
+class CompilationUnit {
+ final declarations = <CompilationUnitMember>[];
+}
+
+/// "Mini AST" representation of a top level member of a compilation unit.
+class CompilationUnitMember extends AnnotatedNode {
+ CompilationUnitMember(Comment documentationComment, List<Annotation> metadata)
+ : super(documentationComment, metadata);
+}
+
+/// "Mini AST" representation of a constructor declaration.
+class ConstructorDeclaration extends ClassMember {
+ final ConstructorReference name;
+
+ ConstructorDeclaration(
+ Comment documentationComment, List<Annotation> metadata, this.name)
+ : super(documentationComment, metadata);
+}
+
+/// "Mini AST" representation of a constructor reference.
+class ConstructorReference {
+ final String name;
+
+ final String constructorName;
+
+ ConstructorReference(this.name, this.constructorName);
+}
+
+/// "Mini AST" representation of an individual enum constant in an enum
+/// declaration.
+class EnumConstantDeclaration extends AnnotatedNode {
+ final String name;
+
+ EnumConstantDeclaration(
+ Comment documentationComment, List<Annotation> metadata, this.name)
+ : super(documentationComment, metadata);
+}
+
+/// "Mini AST" representation of an enum declaration.
+class EnumDeclaration extends CompilationUnitMember {
+ final String name;
+
+ final List<EnumConstantDeclaration> constants;
+
+ EnumDeclaration(Comment documentationComment, List<Annotation> metadata,
+ this.name, this.constants)
+ : super(documentationComment, metadata);
+}
+
+/// "Mini AST" representation of an expression.
+class Expression {}
+
+/// "Mini AST" representation of an integer literal.
+class IntegerLiteral extends Expression {
+ final int value;
+
+ IntegerLiteral(this.value);
+}
+
+/// "Mini AST" representation of a method declaration.
+class MethodDeclaration extends ClassMember {
+ final bool isGetter;
+
+ final String name;
+
+ final TypeName returnType;
+
+ MethodDeclaration(Comment documentationComment, List<Annotation> metadata,
+ this.isGetter, this.name, this.returnType)
+ : super(documentationComment, metadata);
+}
+
+/// Parser listener which generates a "mini AST" representation of the source
+/// code. This representation is just sufficient for summary code generation.
+class MiniAstBuilder extends StackListener {
+ bool inMetadata = false;
+
+ final compilationUnit = new CompilationUnit();
+
+ @override
+ Uri get uri => null;
+
+ @override
+ void beginMetadata(Token token) {
+ inMetadata = true;
+ }
+
+ @override
+ void beginMetadataStar(Token token) {
+ debugEvent("beginMetadataStar");
+ if (token.precedingComments != null) {
+ push(new Comment(token.precedingComments));
+ } else {
+ push(NullValue.Comments);
+ }
+ }
+
+ @override
+ void endArguments(int count, Token beginToken, Token endToken) {
+ debugEvent("Arguments");
+ push(popList(count));
+ }
+
+ @override
+ void endClassBody(int memberCount, Token beginToken, Token endToken) {
+ debugEvent("ClassBody");
+ push(popList(memberCount));
+ }
+
+ void endClassDeclaration(
+ int interfacesCount,
+ Token beginToken,
+ Token classKeyword,
+ Token extendsKeyword,
+ Token implementsKeyword,
+ Token endToken) {
+ debugEvent("ClassDeclaration");
+ // ignore: strong_mode_down_cast_composite
+ List<ClassMember> members = pop();
scheglov 2017/03/14 17:22:40 Would this be better? var members = pop() as List<
Paul Berry 2017/03/14 17:31:36 Personally, I like it better. But IIRC, Peter has
scheglov 2017/03/14 17:35:37 OK Probably performance is not a concern for gener
+ TypeName superclass = pop();
+ pop(); // Type variables
+ String name = pop();
+ // ignore: strong_mode_down_cast_composite
+ List<Annotation> metadata = pop();
+ Comment comment = pop();
+ compilationUnit.declarations.add(
+ new ClassDeclaration(comment, metadata, name, superclass, members));
+ }
+
+ @override
+ void endCombinators(int count) {
+ debugEvent("Combinators");
+ }
+
+ @override
+ void endConditionalUris(int count) {
+ debugEvent("ConditionalUris");
+ if (count != 0) {
+ internalError('Conditional URIs are not supported by summary codegen');
+ }
+ }
+
+ @override
+ void endConstructorReference(
+ Token start, Token periodBeforeName, Token endToken) {
+ debugEvent("ConstructorReference");
+ String constructorName = popIfNotNull(periodBeforeName);
+ pop(); // Type arguments
+ String name = pop();
+ push(new ConstructorReference(name, constructorName));
+ }
+
+ void endEnum(Token enumKeyword, Token endBrace, int count) {
+ debugEvent("Enum");
+ // ignore: strong_mode_down_cast_composite
+ List<EnumConstantDeclaration> constants = popList(count);
+ String name = pop();
+ // ignore: strong_mode_down_cast_composite
+ List<Annotation> metadata = pop();
+ Comment comment = pop();
+ compilationUnit.declarations
+ .add(new EnumDeclaration(comment, metadata, name, constants));
+ }
+
+ @override
+ void endFactoryMethod(
+ Token beginToken, Token factoryKeyword, Token endToken) {
+ debugEvent("FactoryMethod");
+ pop(); // Body
+ ConstructorReference name = pop();
+ // ignore: strong_mode_down_cast_composite
+ List<Annotation> metadata = pop();
+ Comment comment = pop();
+ push(new ConstructorDeclaration(comment, metadata, name));
+ }
+
+ @override
+ void endFieldInitializer(Token assignment) {
+ debugEvent("FieldInitializer");
+ pop(); // Expression
+ }
+
+ @override
+ void endFormalParameter(
+ Token covariantKeyword, Token thisKeyword, FormalParameterType kind) {
+ debugEvent("FormalParameter");
+ pop(); // Name
+ pop(); // Type
+ pop(); // Metadata
+ pop(); // Comment
+ }
+
+ @override
+ void endFormalParameters(int count, Token beginToken, Token endToken) {
+ debugEvent("FormalParameters");
+ }
+
+ @override
+ void endIdentifierList(int count) {
+ debugEvent("IdentifierList");
+ push(popList(count));
+ }
+
+ @override
+ void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword,
+ Token semicolon) {
+ debugEvent("Import");
+ popIfNotNull(asKeyword); // Prefix identifier
+ pop(); // URI
+ pop(); // Metadata
+ pop(); // Comment
+ }
+
+ @override
+ void endLibraryName(Token libraryKeyword, Token semicolon) {
+ debugEvent("LibraryName");
+ pop(); // Library name
+ pop(); // Metadata
+ pop(); // Comment
+ }
+
+ @override
+ void endLiteralString(int interpolationCount, Token endToken) {
+ super.endLiteralString(interpolationCount, endToken);
+ String value = pop();
+ push(new StringLiteral(value));
+ }
+
+ @override
+ void endMember() {
+ debugEvent("Member");
+ }
+
+ @override
+ void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
+ debugEvent("Metadata");
+ inMetadata = false;
+ // ignore: strong_mode_down_cast_composite
+ List<Expression> arguments = pop();
+ String constructorName = popIfNotNull(periodBeforeName);
+ pop(); // Type arguments
+ String name = pop();
+ push(new Annotation(name, constructorName, arguments));
+ }
+
+ @override
+ void endMetadataStar(int count, bool forParameter) {
+ debugEvent("MetadataStar");
+ push(popList(count) ?? NullValue.Metadata);
+ }
+
+ void endMethod(Token getOrSet, Token beginToken, Token endToken) {
+ debugEvent("Method");
+ pop(); // Body
+ pop(); // Initializers
+ pop(); // Formal parameters
+ pop(); // Type variables
+ String name = pop();
+ TypeName returnType = pop();
+ // ignore: strong_mode_down_cast_composite
+ List<Annotation> metadata = pop();
+ Comment comment = pop();
+ push(new MethodDeclaration(
+ comment, metadata, getOrSet?.lexeme == 'get', name, returnType));
+ }
+
+ @override
+ void endSend(Token beginToken, Token endToken) {
+ debugEvent("Send");
+ // ignore: strong_mode_down_cast_composite
+ pop(); // Arguments
+ pop(); // Type arguments
+ pop(); // Receiver
+ push(new UnknownExpression());
+ }
+
+ @override
+ void endShow(Token showKeyword) {
+ debugEvent("Show");
+ pop(); // Shown names
+ }
+
+ @override
+ void endTopLevelFields(int count, Token beginToken, Token endToken) {
+ // We ignore top level variable declarations; they are present just to make
+ // the IDL analyze without warnings.
+ debugEvent("TopLevelFields");
+ popList(count); // Fields
+ pop(); // Type
+ pop(); // Metadata
+ pop(); // Comment
+ }
+
+ @override
+ void endTypeArguments(int count, Token beginToken, Token endToken) {
+ debugEvent("TypeArguments");
+ push(popList(count));
+ }
+
+ @override
+ void handleAsyncModifier(Token asyncToken, Token starToken) {
+ debugEvent("AsyncModifier");
+ }
+
+ @override
+ void handleBinaryExpression(Token token) {
+ debugEvent("BinaryExpression");
+ pop(); // RHS
+ pop(); // LHS
+ push(new UnknownExpression());
+ }
+
+ @override
+ void handleFormalParameterWithoutValue(Token token) {
+ debugEvent("FormalParameterWithoutValue");
+ }
+
+ @override
+ void handleFunctionBodySkipped(Token token, bool isExpressionBody) {
+ if (isExpressionBody) pop();
+ push(NullValue.FunctionBody);
+ }
+
+ void handleIdentifier(Token token, IdentifierContext context) {
+ if (context == IdentifierContext.enumValueDeclaration) {
+ var comment = new Comment(token.precedingComments);
+ push(new EnumConstantDeclaration(comment, null, token.lexeme));
+ } else {
+ push(token.lexeme);
+ }
+ }
+
+ void handleLiteralInt(Token token) {
+ debugEvent("LiteralInt");
+ push(new IntegerLiteral(int.parse(token.lexeme)));
+ }
+
+ void handleLiteralNull(Token token) {
+ debugEvent("LiteralNull");
+ push(new UnknownExpression());
+ }
+
+ @override
+ void handleModifier(Token token) {
+ debugEvent("Modifier");
+ }
+
+ @override
+ void handleModifiers(int count) {
+ debugEvent("Modifiers");
+ }
+
+ @override
+ void handleQualified(Token period) {
+ debugEvent("Qualified");
+ String suffix = pop();
+ String prefix = pop();
+ push('$prefix.$suffix');
+ }
+
+ @override
+ void handleType(Token beginToken, Token endToken) {
+ debugEvent("Type");
+ // ignore: strong_mode_down_cast_composite
+ List<TypeName> typeArguments = pop();
+ String name = pop();
+ push(new TypeName(name, typeArguments));
+ }
+}
+
+/// Parser intended for use with [MiniAstBuilder].
+class MiniAstParser extends Parser {
+ MiniAstParser(MiniAstBuilder listener) : super(listener);
+
+ Token parseArgumentsOpt(Token token) {
+ MiniAstBuilder listener = this.listener;
+ if (listener.inMetadata) {
+ return super.parseArgumentsOpt(token);
+ } else {
+ return skipArgumentsOpt(token);
+ }
+ }
+
+ Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) {
+ return skipFunctionBody(token, isExpression, allowAbstract);
+ }
+}
+
+/// "Mini AST" representation of a string literal.
+class StringLiteral extends Expression {
+ final String stringValue;
+
+ StringLiteral(this.stringValue);
+}
+
+/// "Mini AST" representation of a type name.
+class TypeName {
+ final String name;
+
+ final List<TypeName> typeArguments;
+
+ TypeName(this.name, this.typeArguments);
+}
+
+/// "Mini AST" representation of an expression which summary code generation
+/// need not be concerned about.
+class UnknownExpression extends Expression {}
« no previous file with comments | « pkg/analyzer/tool/summary/generate.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698