| 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 |