| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 analyzer.src.generated.resolver; | 5 library analyzer.src.generated.resolver; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
| 11 import 'package:analyzer/dart/ast/visitor.dart'; | 11 import 'package:analyzer/dart/ast/visitor.dart'; |
| 12 import 'package:analyzer/dart/element/element.dart'; | 12 import 'package:analyzer/dart/element/element.dart'; |
| 13 import 'package:analyzer/dart/element/type.dart'; | 13 import 'package:analyzer/dart/element/type.dart'; |
| 14 import 'package:analyzer/dart/element/visitor.dart'; | 14 import 'package:analyzer/dart/element/visitor.dart'; |
| 15 import 'package:analyzer/error/error.dart'; | 15 import 'package:analyzer/error/error.dart'; |
| 16 import 'package:analyzer/error/listener.dart'; | 16 import 'package:analyzer/error/listener.dart'; |
| 17 import 'package:analyzer/exception/exception.dart'; | 17 import 'package:analyzer/exception/exception.dart'; |
| 18 import 'package:analyzer/src/dart/ast/ast.dart'; | 18 import 'package:analyzer/src/dart/ast/ast.dart'; |
| 19 import 'package:analyzer/src/dart/ast/utilities.dart'; | 19 import 'package:analyzer/src/dart/ast/utilities.dart'; |
| 20 import 'package:analyzer/src/dart/element/element.dart'; | 20 import 'package:analyzer/src/dart/element/element.dart'; |
| 21 import 'package:analyzer/src/dart/element/type.dart'; | 21 import 'package:analyzer/src/dart/element/type.dart'; |
| 22 import 'package:analyzer/src/dart/element/utilities.dart'; | |
| 23 import 'package:analyzer/src/dart/resolver/inheritance_manager.dart'; | 22 import 'package:analyzer/src/dart/resolver/inheritance_manager.dart'; |
| 24 import 'package:analyzer/src/dart/resolver/scope.dart'; | 23 import 'package:analyzer/src/dart/resolver/scope.dart'; |
| 25 import 'package:analyzer/src/error/codes.dart'; | 24 import 'package:analyzer/src/error/codes.dart'; |
| 26 import 'package:analyzer/src/generated/constant.dart'; | 25 import 'package:analyzer/src/generated/constant.dart'; |
| 27 import 'package:analyzer/src/generated/element_resolver.dart'; | 26 import 'package:analyzer/src/generated/element_resolver.dart'; |
| 28 import 'package:analyzer/src/generated/engine.dart'; | 27 import 'package:analyzer/src/generated/engine.dart'; |
| 29 import 'package:analyzer/src/generated/error_verifier.dart'; | 28 import 'package:analyzer/src/generated/error_verifier.dart'; |
| 30 import 'package:analyzer/src/generated/source.dart'; | 29 import 'package:analyzer/src/generated/source.dart'; |
| 31 import 'package:analyzer/src/generated/static_type_analyzer.dart'; | 30 import 'package:analyzer/src/generated/static_type_analyzer.dart'; |
| 32 import 'package:analyzer/src/generated/type_system.dart'; | 31 import 'package:analyzer/src/generated/type_system.dart'; |
| (...skipping 2227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2260 } | 2259 } |
| 2261 if (element is PropertyAccessorElement) { | 2260 if (element is PropertyAccessorElement) { |
| 2262 PropertyInducingElement variable = element.variable; | 2261 PropertyInducingElement variable = element.variable; |
| 2263 return variable != null && variable.isConst; | 2262 return variable != null && variable.isConst; |
| 2264 } | 2263 } |
| 2265 return false; | 2264 return false; |
| 2266 } | 2265 } |
| 2267 } | 2266 } |
| 2268 | 2267 |
| 2269 /** | 2268 /** |
| 2270 * A visitor that resolves declarations in an AST structure to already built | |
| 2271 * elements. | |
| 2272 * | |
| 2273 * The resulting AST must have everything resolved that would have been resolved | |
| 2274 * by a [CompilationUnitBuilder] (that is, must be a valid [RESOLVED_UNIT1]). | |
| 2275 * This class must not assume that the [CompilationUnitElement] passed to it is | |
| 2276 * any more complete than a [COMPILATION_UNIT_ELEMENT]. | |
| 2277 */ | |
| 2278 class DeclarationResolver extends RecursiveAstVisitor<Object> | |
| 2279 with ExistingElementResolver { | |
| 2280 /** | |
| 2281 * The analysis context containing the sources to be analyzed. | |
| 2282 */ | |
| 2283 AnalysisContext _context; | |
| 2284 | |
| 2285 /** | |
| 2286 * The elements that are reachable from the compilation unit element. When a | |
| 2287 * compilation unit has been resolved, this set should be empty. | |
| 2288 */ | |
| 2289 Set<Element> _expectedElements; | |
| 2290 | |
| 2291 /** | |
| 2292 * The function type alias containing the AST nodes being visited, or `null` | |
| 2293 * if we are not in the scope of a function type alias. | |
| 2294 */ | |
| 2295 FunctionTypeAliasElement _enclosingAlias; | |
| 2296 | |
| 2297 /** | |
| 2298 * The class containing the AST nodes being visited, or `null` if we are not | |
| 2299 * in the scope of a class. | |
| 2300 */ | |
| 2301 ClassElement _enclosingClass; | |
| 2302 | |
| 2303 /** | |
| 2304 * The method or function containing the AST nodes being visited, or `null` if | |
| 2305 * we are not in the scope of a method or function. | |
| 2306 */ | |
| 2307 ExecutableElement _enclosingExecutable; | |
| 2308 | |
| 2309 /** | |
| 2310 * The parameter containing the AST nodes being visited, or `null` if we are | |
| 2311 * not in the scope of a parameter. | |
| 2312 */ | |
| 2313 ParameterElement _enclosingParameter; | |
| 2314 | |
| 2315 /** | |
| 2316 * Resolve the declarations within the given compilation [unit] to the | |
| 2317 * elements rooted at the given [element]. Throw an [ElementMismatchException] | |
| 2318 * if the element model and compilation unit do not match each other. | |
| 2319 */ | |
| 2320 void resolve(CompilationUnit unit, CompilationUnitElement element) { | |
| 2321 _context = element.context; | |
| 2322 ElementGatherer gatherer = new ElementGatherer(); | |
| 2323 element.accept(gatherer); | |
| 2324 _expectedElements = gatherer.elements; | |
| 2325 _enclosingUnit = element; | |
| 2326 _expectedElements.remove(element); | |
| 2327 unit.element = element; | |
| 2328 unit.accept(this); | |
| 2329 _validateResolution(); | |
| 2330 } | |
| 2331 | |
| 2332 @override | |
| 2333 Object visitCatchClause(CatchClause node) { | |
| 2334 SimpleIdentifier exceptionParameter = node.exceptionParameter; | |
| 2335 if (exceptionParameter != null) { | |
| 2336 List<LocalVariableElement> localVariables = | |
| 2337 _enclosingExecutable.localVariables; | |
| 2338 _findIdentifier(localVariables, exceptionParameter); | |
| 2339 SimpleIdentifier stackTraceParameter = node.stackTraceParameter; | |
| 2340 if (stackTraceParameter != null) { | |
| 2341 _findIdentifier(localVariables, stackTraceParameter); | |
| 2342 } | |
| 2343 } | |
| 2344 return super.visitCatchClause(node); | |
| 2345 } | |
| 2346 | |
| 2347 @override | |
| 2348 Object visitClassDeclaration(ClassDeclaration node) { | |
| 2349 ClassElement outerClass = _enclosingClass; | |
| 2350 try { | |
| 2351 SimpleIdentifier className = node.name; | |
| 2352 _enclosingClass = _findIdentifier(_enclosingUnit.types, className); | |
| 2353 super.visitClassDeclaration(node); | |
| 2354 _resolveMetadata(node, node.metadata, _enclosingClass); | |
| 2355 return null; | |
| 2356 } finally { | |
| 2357 _enclosingClass = outerClass; | |
| 2358 } | |
| 2359 } | |
| 2360 | |
| 2361 @override | |
| 2362 Object visitClassTypeAlias(ClassTypeAlias node) { | |
| 2363 ClassElement outerClass = _enclosingClass; | |
| 2364 try { | |
| 2365 SimpleIdentifier className = node.name; | |
| 2366 _enclosingClass = _findIdentifier(_enclosingUnit.types, className); | |
| 2367 super.visitClassTypeAlias(node); | |
| 2368 _resolveMetadata(node, node.metadata, _enclosingClass); | |
| 2369 return null; | |
| 2370 } finally { | |
| 2371 _enclosingClass = outerClass; | |
| 2372 } | |
| 2373 } | |
| 2374 | |
| 2375 @override | |
| 2376 Object visitConstructorDeclaration(ConstructorDeclaration node) { | |
| 2377 ExecutableElement outerExecutable = _enclosingExecutable; | |
| 2378 try { | |
| 2379 SimpleIdentifier constructorName = node.name; | |
| 2380 if (constructorName == null) { | |
| 2381 _enclosingExecutable = _enclosingClass.unnamedConstructor; | |
| 2382 if (_enclosingExecutable == null) { | |
| 2383 _mismatch('Could not find default constructor', node); | |
| 2384 } | |
| 2385 } else { | |
| 2386 _enclosingExecutable = | |
| 2387 _enclosingClass.getNamedConstructor(constructorName.name); | |
| 2388 if (_enclosingExecutable == null) { | |
| 2389 _mismatch( | |
| 2390 'Could not find constructor element with name "${constructorName.n
ame}', | |
| 2391 node); | |
| 2392 } | |
| 2393 constructorName.staticElement = _enclosingExecutable; | |
| 2394 } | |
| 2395 _expectedElements.remove(_enclosingExecutable); | |
| 2396 node.element = _enclosingExecutable as ConstructorElement; | |
| 2397 super.visitConstructorDeclaration(node); | |
| 2398 _resolveMetadata(node, node.metadata, _enclosingExecutable); | |
| 2399 return null; | |
| 2400 } finally { | |
| 2401 _enclosingExecutable = outerExecutable; | |
| 2402 } | |
| 2403 } | |
| 2404 | |
| 2405 @override | |
| 2406 Object visitDeclaredIdentifier(DeclaredIdentifier node) { | |
| 2407 SimpleIdentifier variableName = node.identifier; | |
| 2408 Element element = | |
| 2409 _findIdentifier(_enclosingExecutable.localVariables, variableName); | |
| 2410 super.visitDeclaredIdentifier(node); | |
| 2411 _resolveMetadata(node, node.metadata, element); | |
| 2412 return null; | |
| 2413 } | |
| 2414 | |
| 2415 @override | |
| 2416 Object visitDefaultFormalParameter(DefaultFormalParameter node) { | |
| 2417 SimpleIdentifier parameterName = node.parameter.identifier; | |
| 2418 ParameterElement element = _getElementForParameter(node, parameterName); | |
| 2419 Expression defaultValue = node.defaultValue; | |
| 2420 if (defaultValue != null) { | |
| 2421 ExecutableElement outerExecutable = _enclosingExecutable; | |
| 2422 try { | |
| 2423 _enclosingExecutable = element.initializer; | |
| 2424 defaultValue.accept(this); | |
| 2425 } finally { | |
| 2426 _enclosingExecutable = outerExecutable; | |
| 2427 } | |
| 2428 } | |
| 2429 ParameterElement outerParameter = _enclosingParameter; | |
| 2430 try { | |
| 2431 _enclosingParameter = element; | |
| 2432 super.visitDefaultFormalParameter(node); | |
| 2433 _resolveMetadata(node, node.metadata, element); | |
| 2434 return null; | |
| 2435 } finally { | |
| 2436 _enclosingParameter = outerParameter; | |
| 2437 } | |
| 2438 } | |
| 2439 | |
| 2440 @override | |
| 2441 Object visitEnumDeclaration(EnumDeclaration node) { | |
| 2442 ClassElement enclosingEnum = | |
| 2443 _findIdentifier(_enclosingUnit.enums, node.name); | |
| 2444 List<FieldElement> constants = enclosingEnum.fields; | |
| 2445 for (EnumConstantDeclaration constant in node.constants) { | |
| 2446 _findIdentifier(constants, constant.name); | |
| 2447 } | |
| 2448 super.visitEnumDeclaration(node); | |
| 2449 _resolveMetadata(node, node.metadata, enclosingEnum); | |
| 2450 return null; | |
| 2451 } | |
| 2452 | |
| 2453 @override | |
| 2454 Object visitExportDirective(ExportDirective node) { | |
| 2455 super.visitExportDirective(node); | |
| 2456 _resolveAnnotations( | |
| 2457 node, node.metadata, _enclosingUnit.getAnnotations(node.offset)); | |
| 2458 return null; | |
| 2459 } | |
| 2460 | |
| 2461 @override | |
| 2462 Object visitFieldDeclaration(FieldDeclaration node) { | |
| 2463 super.visitFieldDeclaration(node); | |
| 2464 _resolveMetadata(node, node.metadata, node.fields.variables[0].element); | |
| 2465 return null; | |
| 2466 } | |
| 2467 | |
| 2468 @override | |
| 2469 Object visitFieldFormalParameter(FieldFormalParameter node) { | |
| 2470 if (node.parent is! DefaultFormalParameter) { | |
| 2471 SimpleIdentifier parameterName = node.identifier; | |
| 2472 ParameterElement element = _getElementForParameter(node, parameterName); | |
| 2473 ParameterElement outerParameter = _enclosingParameter; | |
| 2474 try { | |
| 2475 _enclosingParameter = element; | |
| 2476 super.visitFieldFormalParameter(node); | |
| 2477 _resolveMetadata(node, node.metadata, element); | |
| 2478 return null; | |
| 2479 } finally { | |
| 2480 _enclosingParameter = outerParameter; | |
| 2481 } | |
| 2482 } else { | |
| 2483 return super.visitFieldFormalParameter(node); | |
| 2484 } | |
| 2485 } | |
| 2486 | |
| 2487 @override | |
| 2488 Object visitFunctionDeclaration(FunctionDeclaration node) { | |
| 2489 ExecutableElement outerExecutable = _enclosingExecutable; | |
| 2490 try { | |
| 2491 SimpleIdentifier functionName = node.name; | |
| 2492 Token property = node.propertyKeyword; | |
| 2493 if (property == null) { | |
| 2494 if (_enclosingExecutable != null) { | |
| 2495 _enclosingExecutable = | |
| 2496 _findIdentifier(_enclosingExecutable.functions, functionName); | |
| 2497 } else { | |
| 2498 _enclosingExecutable = | |
| 2499 _findIdentifier(_enclosingUnit.functions, functionName); | |
| 2500 } | |
| 2501 } else { | |
| 2502 if (_enclosingExecutable != null) { | |
| 2503 _enclosingExecutable = | |
| 2504 _findIdentifier(_enclosingExecutable.functions, functionName); | |
| 2505 } else { | |
| 2506 List<PropertyAccessorElement> accessors; | |
| 2507 if (_enclosingClass != null) { | |
| 2508 accessors = _enclosingClass.accessors; | |
| 2509 } else { | |
| 2510 accessors = _enclosingUnit.accessors; | |
| 2511 } | |
| 2512 PropertyAccessorElement accessor; | |
| 2513 if (property.keyword == Keyword.GET) { | |
| 2514 accessor = _findIdentifier(accessors, functionName); | |
| 2515 } else if (property.keyword == Keyword.SET) { | |
| 2516 accessor = _findWithNameAndOffset(accessors, functionName, | |
| 2517 functionName.name + '=', functionName.offset); | |
| 2518 _expectedElements.remove(accessor); | |
| 2519 functionName.staticElement = accessor; | |
| 2520 } | |
| 2521 _enclosingExecutable = accessor; | |
| 2522 } | |
| 2523 } | |
| 2524 node.functionExpression.element = _enclosingExecutable; | |
| 2525 super.visitFunctionDeclaration(node); | |
| 2526 _resolveMetadata(node, node.metadata, _enclosingExecutable); | |
| 2527 return null; | |
| 2528 } finally { | |
| 2529 _enclosingExecutable = outerExecutable; | |
| 2530 } | |
| 2531 } | |
| 2532 | |
| 2533 @override | |
| 2534 Object visitFunctionExpression(FunctionExpression node) { | |
| 2535 if (node.parent is! FunctionDeclaration) { | |
| 2536 FunctionElement element = _findAtOffset( | |
| 2537 _enclosingExecutable.functions, node, node.beginToken.offset); | |
| 2538 _expectedElements.remove(element); | |
| 2539 node.element = element; | |
| 2540 } | |
| 2541 ExecutableElement outerExecutable = _enclosingExecutable; | |
| 2542 try { | |
| 2543 _enclosingExecutable = node.element; | |
| 2544 return super.visitFunctionExpression(node); | |
| 2545 } finally { | |
| 2546 _enclosingExecutable = outerExecutable; | |
| 2547 } | |
| 2548 } | |
| 2549 | |
| 2550 @override | |
| 2551 Object visitFunctionTypeAlias(FunctionTypeAlias node) { | |
| 2552 FunctionTypeAliasElement outerAlias = _enclosingAlias; | |
| 2553 try { | |
| 2554 SimpleIdentifier aliasName = node.name; | |
| 2555 _enclosingAlias = | |
| 2556 _findIdentifier(_enclosingUnit.functionTypeAliases, aliasName); | |
| 2557 super.visitFunctionTypeAlias(node); | |
| 2558 _resolveMetadata(node, node.metadata, _enclosingAlias); | |
| 2559 return null; | |
| 2560 } finally { | |
| 2561 _enclosingAlias = outerAlias; | |
| 2562 } | |
| 2563 } | |
| 2564 | |
| 2565 @override | |
| 2566 Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { | |
| 2567 if (node.parent is! DefaultFormalParameter) { | |
| 2568 SimpleIdentifier parameterName = node.identifier; | |
| 2569 ParameterElement element = _getElementForParameter(node, parameterName); | |
| 2570 ParameterElement outerParameter = _enclosingParameter; | |
| 2571 try { | |
| 2572 _enclosingParameter = element; | |
| 2573 super.visitFunctionTypedFormalParameter(node); | |
| 2574 _resolveMetadata(node, node.metadata, _enclosingParameter); | |
| 2575 return null; | |
| 2576 } finally { | |
| 2577 _enclosingParameter = outerParameter; | |
| 2578 } | |
| 2579 } else { | |
| 2580 return super.visitFunctionTypedFormalParameter(node); | |
| 2581 } | |
| 2582 } | |
| 2583 | |
| 2584 @override | |
| 2585 Object visitImportDirective(ImportDirective node) { | |
| 2586 super.visitImportDirective(node); | |
| 2587 _resolveAnnotations( | |
| 2588 node, node.metadata, _enclosingUnit.getAnnotations(node.offset)); | |
| 2589 return null; | |
| 2590 } | |
| 2591 | |
| 2592 @override | |
| 2593 Object visitLabeledStatement(LabeledStatement node) { | |
| 2594 for (Label label in node.labels) { | |
| 2595 SimpleIdentifier labelName = label.label; | |
| 2596 _findIdentifier(_enclosingExecutable.labels, labelName); | |
| 2597 } | |
| 2598 return super.visitLabeledStatement(node); | |
| 2599 } | |
| 2600 | |
| 2601 @override | |
| 2602 Object visitLibraryDirective(LibraryDirective node) { | |
| 2603 super.visitLibraryDirective(node); | |
| 2604 _resolveAnnotations( | |
| 2605 node, node.metadata, _enclosingUnit.getAnnotations(node.offset)); | |
| 2606 return null; | |
| 2607 } | |
| 2608 | |
| 2609 @override | |
| 2610 Object visitMethodDeclaration(MethodDeclaration node) { | |
| 2611 ExecutableElement outerExecutable = _enclosingExecutable; | |
| 2612 try { | |
| 2613 Token property = node.propertyKeyword; | |
| 2614 SimpleIdentifier methodName = node.name; | |
| 2615 String nameOfMethod = methodName.name; | |
| 2616 if (property == null) { | |
| 2617 String elementName = nameOfMethod == '-' && | |
| 2618 node.parameters != null && | |
| 2619 node.parameters.parameters.isEmpty | |
| 2620 ? 'unary-' | |
| 2621 : nameOfMethod; | |
| 2622 _enclosingExecutable = _findWithNameAndOffset(_enclosingClass.methods, | |
| 2623 methodName, elementName, methodName.offset); | |
| 2624 _expectedElements.remove(_enclosingExecutable); | |
| 2625 methodName.staticElement = _enclosingExecutable; | |
| 2626 } else { | |
| 2627 PropertyAccessorElement accessor; | |
| 2628 if (property.keyword == Keyword.GET) { | |
| 2629 accessor = _findIdentifier(_enclosingClass.accessors, methodName); | |
| 2630 } else if (property.keyword == Keyword.SET) { | |
| 2631 accessor = _findWithNameAndOffset(_enclosingClass.accessors, | |
| 2632 methodName, nameOfMethod + '=', methodName.offset); | |
| 2633 _expectedElements.remove(accessor); | |
| 2634 methodName.staticElement = accessor; | |
| 2635 } | |
| 2636 _enclosingExecutable = accessor; | |
| 2637 } | |
| 2638 super.visitMethodDeclaration(node); | |
| 2639 _resolveMetadata(node, node.metadata, _enclosingExecutable); | |
| 2640 return null; | |
| 2641 } finally { | |
| 2642 _enclosingExecutable = outerExecutable; | |
| 2643 } | |
| 2644 } | |
| 2645 | |
| 2646 @override | |
| 2647 Object visitPartDirective(PartDirective node) { | |
| 2648 super.visitPartDirective(node); | |
| 2649 _resolveAnnotations( | |
| 2650 node, node.metadata, _enclosingUnit.getAnnotations(node.offset)); | |
| 2651 return null; | |
| 2652 } | |
| 2653 | |
| 2654 @override | |
| 2655 Object visitPartOfDirective(PartOfDirective node) { | |
| 2656 node.element = _enclosingUnit.library; | |
| 2657 return super.visitPartOfDirective(node); | |
| 2658 } | |
| 2659 | |
| 2660 @override | |
| 2661 Object visitSimpleFormalParameter(SimpleFormalParameter node) { | |
| 2662 if (node.parent is! DefaultFormalParameter) { | |
| 2663 SimpleIdentifier parameterName = node.identifier; | |
| 2664 ParameterElement element = _getElementForParameter(node, parameterName); | |
| 2665 ParameterElement outerParameter = _enclosingParameter; | |
| 2666 try { | |
| 2667 _enclosingParameter = element; | |
| 2668 super.visitSimpleFormalParameter(node); | |
| 2669 _resolveMetadata(node, node.metadata, element); | |
| 2670 return null; | |
| 2671 } finally { | |
| 2672 _enclosingParameter = outerParameter; | |
| 2673 } | |
| 2674 } else {} | |
| 2675 return super.visitSimpleFormalParameter(node); | |
| 2676 } | |
| 2677 | |
| 2678 @override | |
| 2679 Object visitSwitchCase(SwitchCase node) { | |
| 2680 for (Label label in node.labels) { | |
| 2681 SimpleIdentifier labelName = label.label; | |
| 2682 _findIdentifier(_enclosingExecutable.labels, labelName); | |
| 2683 } | |
| 2684 return super.visitSwitchCase(node); | |
| 2685 } | |
| 2686 | |
| 2687 @override | |
| 2688 Object visitSwitchDefault(SwitchDefault node) { | |
| 2689 for (Label label in node.labels) { | |
| 2690 SimpleIdentifier labelName = label.label; | |
| 2691 _findIdentifier(_enclosingExecutable.labels, labelName); | |
| 2692 } | |
| 2693 return super.visitSwitchDefault(node); | |
| 2694 } | |
| 2695 | |
| 2696 @override | |
| 2697 Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { | |
| 2698 super.visitTopLevelVariableDeclaration(node); | |
| 2699 _resolveMetadata(node, node.metadata, node.variables.variables[0].element); | |
| 2700 return null; | |
| 2701 } | |
| 2702 | |
| 2703 @override | |
| 2704 Object visitTypeParameter(TypeParameter node) { | |
| 2705 SimpleIdentifier parameterName = node.name; | |
| 2706 Element element = null; | |
| 2707 if (_enclosingExecutable != null) { | |
| 2708 element = _findIdentifier( | |
| 2709 _enclosingExecutable.typeParameters, parameterName, | |
| 2710 required: false); | |
| 2711 } | |
| 2712 if (element == null) { | |
| 2713 if (_enclosingClass != null) { | |
| 2714 element = | |
| 2715 _findIdentifier(_enclosingClass.typeParameters, parameterName); | |
| 2716 } else if (_enclosingAlias != null) { | |
| 2717 element = | |
| 2718 _findIdentifier(_enclosingAlias.typeParameters, parameterName); | |
| 2719 } | |
| 2720 } | |
| 2721 if (element == null) { | |
| 2722 String name = parameterName.name; | |
| 2723 int offset = parameterName.offset; | |
| 2724 _mismatch( | |
| 2725 'Could not find type parameter with name "$name" at $offset', node); | |
| 2726 } | |
| 2727 super.visitTypeParameter(node); | |
| 2728 _resolveMetadata(node, node.metadata, element); | |
| 2729 return null; | |
| 2730 } | |
| 2731 | |
| 2732 @override | |
| 2733 Object visitVariableDeclaration(VariableDeclaration node) { | |
| 2734 VariableElement element = null; | |
| 2735 SimpleIdentifier variableName = node.name; | |
| 2736 if (_enclosingExecutable != null) { | |
| 2737 element = _findIdentifier( | |
| 2738 _enclosingExecutable.localVariables, variableName, | |
| 2739 required: false); | |
| 2740 } | |
| 2741 if (element == null && _enclosingClass != null) { | |
| 2742 element = _findIdentifier(_enclosingClass.fields, variableName, | |
| 2743 required: false); | |
| 2744 } | |
| 2745 if (element == null && _enclosingUnit != null) { | |
| 2746 element = _findIdentifier(_enclosingUnit.topLevelVariables, variableName); | |
| 2747 } | |
| 2748 Expression initializer = node.initializer; | |
| 2749 if (initializer != null) { | |
| 2750 ExecutableElement outerExecutable = _enclosingExecutable; | |
| 2751 try { | |
| 2752 _enclosingExecutable = element.initializer; | |
| 2753 return super.visitVariableDeclaration(node); | |
| 2754 } finally { | |
| 2755 _enclosingExecutable = outerExecutable; | |
| 2756 } | |
| 2757 } | |
| 2758 return super.visitVariableDeclaration(node); | |
| 2759 } | |
| 2760 | |
| 2761 @override | |
| 2762 Object visitVariableDeclarationList(VariableDeclarationList node) { | |
| 2763 super.visitVariableDeclarationList(node); | |
| 2764 if (node.parent is! FieldDeclaration && | |
| 2765 node.parent is! TopLevelVariableDeclaration) { | |
| 2766 _resolveMetadata(node, node.metadata, node.variables[0].element); | |
| 2767 } | |
| 2768 return null; | |
| 2769 } | |
| 2770 | |
| 2771 /** | |
| 2772 * Return the element in the given list of [elements] that was created for the | |
| 2773 * declaration at the given [offset]. Throw an [ElementMismatchException] if | |
| 2774 * an element at that offset cannot be found. | |
| 2775 * | |
| 2776 * This method should only be used when there is no name associated with the | |
| 2777 * node. | |
| 2778 */ | |
| 2779 Element _findAtOffset(List<Element> elements, AstNode node, int offset) => | |
| 2780 _findWithNameAndOffset(elements, node, '', offset); | |
| 2781 | |
| 2782 /** | |
| 2783 * Return the element in the given list of [elements] that was created for the | |
| 2784 * declaration with the given [identifier]. As a side-effect, associate the | |
| 2785 * returned element with the identifier. Throw an [ElementMismatchException] | |
| 2786 * if an element corresponding to the identifier cannot be found unless | |
| 2787 * [required] is `false`, in which case return `null`. | |
| 2788 */ | |
| 2789 Element _findIdentifier(List<Element> elements, SimpleIdentifier identifier, | |
| 2790 {bool required: true}) { | |
| 2791 Element element = _findWithNameAndOffset( | |
| 2792 elements, identifier, identifier.name, identifier.offset, | |
| 2793 required: required); | |
| 2794 _expectedElements.remove(element); | |
| 2795 identifier.staticElement = element; | |
| 2796 return element; | |
| 2797 } | |
| 2798 | |
| 2799 /** | |
| 2800 * Return the element in the given list of [elements] that was created for the | |
| 2801 * declaration with the given [name] at the given [offset]. Throw an | |
| 2802 * [ElementMismatchException] if an element corresponding to the identifier | |
| 2803 * cannot be found unless [required] is `false`, in which case return `null`. | |
| 2804 */ | |
| 2805 Element _findWithNameAndOffset( | |
| 2806 List<Element> elements, AstNode node, String name, int offset, | |
| 2807 {bool required: true}) { | |
| 2808 int length = elements.length; | |
| 2809 for (int i = 0; i < length; i++) { | |
| 2810 Element element = elements[i]; | |
| 2811 if (element.nameOffset == offset && element.name == name) { | |
| 2812 return element; | |
| 2813 } | |
| 2814 } | |
| 2815 if (!required) { | |
| 2816 return null; | |
| 2817 } | |
| 2818 for (int i = 0; i < length; i++) { | |
| 2819 Element element = elements[i]; | |
| 2820 if (element.name == name) { | |
| 2821 _mismatch( | |
| 2822 'Found element with name "$name" at ${element.nameOffset}, ' | |
| 2823 'but expected offset of $offset', | |
| 2824 node); | |
| 2825 } | |
| 2826 if (element.nameOffset == offset) { | |
| 2827 _mismatch( | |
| 2828 'Found element with name "${element.name}" at $offset, ' | |
| 2829 'but expected element with name "$name"', | |
| 2830 node); | |
| 2831 } | |
| 2832 } | |
| 2833 _mismatch('Could not find element with name "$name" at $offset', node); | |
| 2834 return null; // Never reached | |
| 2835 } | |
| 2836 | |
| 2837 /** | |
| 2838 * Search the most closely enclosing list of parameter elements for a | |
| 2839 * parameter, defined by the given [node], with the given [parameterName]. | |
| 2840 * Return the element that was found, or throw an [ElementMismatchException] | |
| 2841 * if an element corresponding to the identifier cannot be found. | |
| 2842 */ | |
| 2843 ParameterElement _getElementForParameter( | |
| 2844 FormalParameter node, SimpleIdentifier parameterName) { | |
| 2845 List<ParameterElement> parameters = null; | |
| 2846 if (_enclosingParameter != null) { | |
| 2847 parameters = _enclosingParameter.parameters; | |
| 2848 } | |
| 2849 if (parameters == null && _enclosingExecutable != null) { | |
| 2850 parameters = _enclosingExecutable.parameters; | |
| 2851 } | |
| 2852 if (parameters == null && _enclosingAlias != null) { | |
| 2853 parameters = _enclosingAlias.parameters; | |
| 2854 } | |
| 2855 if (parameters == null) { | |
| 2856 StringBuffer buffer = new StringBuffer(); | |
| 2857 buffer.writeln('Could not find parameter in enclosing scope'); | |
| 2858 buffer.writeln( | |
| 2859 '(_enclosingParameter == null) == ${_enclosingParameter == null}'); | |
| 2860 buffer.writeln( | |
| 2861 '(_enclosingExecutable == null) == ${_enclosingExecutable == null}'); | |
| 2862 buffer.writeln('(_enclosingAlias == null) == ${_enclosingAlias == null}'); | |
| 2863 _mismatch(buffer.toString(), parameterName); | |
| 2864 } | |
| 2865 return _findIdentifier(parameters, parameterName); | |
| 2866 } | |
| 2867 | |
| 2868 /** | |
| 2869 * Associate each of the annotation [nodes] with the corresponding | |
| 2870 * [ElementAnnotation] in [annotations]. If there is a problem, report it | |
| 2871 * against the given [parent] node. | |
| 2872 */ | |
| 2873 void _resolveAnnotations(AstNode parent, NodeList<Annotation> nodes, | |
| 2874 List<ElementAnnotation> annotations) { | |
| 2875 int nodeCount = nodes.length; | |
| 2876 if (nodeCount != annotations.length) { | |
| 2877 _mismatch( | |
| 2878 'Found $nodeCount annotation nodes and ' | |
| 2879 '${annotations.length} element annotations', | |
| 2880 parent); | |
| 2881 } | |
| 2882 for (int i = 0; i < nodeCount; i++) { | |
| 2883 nodes[i].elementAnnotation = annotations[i]; | |
| 2884 } | |
| 2885 } | |
| 2886 | |
| 2887 /** | |
| 2888 * If [element] is not `null`, associate each of the annotation [nodes] with | |
| 2889 * the corresponding [ElementAnnotation] in [element.metadata]. If there is a | |
| 2890 * problem, report it against the given [parent] node. | |
| 2891 * | |
| 2892 * If [element] is `null`, do nothing--this allows us to be robust in the | |
| 2893 * case where we are operating on an element model that hasn't been fully | |
| 2894 * built. | |
| 2895 */ | |
| 2896 void _resolveMetadata( | |
| 2897 AstNode parent, NodeList<Annotation> nodes, Element element) { | |
| 2898 if (element != null) { | |
| 2899 _resolveAnnotations(parent, nodes, element.metadata); | |
| 2900 } | |
| 2901 } | |
| 2902 | |
| 2903 /** | |
| 2904 * Throw an exception if there are non-synthetic elements in the element model | |
| 2905 * that were not associated with an AST node. | |
| 2906 */ | |
| 2907 void _validateResolution() { | |
| 2908 if (_expectedElements.isNotEmpty) { | |
| 2909 StringBuffer buffer = new StringBuffer(); | |
| 2910 buffer.write(_expectedElements.length); | |
| 2911 buffer.writeln(' unmatched elements found:'); | |
| 2912 for (Element element in _expectedElements) { | |
| 2913 buffer.write(' '); | |
| 2914 buffer.writeln(element); | |
| 2915 } | |
| 2916 throw new ElementMismatchException(buffer.toString()); | |
| 2917 } | |
| 2918 } | |
| 2919 } | |
| 2920 | |
| 2921 /** | |
| 2922 * A visitor that resolves directives in an AST structure to already built | 2269 * A visitor that resolves directives in an AST structure to already built |
| 2923 * elements. | 2270 * elements. |
| 2924 * | 2271 * |
| 2925 * The resulting AST must have everything resolved that would have been resolved | 2272 * The resulting AST must have everything resolved that would have been resolved |
| 2926 * by a [DirectiveElementBuilder]. | 2273 * by a [DirectiveElementBuilder]. |
| 2927 */ | 2274 */ |
| 2928 class DirectiveResolver extends SimpleAstVisitor { | 2275 class DirectiveResolver extends SimpleAstVisitor { |
| 2929 LibraryElement _enclosingLibrary; | 2276 LibraryElement _enclosingLibrary; |
| 2930 | 2277 |
| 2931 @override | 2278 @override |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3324 buffer.write(_typeParameters.length); | 2671 buffer.write(_typeParameters.length); |
| 3325 buffer.write(" type parameters"); | 2672 buffer.write(" type parameters"); |
| 3326 } | 2673 } |
| 3327 if (buffer.length > 0) { | 2674 if (buffer.length > 0) { |
| 3328 AnalysisEngine.instance.logger | 2675 AnalysisEngine.instance.logger |
| 3329 .logError("Failed to capture elements: $buffer"); | 2676 .logError("Failed to capture elements: $buffer"); |
| 3330 } | 2677 } |
| 3331 } | 2678 } |
| 3332 } | 2679 } |
| 3333 | 2680 |
| 3334 class ElementMismatchException extends AnalysisException { | |
| 3335 /** | |
| 3336 * Initialize a newly created exception to have the given [message] and | |
| 3337 * [cause]. | |
| 3338 */ | |
| 3339 ElementMismatchException(String message, [CaughtException cause = null]) | |
| 3340 : super(message, cause); | |
| 3341 } | |
| 3342 | |
| 3343 /** | 2681 /** |
| 3344 * Instances of the class `EnumMemberBuilder` build the members in enum declarat
ions. | 2682 * Instances of the class `EnumMemberBuilder` build the members in enum declarat
ions. |
| 3345 */ | 2683 */ |
| 3346 class EnumMemberBuilder extends RecursiveAstVisitor<Object> { | 2684 class EnumMemberBuilder extends RecursiveAstVisitor<Object> { |
| 3347 /** | 2685 /** |
| 3348 * The type provider used to access the types needed to build an element model
for enum | 2686 * The type provider used to access the types needed to build an element model
for enum |
| 3349 * declarations. | 2687 * declarations. |
| 3350 */ | 2688 */ |
| 3351 final TypeProvider _typeProvider; | 2689 final TypeProvider _typeProvider; |
| 3352 | 2690 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3424 | 2762 |
| 3425 /** | 2763 /** |
| 3426 * Create a getter that corresponds to the given [field]. | 2764 * Create a getter that corresponds to the given [field]. |
| 3427 */ | 2765 */ |
| 3428 PropertyAccessorElement _createGetter(FieldElementImpl field) { | 2766 PropertyAccessorElement _createGetter(FieldElementImpl field) { |
| 3429 return new PropertyAccessorElementImpl_ImplicitGetter(field); | 2767 return new PropertyAccessorElementImpl_ImplicitGetter(field); |
| 3430 } | 2768 } |
| 3431 } | 2769 } |
| 3432 | 2770 |
| 3433 /** | 2771 /** |
| 3434 * A mixin for classes that use an existing element model to resolve a portion | |
| 3435 * of an AST structure. | |
| 3436 */ | |
| 3437 class ExistingElementResolver { | |
| 3438 /** | |
| 3439 * The compilation unit containing the AST nodes being visited. | |
| 3440 */ | |
| 3441 CompilationUnitElementImpl _enclosingUnit; | |
| 3442 | |
| 3443 /** | |
| 3444 * Throw an [ElementMismatchException] to report that the element model and th
e | |
| 3445 * AST do not match. The [message] will have the path to the given [node] | |
| 3446 * appended to it. | |
| 3447 */ | |
| 3448 void _mismatch(String message, AstNode node) { | |
| 3449 StringBuffer buffer = new StringBuffer(); | |
| 3450 buffer.write('Mismatch in '); | |
| 3451 buffer.write(runtimeType); | |
| 3452 buffer.write(' while resolving '); | |
| 3453 buffer.writeln(_enclosingUnit?.source?.fullName); | |
| 3454 buffer.writeln(message); | |
| 3455 buffer.write('Path to root:'); | |
| 3456 String separator = ' '; | |
| 3457 AstNode parent = node; | |
| 3458 while (parent != null) { | |
| 3459 buffer.write(separator); | |
| 3460 buffer.write(parent.runtimeType.toString()); | |
| 3461 separator = ', '; | |
| 3462 parent = parent.parent; | |
| 3463 } | |
| 3464 throw new ElementMismatchException(buffer.toString()); | |
| 3465 } | |
| 3466 } | |
| 3467 | |
| 3468 /** | |
| 3469 * Instances of the class `ExitDetector` determine whether the visited AST node
is guaranteed | 2772 * Instances of the class `ExitDetector` determine whether the visited AST node
is guaranteed |
| 3470 * to terminate by executing a `return` statement, `throw` expression, `rethrow` | 2773 * to terminate by executing a `return` statement, `throw` expression, `rethrow` |
| 3471 * expression, or simple infinite loop such as `while(true)`. | 2774 * expression, or simple infinite loop such as `while(true)`. |
| 3472 */ | 2775 */ |
| 3473 class ExitDetector extends GeneralizingAstVisitor<bool> { | 2776 class ExitDetector extends GeneralizingAstVisitor<bool> { |
| 3474 /** | 2777 /** |
| 3475 * Set to `true` when a `break` is encountered, and reset to `false` when a | 2778 * Set to `true` when a `break` is encountered, and reset to `false` when a |
| 3476 * `do`, `while`, `for` or `switch` block is entered. | 2779 * `do`, `while`, `for` or `switch` block is entered. |
| 3477 */ | 2780 */ |
| 3478 bool _enclosingBlockContainsBreak = false; | 2781 bool _enclosingBlockContainsBreak = false; |
| (...skipping 7794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11273 return null; | 10576 return null; |
| 11274 } | 10577 } |
| 11275 if (identical(node.staticElement, variable)) { | 10578 if (identical(node.staticElement, variable)) { |
| 11276 if (node.inSetterContext()) { | 10579 if (node.inSetterContext()) { |
| 11277 result = true; | 10580 result = true; |
| 11278 } | 10581 } |
| 11279 } | 10582 } |
| 11280 return null; | 10583 return null; |
| 11281 } | 10584 } |
| 11282 } | 10585 } |
| OLD | NEW |