OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |