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

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

Issue 2711463005: Add contextual information about identifiers to the parser listener API. (Closed)
Patch Set: Fix broken import 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library fasta.analyzer.ast_builder; 5 library fasta.analyzer.ast_builder;
6 6
7 import 'package:front_end/src/fasta/scanner/token.dart' 7 import 'package:front_end/src/fasta/scanner/token.dart'
8 show BeginGroupToken, Token; 8 show BeginGroupToken, Token;
9 9
10 import 'package:analyzer/analyzer.dart'; 10 import 'package:analyzer/analyzer.dart';
(...skipping 11 matching lines...) Expand all
22 import '../errors.dart' show internalError; 22 import '../errors.dart' show internalError;
23 23
24 import '../source/scope_listener.dart' 24 import '../source/scope_listener.dart'
25 show JumpTargetKind, NullValue, Scope, ScopeListener; 25 show JumpTargetKind, NullValue, Scope, ScopeListener;
26 26
27 import '../kernel/kernel_builder.dart' 27 import '../kernel/kernel_builder.dart'
28 show Builder, KernelLibraryBuilder, ProcedureBuilder; 28 show Builder, KernelLibraryBuilder, ProcedureBuilder;
29 29
30 import '../parser/parser.dart' show optional; 30 import '../parser/parser.dart' show optional;
31 31
32 import '../parser/identifier_context.dart' show IdentifierContext;
33
32 import '../quote.dart'; 34 import '../quote.dart';
33 35
34 import '../source/outline_builder.dart' show asyncMarkerFromTokens; 36 import '../source/outline_builder.dart' show asyncMarkerFromTokens;
35 37
36 import 'element_store.dart' 38 import 'element_store.dart'
37 show 39 show
38 AnalyzerLocalVariableElemment, 40 AnalyzerLocalVariableElemment,
39 AnalyzerParameterElement, 41 AnalyzerParameterElement,
40 ElementStore, 42 ElementStore,
41 KernelClassElement; 43 KernelClassElement;
42 44
43 import 'token_utils.dart' show toAnalyzerToken; 45 import 'token_utils.dart' show toAnalyzerToken;
44 46
45 import 'analyzer.dart' show toKernel; 47 import 'analyzer.dart' show toKernel;
46 48
47 class AstBuilder extends ScopeListener { 49 class AstBuilder extends ScopeListener {
48 final AstFactory ast = standard.astFactory; 50 final AstFactory ast = standard.astFactory;
49 51
50 final KernelLibraryBuilder library; 52 final KernelLibraryBuilder library;
51 53
52 final Builder member; 54 final Builder member;
53 55
54 final ElementStore elementStore; 56 final ElementStore elementStore;
55 57
56 bool isFirstIdentifier = false;
57
58 @override 58 @override
59 final Uri uri; 59 final Uri uri;
60 60
61 /// If `true`, the first call to [handleIdentifier] should push a
62 /// List<SimpleIdentifier> on the stack, and [handleQualified] should append
63 /// to the list.
64 var accumulateIdentifierComponents = false;
65
66 AstBuilder(this.library, this.member, this.elementStore, Scope scope, 61 AstBuilder(this.library, this.member, this.elementStore, Scope scope,
67 [Uri uri]) 62 [Uri uri])
68 : uri = uri ?? library.fileUri, 63 : uri = uri ?? library.fileUri,
69 super(scope); 64 super(scope);
70 65
71 createJumpTarget(JumpTargetKind kind, int charOffset) { 66 createJumpTarget(JumpTargetKind kind, int charOffset) {
72 // TODO(ahe): Implement jump targets. 67 // TODO(ahe): Implement jump targets.
73 return null; 68 return null;
74 } 69 }
75 70
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 } 120 }
126 121
127 void endArguments(int count, Token beginToken, Token endToken) { 122 void endArguments(int count, Token beginToken, Token endToken) {
128 debugEvent("Arguments"); 123 debugEvent("Arguments");
129 List expressions = popList(count); 124 List expressions = popList(count);
130 ArgumentList arguments = ast.argumentList( 125 ArgumentList arguments = ast.argumentList(
131 toAnalyzerToken(beginToken), expressions, toAnalyzerToken(endToken)); 126 toAnalyzerToken(beginToken), expressions, toAnalyzerToken(endToken));
132 push(ast.methodInvocation(null, null, null, null, arguments)); 127 push(ast.methodInvocation(null, null, null, null, arguments));
133 } 128 }
134 129
135 void beginExpression(Token token) { 130 void handleIdentifier(Token token, IdentifierContext context) {
136 isFirstIdentifier = true;
137 }
138
139 void handleIdentifier(Token token) {
140 debugEvent("handleIdentifier"); 131 debugEvent("handleIdentifier");
141 String name = token.value; 132 String name = token.value;
142 SimpleIdentifier identifier = ast.simpleIdentifier(toAnalyzerToken(token)); 133 SimpleIdentifier identifier = ast.simpleIdentifier(toAnalyzerToken(token));
143 if (accumulateIdentifierComponents) { 134 if (context.inLibraryOrPartOfDeclaration) {
144 if (isFirstIdentifier) { 135 if (!context.isContinuation) {
145 push([identifier]); 136 push([identifier]);
146 } else { 137 } else {
147 push(identifier); 138 push(identifier);
148 } 139 }
149 } else { 140 } else {
150 if (isFirstIdentifier) { 141 if (context.isScopeReference) {
151 Builder builder = scope.lookup(name, token.charOffset, uri); 142 Builder builder = scope.lookup(name, token.charOffset, uri);
152 if (builder != null) { 143 if (builder != null) {
153 Element element = elementStore[builder]; 144 Element element = elementStore[builder];
154 assert(element != null); 145 assert(element != null);
155 identifier.staticElement = element; 146 identifier.staticElement = element;
156 } 147 }
157 } 148 }
158 push(identifier); 149 push(identifier);
159 } 150 }
160 isFirstIdentifier = false;
161 } 151 }
162 152
163 void endSend(Token token) { 153 void endSend(Token token) {
164 debugEvent("Send"); 154 debugEvent("Send");
165 MethodInvocation arguments = pop(); 155 MethodInvocation arguments = pop();
166 TypeArgumentList typeArguments = pop(); 156 TypeArgumentList typeArguments = pop();
167 if (arguments != null) { 157 if (arguments != null) {
168 if (typeArguments != null) { 158 if (typeArguments != null) {
169 arguments.typeArguments = typeArguments; 159 arguments.typeArguments = typeArguments;
170 } 160 }
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 void handleAsyncModifier(Token asyncToken, Token starToken) { 390 void handleAsyncModifier(Token asyncToken, Token starToken) {
401 debugEvent("AsyncModifier"); 391 debugEvent("AsyncModifier");
402 push(asyncMarkerFromTokens(asyncToken, starToken)); 392 push(asyncMarkerFromTokens(asyncToken, starToken));
403 } 393 }
404 394
405 void endAwaitExpression(Token beginToken, Token endToken) { 395 void endAwaitExpression(Token beginToken, Token endToken) {
406 debugEvent("AwaitExpression"); 396 debugEvent("AwaitExpression");
407 push(ast.awaitExpression(toAnalyzerToken(beginToken), pop())); 397 push(ast.awaitExpression(toAnalyzerToken(beginToken), pop()));
408 } 398 }
409 399
410 void beginLiteralSymbol(Token token) {
411 isFirstIdentifier = false;
412 }
413
414 void handleLiteralBool(Token token) { 400 void handleLiteralBool(Token token) {
415 debugEvent("LiteralBool"); 401 debugEvent("LiteralBool");
416 bool value = identical(token.stringValue, "true"); 402 bool value = identical(token.stringValue, "true");
417 assert(value || identical(token.stringValue, "false")); 403 assert(value || identical(token.stringValue, "false"));
418 push(ast.booleanLiteral(toAnalyzerToken(token), value)); 404 push(ast.booleanLiteral(toAnalyzerToken(token), value));
419 } 405 }
420 406
421 void handleLiteralDouble(Token token) { 407 void handleLiteralDouble(Token token) {
422 debugEvent("LiteralDouble"); 408 debugEvent("LiteralDouble");
423 push(ast.doubleLiteral(toAnalyzerToken(token), double.parse(token.value))); 409 push(ast.doubleLiteral(toAnalyzerToken(token), double.parse(token.value)));
(...skipping 30 matching lines...) Expand all
454 push(ast.symbolLiteral(toAnalyzerToken(hashToken), components)); 440 push(ast.symbolLiteral(toAnalyzerToken(hashToken), components));
455 } 441 }
456 442
457 void endType(Token beginToken, Token endToken) { 443 void endType(Token beginToken, Token endToken) {
458 debugEvent("Type"); 444 debugEvent("Type");
459 TypeArgumentList arguments = pop(); 445 TypeArgumentList arguments = pop();
460 Identifier name = pop(); 446 Identifier name = pop();
461 // TODO(paulberry,ahe): what if the type doesn't resolve to a class 447 // TODO(paulberry,ahe): what if the type doesn't resolve to a class
462 // element? 448 // element?
463 KernelClassElement cls = name.staticElement; 449 KernelClassElement cls = name.staticElement;
464 if (cls == null) { 450 push(ast.typeName(name, arguments)..type = cls?.rawType);
465 // TODO(paulberry): This is a kludge. Ideally we should already have
466 // set the static element at the time that handleIdentifier was called.
467 Builder builder = scope.lookup(name.name, beginToken.charOffset, uri);
468 if (builder == null) {
469 internalError("Undefined name: $name");
470 }
471 cls = elementStore[builder];
472 assert(cls != null);
473 if (name is SimpleIdentifier) {
474 name.staticElement = cls;
475 }
476 }
477 push(ast.typeName(name, arguments)..type = cls.rawType);
478 } 451 }
479 452
480 void handleAsOperator(Token operator, Token endToken) { 453 void handleAsOperator(Token operator, Token endToken) {
481 debugEvent("AsOperator"); 454 debugEvent("AsOperator");
482 TypeName type = pop(); 455 TypeName type = pop();
483 Expression expression = pop(); 456 Expression expression = pop();
484 push(ast.asExpression(expression, toAnalyzerToken(operator), type)); 457 push(ast.asExpression(expression, toAnalyzerToken(operator), type));
485 } 458 }
486 459
487 void handleIsOperator(Token operator, Token not, Token endToken) { 460 void handleIsOperator(Token operator, Token not, Token endToken) {
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 debugEvent("MixinApplication"); 843 debugEvent("MixinApplication");
871 List<TypeName> mixinTypes = pop(); 844 List<TypeName> mixinTypes = pop();
872 // TODO(paulberry,ahe): the parser doesn't give us enough information to 845 // TODO(paulberry,ahe): the parser doesn't give us enough information to
873 // locate the "with" keyword. 846 // locate the "with" keyword.
874 Token withKeyword; 847 Token withKeyword;
875 TypeName supertype = pop(); 848 TypeName supertype = pop();
876 push(new _MixinApplication(supertype, withKeyword, mixinTypes)); 849 push(new _MixinApplication(supertype, withKeyword, mixinTypes));
877 } 850 }
878 851
879 @override 852 @override
880 void endNamedMixinApplication( 853 void endNamedMixinApplication(Token beginToken, Token equalsToken,
881 Token beginToken, Token equalsToken, Token implementsKeyword, Token endTok en) { 854 Token implementsKeyword, Token endToken) {
882 debugEvent("NamedMixinApplication"); 855 debugEvent("NamedMixinApplication");
883 ImplementsClause implementsClause; 856 ImplementsClause implementsClause;
884 if (implementsKeyword != null) { 857 if (implementsKeyword != null) {
885 List<TypeName> interfaces = pop(); 858 List<TypeName> interfaces = pop();
886 implementsClause = 859 implementsClause =
887 ast.implementsClause(toAnalyzerToken(implementsKeyword), interfaces); 860 ast.implementsClause(toAnalyzerToken(implementsKeyword), interfaces);
888 } 861 }
889 _MixinApplication mixinApplication = pop(); 862 _MixinApplication mixinApplication = pop();
890 var superclass = mixinApplication.supertype; 863 var superclass = mixinApplication.supertype;
891 var withClause = ast.withClause( 864 var withClause = ast.withClause(
(...skipping 24 matching lines...) Expand all
916 typeParameters, 889 typeParameters,
917 equals, 890 equals,
918 abstractKeyword, 891 abstractKeyword,
919 superclass, 892 superclass,
920 withClause, 893 withClause,
921 implementsClause, 894 implementsClause,
922 toAnalyzerToken(endToken))); 895 toAnalyzerToken(endToken)));
923 } 896 }
924 897
925 @override 898 @override
926 void beginLibraryName(Token token) {
927 accumulateIdentifierComponents = true;
928 isFirstIdentifier = true;
929 }
930
931 @override
932 void endLibraryName(Token libraryKeyword, Token semicolon) { 899 void endLibraryName(Token libraryKeyword, Token semicolon) {
933 debugEvent("LibraryName"); 900 debugEvent("LibraryName");
934 List<SimpleIdentifier> libraryName = pop(); 901 List<SimpleIdentifier> libraryName = pop();
935 var name = ast.libraryIdentifier(libraryName); 902 var name = ast.libraryIdentifier(libraryName);
936 List<Annotation> metadata = pop(); 903 List<Annotation> metadata = pop();
937 // TODO(paulberry): capture doc comments. See dartbug.com/28851. 904 // TODO(paulberry): capture doc comments. See dartbug.com/28851.
938 Comment comment = null; 905 Comment comment = null;
939 push(ast.libraryDirective(comment, metadata, 906 push(ast.libraryDirective(comment, metadata,
940 toAnalyzerToken(libraryKeyword), name, toAnalyzerToken(semicolon))); 907 toAnalyzerToken(libraryKeyword), name, toAnalyzerToken(semicolon)));
941 accumulateIdentifierComponents = false;
942 } 908 }
943 909
944 @override 910 @override
945 void handleQualified(Token period) { 911 void handleQualified(Token period) {
946 SimpleIdentifier identifier = pop(); 912 SimpleIdentifier identifier = pop();
947 if (accumulateIdentifierComponents) { 913 var prefix = pop();
948 List<SimpleIdentifier> list = pop(); 914 if (prefix is List) {
949 list.add(identifier); 915 // We're just accumulating components into a list.
950 push(list); 916 prefix.add(identifier);
917 push(prefix);
918 } else if (prefix is SimpleIdentifier) {
919 // TODO(paulberry): resolve [identifier].
920 push(ast.prefixedIdentifier(prefix, toAnalyzerToken(period), identifier));
951 } else { 921 } else {
952 var prefix = pop(); 922 // TODO(paulberry): implement.
953 if (prefix is SimpleIdentifier) { 923 logEvent('Qualified with >1 dot');
954 // TODO(paulberry): resolve [identifier].
955 push(ast.prefixedIdentifier(prefix, toAnalyzerToken(period), identifier) );
956 } else {
957 // TODO(paulberry): implement.
958 logEvent('Qualified with >1 dot');
959 }
960 } 924 }
961 } 925 }
962 926
963 @override 927 @override
964 void endPart(Token partKeyword, Token semicolon) { 928 void endPart(Token partKeyword, Token semicolon) {
965 debugEvent("Part"); 929 debugEvent("Part");
966 StringLiteral uri = pop(); 930 StringLiteral uri = pop();
967 List<Annotation> metadata = pop(); 931 List<Annotation> metadata = pop();
968 // TODO(paulberry): capture doc comments. See dartbug.com/28851. 932 // TODO(paulberry): capture doc comments. See dartbug.com/28851.
969 Comment comment = null; 933 Comment comment = null;
970 push(ast.partDirective(comment, metadata, toAnalyzerToken(partKeyword), uri, 934 push(ast.partDirective(comment, metadata, toAnalyzerToken(partKeyword), uri,
971 toAnalyzerToken(semicolon))); 935 toAnalyzerToken(semicolon)));
972 } 936 }
973 937
974 @override 938 @override
975 void beginPartOf(Token token) {
976 accumulateIdentifierComponents = true;
977 isFirstIdentifier = true;
978 }
979
980 @override
981 void endPartOf(Token partKeyword, Token semicolon) { 939 void endPartOf(Token partKeyword, Token semicolon) {
982 debugEvent("PartOf"); 940 debugEvent("PartOf");
983 List<SimpleIdentifier> libraryName = pop(); 941 List<SimpleIdentifier> libraryName = pop();
984 var name = ast.libraryIdentifier(libraryName); 942 var name = ast.libraryIdentifier(libraryName);
985 StringLiteral uri = null; // TODO(paulberry) 943 StringLiteral uri = null; // TODO(paulberry)
986 // TODO(paulberry,ahe): seems hacky. It would be nice if the parser passed 944 // TODO(paulberry,ahe): seems hacky. It would be nice if the parser passed
987 // in a reference to the "of" keyword. 945 // in a reference to the "of" keyword.
988 var ofKeyword = partKeyword.next; 946 var ofKeyword = partKeyword.next;
989 List<Annotation> metadata = pop(); 947 List<Annotation> metadata = pop();
990 // TODO(paulberry): capture doc comments. See dartbug.com/28851. 948 // TODO(paulberry): capture doc comments. See dartbug.com/28851.
991 Comment comment = null; 949 Comment comment = null;
992 push(ast.partOfDirective(comment, metadata, toAnalyzerToken(partKeyword), 950 push(ast.partOfDirective(comment, metadata, toAnalyzerToken(partKeyword),
993 toAnalyzerToken(ofKeyword), uri, name, toAnalyzerToken(semicolon))); 951 toAnalyzerToken(ofKeyword), uri, name, toAnalyzerToken(semicolon)));
994 accumulateIdentifierComponents = false;
995 } 952 }
996 953
997 void endUnnamedFunction(Token token) { 954 void endUnnamedFunction(Token token) {
998 // TODO(paulberry): set up scopes properly to resolve parameters and type 955 // TODO(paulberry): set up scopes properly to resolve parameters and type
999 // variables. Note that this is tricky due to the handling of initializers 956 // variables. Note that this is tricky due to the handling of initializers
1000 // in constructors, so the logic should be shared with BodyBuilder as much 957 // in constructors, so the logic should be shared with BodyBuilder as much
1001 // as possible. 958 // as possible.
1002 debugEvent("UnnamedFunction"); 959 debugEvent("UnnamedFunction");
1003 var body = _endFunctionBody(); 960 var body = _endFunctionBody();
1004 FormalParameterList parameters = pop(); 961 FormalParameterList parameters = pop();
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1112 @override 1069 @override
1113 void endMember() { 1070 void endMember() {
1114 debugEvent("Member"); 1071 debugEvent("Member");
1115 } 1072 }
1116 1073
1117 @override 1074 @override
1118 void handleVoidKeyword(Token token) { 1075 void handleVoidKeyword(Token token) {
1119 debugEvent("VoidKeyword"); 1076 debugEvent("VoidKeyword");
1120 // TODO(paulberry): is this sufficient, or do we need to hook the "void" 1077 // TODO(paulberry): is this sufficient, or do we need to hook the "void"
1121 // keyword up to an element? 1078 // keyword up to an element?
1122 handleIdentifier(token); 1079 handleIdentifier(token, IdentifierContext.typeReference);
1123 handleNoTypeArguments(token); 1080 handleNoTypeArguments(token);
1124 endType(token, token); 1081 endType(token, token);
1125 } 1082 }
1126 1083
1127 @override 1084 @override
1128 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) { 1085 void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
1129 debugEvent("FunctionTypeAlias"); 1086 debugEvent("FunctionTypeAlias");
1130 FormalParameterList parameters = pop(); 1087 FormalParameterList parameters = pop();
1131 TypeParameterList typeParameters = pop(); 1088 TypeParameterList typeParameters = pop();
1132 SimpleIdentifier name = pop(); 1089 SimpleIdentifier name = pop();
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1169 /// [ClassDeclaration] or [ClassTypeAlias] object. 1126 /// [ClassDeclaration] or [ClassTypeAlias] object.
1170 class _MixinApplication { 1127 class _MixinApplication {
1171 final TypeName supertype; 1128 final TypeName supertype;
1172 1129
1173 final Token withKeyword; 1130 final Token withKeyword;
1174 1131
1175 final List<TypeName> mixinTypes; 1132 final List<TypeName> mixinTypes;
1176 1133
1177 _MixinApplication(this.supertype, this.withKeyword, this.mixinTypes); 1134 _MixinApplication(this.supertype, this.withKeyword, this.mixinTypes);
1178 } 1135 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698