| 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.body_builder; | 5 library fasta.body_builder; |
| 6 | 6 |
| 7 import '../fasta_codes.dart' | 7 import '../fasta_codes.dart' |
| 8 show FastaMessage, codeExpectedButGot, codeExpectedFunctionBody; | 8 show FastaMessage, codeExpectedButGot, codeExpectedFunctionBody; |
| 9 | 9 |
| 10 import '../parser/parser.dart' show FormalParameterType, MemberKind, optional; | 10 import '../parser/parser.dart' show FormalParameterType, MemberKind, optional; |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 addCompileTimeError(-1, "Label not found: '$name'."); | 299 addCompileTimeError(-1, "Label not found: '$name'."); |
| 300 } else { | 300 } else { |
| 301 outerSwitchScope.forwardDeclareLabel(name, builder); | 301 outerSwitchScope.forwardDeclareLabel(name, builder); |
| 302 } | 302 } |
| 303 }); | 303 }); |
| 304 } | 304 } |
| 305 switchScope = outerSwitchScope; | 305 switchScope = outerSwitchScope; |
| 306 } | 306 } |
| 307 | 307 |
| 308 void declareVariable(VariableDeclaration variable) { | 308 void declareVariable(VariableDeclaration variable) { |
| 309 // ignore: UNUSED_LOCAL_VARIABLE |
| 310 Statement discardedStatement; |
| 311 String name = variable.name; |
| 312 int offset = variable.fileOffset; |
| 313 if (scope.local[name] != null) { |
| 314 // This reports an error for duplicated declarations in the same scope: |
| 315 // `{ var x; var x; }` |
| 316 discardedStatement = pop(); // TODO(ahe): Issue 29717. |
| 317 push(buildCompileTimeErrorStatement( |
| 318 "'$name' already declared in this scope.", offset)); |
| 319 return; |
| 320 } |
| 309 InputError error = scope.declare( | 321 InputError error = scope.declare( |
| 310 variable.name, | 322 variable.name, |
| 311 new KernelVariableBuilder( | 323 new KernelVariableBuilder( |
| 312 variable, member ?? classBuilder ?? library, uri), | 324 variable, member ?? classBuilder ?? library, uri), |
| 313 variable.fileOffset, | 325 variable.fileOffset, |
| 314 uri); | 326 uri); |
| 315 if (error != null) { | 327 if (error != null) { |
| 316 addCompileTimeError( | 328 // This case is different from the above error. In this case, the problem |
| 317 variable.fileOffset, | 329 // is using `x` before it's declared: `{ var x; { print(x); var x; |
| 318 "Can't declare '${variable.name}' because it was already used in " | 330 // }}`. In this case, we want two errors, the `x` in `print(x)` and the |
| 319 "this scope."); | 331 // second (or innermost declaration) of `x`. |
| 332 discardedStatement = pop(); // TODO(ahe): Issue 29717. |
| 333 |
| 334 // Reports the error on the last declaration of `x`. |
| 335 push(buildCompileTimeErrorStatement( |
| 336 "Can't declare '$name' because it was already used in this scope.", |
| 337 offset)); |
| 338 |
| 339 // Reports the error on `print(x)`. |
| 320 library.addCompileTimeError(error.charOffset, error.error, | 340 library.addCompileTimeError(error.charOffset, error.error, |
| 321 fileUri: error.uri); | 341 fileUri: error.uri); |
| 322 } | 342 } |
| 323 } | 343 } |
| 324 | 344 |
| 325 @override | 345 @override |
| 326 JumpTarget createJumpTarget(JumpTargetKind kind, int charOffset) { | 346 JumpTarget createJumpTarget(JumpTargetKind kind, int charOffset) { |
| 327 return new JumpTarget(kind, functionNestingLevel, member, charOffset); | 347 return new JumpTarget(kind, functionNestingLevel, member, charOffset); |
| 328 } | 348 } |
| 329 | 349 |
| (...skipping 1341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1671 count--; | 1691 count--; |
| 1672 } | 1692 } |
| 1673 FormalParameters formals = new FormalParameters( | 1693 FormalParameters formals = new FormalParameters( |
| 1674 popList(count) ?? <VariableDeclaration>[], | 1694 popList(count) ?? <VariableDeclaration>[], |
| 1675 optional, | 1695 optional, |
| 1676 beginToken.charOffset); | 1696 beginToken.charOffset); |
| 1677 push(formals); | 1697 push(formals); |
| 1678 if ((inCatchClause || functionNestingLevel != 0) && | 1698 if ((inCatchClause || functionNestingLevel != 0) && |
| 1679 kind != MemberKind.GeneralizedFunctionType) { | 1699 kind != MemberKind.GeneralizedFunctionType) { |
| 1680 enterLocalScope(formals.computeFormalParameterScope( | 1700 enterLocalScope(formals.computeFormalParameterScope( |
| 1681 scope, member ?? classBuilder ?? library)); | 1701 scope, member ?? classBuilder ?? library, this)); |
| 1682 } | 1702 } |
| 1683 } | 1703 } |
| 1684 | 1704 |
| 1685 @override | 1705 @override |
| 1686 void beginCatchClause(Token token) { | 1706 void beginCatchClause(Token token) { |
| 1687 debugEvent("beginCatchClause"); | 1707 debugEvent("beginCatchClause"); |
| 1688 inCatchClause = true; | 1708 inCatchClause = true; |
| 1689 } | 1709 } |
| 1690 | 1710 |
| 1691 @override | 1711 @override |
| (...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2124 typeParameters: typeParameters, asyncMarker: asyncModifier) | 2144 typeParameters: typeParameters, asyncMarker: asyncModifier) |
| 2125 ..fileOffset = formals.charOffset | 2145 ..fileOffset = formals.charOffset |
| 2126 ..fileEndOffset = endToken.charOffset)); | 2146 ..fileEndOffset = endToken.charOffset)); |
| 2127 } | 2147 } |
| 2128 | 2148 |
| 2129 @override | 2149 @override |
| 2130 void endFunctionDeclaration(Token token) { | 2150 void endFunctionDeclaration(Token token) { |
| 2131 debugEvent("FunctionDeclaration"); | 2151 debugEvent("FunctionDeclaration"); |
| 2132 FunctionNode function = pop(); | 2152 FunctionNode function = pop(); |
| 2133 exitLocalScope(); | 2153 exitLocalScope(); |
| 2134 FunctionDeclaration declaration = pop(); | 2154 var declaration = pop(); |
| 2135 function.returnType = pop() ?? const DynamicType(); | 2155 var returnType = pop() ?? const DynamicType(); |
| 2136 declaration.variable.type = function.functionType; | |
| 2137 pop(); // Modifiers. | 2156 pop(); // Modifiers. |
| 2138 exitFunction(); | 2157 exitFunction(); |
| 2139 declaration.function = function; | 2158 if (declaration is FunctionDeclaration) { |
| 2140 function.parent = declaration; | 2159 function.returnType = returnType; |
| 2160 declaration.variable.type = function.functionType; |
| 2161 declaration.function = function; |
| 2162 function.parent = declaration; |
| 2163 } else { |
| 2164 // If [declaration] isn't a [FunctionDeclaration], it must be because |
| 2165 // there was a compile-time error. |
| 2166 |
| 2167 // TODO(paulberry): ensure that when integrating with analyzer, type |
| 2168 // inference is still performed for the dropped declaration. |
| 2169 assert(library.compileTimeErrors.isNotEmpty); |
| 2170 } |
| 2141 push(declaration); | 2171 push(declaration); |
| 2142 } | 2172 } |
| 2143 | 2173 |
| 2144 @override | 2174 @override |
| 2145 void endUnnamedFunction(Token beginToken, Token token) { | 2175 void endUnnamedFunction(Token beginToken, Token token) { |
| 2146 debugEvent("UnnamedFunction"); | 2176 debugEvent("UnnamedFunction"); |
| 2147 Statement body = popStatement(); | 2177 Statement body = popStatement(); |
| 2148 AsyncMarker asyncModifier = pop(); | 2178 AsyncMarker asyncModifier = pop(); |
| 2149 exitLocalScope(); | 2179 exitLocalScope(); |
| 2150 FormalParameters formals = pop(); | 2180 FormalParameters formals = pop(); |
| (...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2571 if (trailing.contains(token.stringValue) && trailing.contains(expected)) { | 2601 if (trailing.contains(token.stringValue) && trailing.contains(expected)) { |
| 2572 handleRecoverableError(token, message); | 2602 handleRecoverableError(token, message); |
| 2573 return newSyntheticToken(token); | 2603 return newSyntheticToken(token); |
| 2574 } | 2604 } |
| 2575 } | 2605 } |
| 2576 return super.handleUnrecoverableError(token, message); | 2606 return super.handleUnrecoverableError(token, message); |
| 2577 } | 2607 } |
| 2578 | 2608 |
| 2579 @override | 2609 @override |
| 2580 Expression buildCompileTimeError(error, [int charOffset = -1]) { | 2610 Expression buildCompileTimeError(error, [int charOffset = -1]) { |
| 2611 // TODO(ahe): This method should be passed the erroneous expression, wrap |
| 2612 // it in a class (TBD) from which the erroneous expression can be easily |
| 2613 // extracted. Similar for statements and initializers. See also [issue |
| 2614 // 29717](https://github.com/dart-lang/sdk/issues/29717) |
| 2581 addCompileTimeError(charOffset, error); | 2615 addCompileTimeError(charOffset, error); |
| 2582 String message = formatUnexpected(uri, charOffset, error); | 2616 String message = formatUnexpected(uri, charOffset, error); |
| 2583 Builder constructor = library.loader.getCompileTimeError(); | 2617 Builder constructor = library.loader.getCompileTimeError(); |
| 2584 return new Throw(buildStaticInvocation(constructor.target, | 2618 return new Throw(buildStaticInvocation(constructor.target, |
| 2585 astFactory.arguments(<Expression>[new StringLiteral(message)]))); | 2619 astFactory.arguments(<Expression>[new StringLiteral(message)]))); |
| 2586 } | 2620 } |
| 2587 | 2621 |
| 2588 Expression buildAbstractClassInstantiationError(String className, | 2622 Expression buildAbstractClassInstantiationError(String className, |
| 2589 [int charOffset = -1]) { | 2623 [int charOffset = -1]) { |
| 2590 warning("The class '$className' is abstract and can't be instantiated.", | 2624 warning("The class '$className' is abstract and can't be instantiated.", |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2635 debugEvent("Operator"); | 2669 debugEvent("Operator"); |
| 2636 push(new Operator(token.stringValue)..fileOffset = token.charOffset); | 2670 push(new Operator(token.stringValue)..fileOffset = token.charOffset); |
| 2637 } | 2671 } |
| 2638 | 2672 |
| 2639 @override | 2673 @override |
| 2640 void handleSymbolVoid(Token token) { | 2674 void handleSymbolVoid(Token token) { |
| 2641 debugEvent("SymbolVoid"); | 2675 debugEvent("SymbolVoid"); |
| 2642 push(new Identifier(token)); | 2676 push(new Identifier(token)); |
| 2643 } | 2677 } |
| 2644 | 2678 |
| 2679 @override |
| 2645 dynamic addCompileTimeError(int charOffset, String message, | 2680 dynamic addCompileTimeError(int charOffset, String message, |
| 2646 {bool silent: false}) { | 2681 {bool silent: false}) { |
| 2647 // TODO(ahe): If constantExpressionRequired is set, set it to false to | 2682 // TODO(ahe): If constantExpressionRequired is set, set it to false to |
| 2648 // avoid a long list of errors. | 2683 // avoid a long list of errors. |
| 2649 return library.addCompileTimeError(charOffset, message, fileUri: uri); | 2684 return library.addCompileTimeError(charOffset, message, fileUri: uri); |
| 2650 } | 2685 } |
| 2651 | 2686 |
| 2652 @override | 2687 @override |
| 2653 void handleInvalidFunctionBody(Token token) { | 2688 void handleInvalidFunctionBody(Token token) { |
| 2654 if (member.isNative) { | 2689 if (member.isNative) { |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3118 namedParameters.add(new NamedType(parameter.name, parameter.type)); | 3153 namedParameters.add(new NamedType(parameter.name, parameter.type)); |
| 3119 } | 3154 } |
| 3120 namedParameters.sort(); | 3155 namedParameters.sort(); |
| 3121 } | 3156 } |
| 3122 } | 3157 } |
| 3123 return new FunctionType(positionalParameters, returnType, | 3158 return new FunctionType(positionalParameters, returnType, |
| 3124 namedParameters: namedParameters, | 3159 namedParameters: namedParameters, |
| 3125 requiredParameterCount: requiredParameterCount); | 3160 requiredParameterCount: requiredParameterCount); |
| 3126 } | 3161 } |
| 3127 | 3162 |
| 3128 Scope computeFormalParameterScope(Scope parent, Builder builder) { | 3163 Scope computeFormalParameterScope( |
| 3164 Scope parent, Builder builder, BuilderHelper helper) { |
| 3129 if (required.length == 0 && optional == null) return parent; | 3165 if (required.length == 0 && optional == null) return parent; |
| 3130 Map<String, Builder> local = <String, Builder>{}; | 3166 Map<String, Builder> local = <String, Builder>{}; |
| 3167 |
| 3131 for (VariableDeclaration parameter in required) { | 3168 for (VariableDeclaration parameter in required) { |
| 3169 if (local[parameter.name] != null) { |
| 3170 helper.addCompileTimeError(parameter.fileOffset, "Duplicated name."); |
| 3171 } |
| 3132 local[parameter.name] = | 3172 local[parameter.name] = |
| 3133 new KernelVariableBuilder(parameter, builder, builder.fileUri); | 3173 new KernelVariableBuilder(parameter, builder, builder.fileUri); |
| 3134 } | 3174 } |
| 3135 if (optional != null) { | 3175 if (optional != null) { |
| 3136 for (VariableDeclaration parameter in optional.formals) { | 3176 for (VariableDeclaration parameter in optional.formals) { |
| 3177 if (local[parameter.name] != null) { |
| 3178 helper.addCompileTimeError(parameter.fileOffset, "Duplicated name."); |
| 3179 } |
| 3137 local[parameter.name] = | 3180 local[parameter.name] = |
| 3138 new KernelVariableBuilder(parameter, builder, builder.fileUri); | 3181 new KernelVariableBuilder(parameter, builder, builder.fileUri); |
| 3139 } | 3182 } |
| 3140 } | 3183 } |
| 3141 return new Scope(local, null, parent, isModifiable: false); | 3184 return new Scope(local, null, parent, isModifiable: false); |
| 3142 } | 3185 } |
| 3143 } | 3186 } |
| 3144 | 3187 |
| 3145 /// Returns a block like this: | 3188 /// Returns a block like this: |
| 3146 /// | 3189 /// |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3193 if (starToken == null) { | 3236 if (starToken == null) { |
| 3194 return AsyncMarker.Async; | 3237 return AsyncMarker.Async; |
| 3195 } else { | 3238 } else { |
| 3196 assert(identical(starToken.stringValue, "*")); | 3239 assert(identical(starToken.stringValue, "*")); |
| 3197 return AsyncMarker.AsyncStar; | 3240 return AsyncMarker.AsyncStar; |
| 3198 } | 3241 } |
| 3199 } else { | 3242 } else { |
| 3200 return internalError("Unknown async modifier: $asyncToken"); | 3243 return internalError("Unknown async modifier: $asyncToken"); |
| 3201 } | 3244 } |
| 3202 } | 3245 } |
| OLD | NEW |