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

Side by Side Diff: pkg/analyzer/lib/src/task/dart.dart

Issue 1323653002: Task to infer static variables (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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.task.dart; 5 library analyzer.src.task.dart;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'package:analyzer/src/context/cache.dart'; 9 import 'package:analyzer/src/context/cache.dart';
10 import 'package:analyzer/src/generated/ast.dart'; 10 import 'package:analyzer/src/generated/ast.dart';
11 import 'package:analyzer/src/generated/constant.dart'; 11 import 'package:analyzer/src/generated/constant.dart';
12 import 'package:analyzer/src/generated/element.dart'; 12 import 'package:analyzer/src/generated/element.dart';
13 import 'package:analyzer/src/generated/engine.dart' 13 import 'package:analyzer/src/generated/engine.dart'
14 hide AnalysisCache, AnalysisTask; 14 hide AnalysisCache, AnalysisTask;
15 import 'package:analyzer/src/generated/error.dart'; 15 import 'package:analyzer/src/generated/error.dart';
16 import 'package:analyzer/src/generated/error_verifier.dart'; 16 import 'package:analyzer/src/generated/error_verifier.dart';
17 import 'package:analyzer/src/generated/incremental_resolver.dart';
17 import 'package:analyzer/src/generated/java_engine.dart'; 18 import 'package:analyzer/src/generated/java_engine.dart';
18 import 'package:analyzer/src/generated/parser.dart'; 19 import 'package:analyzer/src/generated/parser.dart';
19 import 'package:analyzer/src/generated/resolver.dart'; 20 import 'package:analyzer/src/generated/resolver.dart';
20 import 'package:analyzer/src/generated/scanner.dart'; 21 import 'package:analyzer/src/generated/scanner.dart';
21 import 'package:analyzer/src/generated/sdk.dart'; 22 import 'package:analyzer/src/generated/sdk.dart';
22 import 'package:analyzer/src/generated/source.dart'; 23 import 'package:analyzer/src/generated/source.dart';
23 import 'package:analyzer/src/task/driver.dart'; 24 import 'package:analyzer/src/task/driver.dart';
24 import 'package:analyzer/src/task/general.dart'; 25 import 'package:analyzer/src/task/general.dart';
25 import 'package:analyzer/src/task/html.dart'; 26 import 'package:analyzer/src/task/html.dart';
26 import 'package:analyzer/src/task/inputs.dart'; 27 import 'package:analyzer/src/task/inputs.dart';
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 * static members inside classes. 179 * static members inside classes.
179 * 180 *
180 * The result is only available for [LibrarySpecificUnit]s, and only when strong 181 * The result is only available for [LibrarySpecificUnit]s, and only when strong
181 * mode is enabled. 182 * mode is enabled.
182 */ 183 */
183 final ListResultDescriptor<VariableElement> INFERABLE_STATIC_VARIABLES_IN_UNIT = 184 final ListResultDescriptor<VariableElement> INFERABLE_STATIC_VARIABLES_IN_UNIT =
184 new ListResultDescriptor<VariableElement>( 185 new ListResultDescriptor<VariableElement>(
185 'INFERABLE_STATIC_VARIABLES_IN_UNIT', null); 186 'INFERABLE_STATIC_VARIABLES_IN_UNIT', null);
186 187
187 /** 188 /**
189 * An inferrable static variable ([VariableElement]) whose type has been
190 * inferred.
191 */
192 final ResultDescriptor<VariableElement> INFERRED_STATIC_VARIABLE =
193 new ResultDescriptor<VariableElement>('INFERRED_STATIC_VARIABLE', null,
194 cachingPolicy: ELEMENT_CACHING_POLICY);
195
196 /**
188 * The partial [LibraryElement] associated with a library. 197 * The partial [LibraryElement] associated with a library.
189 * 198 *
190 * The [LibraryElement] and its [CompilationUnitElement]s are attached to each 199 * The [LibraryElement] and its [CompilationUnitElement]s are attached to each
191 * other. Directives 'library', 'part' and 'part of' are resolved. 200 * other. Directives 'library', 'part' and 'part of' are resolved.
192 * 201 *
193 * The result is only available for [Source]s representing a library. 202 * The result is only available for [Source]s representing a library.
194 */ 203 */
195 final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT1 = 204 final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT1 =
196 new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT1', null, 205 new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT1', null,
197 cachingPolicy: ELEMENT_CACHING_POLICY); 206 cachingPolicy: ELEMENT_CACHING_POLICY);
(...skipping 1468 matching lines...) Expand 10 before | Expand all | Expand 10 after
1666 node.getAncestor((AstNode ancestor) => ancestor is VariableDeclaration); 1675 node.getAncestor((AstNode ancestor) => ancestor is VariableDeclaration);
1667 if (declaration == null || declaration.name != node) { 1676 if (declaration == null || declaration.name != node) {
1668 throw new AnalysisException( 1677 throw new AnalysisException(
1669 "NodeLocator failed to find a variable's declaration"); 1678 "NodeLocator failed to find a variable's declaration");
1670 } 1679 }
1671 VariableGatherer gatherer = new VariableGatherer(_isInferableStatic); 1680 VariableGatherer gatherer = new VariableGatherer(_isInferableStatic);
1672 declaration.initializer.accept(gatherer); 1681 declaration.initializer.accept(gatherer);
1673 // 1682 //
1674 // Record outputs. 1683 // Record outputs.
1675 // 1684 //
1676 outputs[INFERABLE_STATIC_VARIABLE_DEPENDENCIES] = gatherer.results; 1685 outputs[INFERABLE_STATIC_VARIABLE_DEPENDENCIES] = gatherer.results.toList();
1677 } 1686 }
1678 1687
1679 /** 1688 /**
1680 * Return `true` if the given [variable] is a static variable whose type 1689 * Return `true` if the given [variable] is a static variable whose type
1681 * should be inferred. 1690 * should be inferred.
1682 */ 1691 */
1683 bool _isInferableStatic(VariableElement variable) => variable.isStatic && 1692 bool _isInferableStatic(VariableElement variable) => variable.isStatic &&
1684 variable.hasImplicitType && 1693 variable.hasImplicitType &&
1685 variable.initializer != null; 1694 variable.initializer != null;
1686 1695
(...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after
2394 * Create a [GenerateHintsTask] based on the given [target] in 2403 * Create a [GenerateHintsTask] based on the given [target] in
2395 * the given [context]. 2404 * the given [context].
2396 */ 2405 */
2397 static GenerateHintsTask createTask( 2406 static GenerateHintsTask createTask(
2398 AnalysisContext context, AnalysisTarget target) { 2407 AnalysisContext context, AnalysisTarget target) {
2399 return new GenerateHintsTask(context, target); 2408 return new GenerateHintsTask(context, target);
2400 } 2409 }
2401 } 2410 }
2402 2411
2403 /** 2412 /**
2413 * An abstract class that defines utility methods that are useful for tasks
2414 * operating on static variables.
2415 */
2416 abstract class InferStaticVariableTask extends ConstantEvaluationAnalysisTask {
2417 InferStaticVariableTask(
2418 InternalAnalysisContext context, VariableElement variable)
2419 : super(context, variable);
2420
2421 /**
2422 * Return the declaration of the target within the given compilation [unit].
2423 * Throw an exception if the declaration cannot be found.
2424 */
2425 VariableDeclaration getDeclaration(CompilationUnit unit) {
2426 VariableElement variable = target;
2427 NodeLocator locator = new NodeLocator(variable.nameOffset);
2428 AstNode node = locator.searchWithin(unit);
2429 VariableDeclaration declaration =
2430 node.getAncestor((AstNode ancestor) => ancestor is VariableDeclaration);
2431 if (declaration == null || declaration.name != node) {
2432 throw new AnalysisException(
2433 "Failed to find the declaration of the variable ${variable.displayName } in ${variable.source}");
2434 }
2435 return declaration;
2436 }
2437 }
2438
2439 /**
2440 * A task that ensures that all of the inferrable static variables in a
2441 * compilation unit have had their type inferred.
2442 */
2443 class InferStaticVariableTypesInUnitTask extends SourceBasedAnalysisTask {
Paul Berry 2015/08/29 01:14:55 Since this task has dependencies which are other s
Brian Wilkerson 2015/08/31 15:08:52 Sorry, I should have included this in a comment, b
Paul Berry 2015/08/31 15:50:59 Acknowledged.
2444 /**
2445 * The name of the input whose value is the [RESOLVED_UNIT5] for the
2446 * compilation unit.
2447 */
2448 static const String UNIT_INPUT = 'UNIT_INPUT';
2449
2450 /**
2451 * The name of the input whose value is a list of the inferrable static
2452 * variables whose types have been computed.
2453 */
2454 static const String INFERRED_VARIABLES_INPUT = 'INFERRED_VARIABLES_INPUT';
2455
2456 /**
2457 * The task descriptor describing this kind of task.
2458 */
2459 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
2460 'InferStaticVariableTypesInUnitTask',
2461 createTask,
2462 buildInputs,
2463 <ResultDescriptor>[RESOLVED_UNIT6]);
2464
2465 /**
2466 * Initialize a newly created task to build a library element for the given
2467 * [unit] in the given [context].
2468 */
2469 InferStaticVariableTypesInUnitTask(
2470 InternalAnalysisContext context, LibrarySpecificUnit unit)
2471 : super(context, unit);
2472
2473 @override
2474 TaskDescriptor get descriptor => DESCRIPTOR;
2475
2476 @override
2477 void internalPerform() {
2478 //
2479 // Prepare inputs.
2480 //
2481 CompilationUnit unit = getRequiredInput(UNIT_INPUT);
2482 //
2483 // Record outputs. There is no additional work to be done at this time
2484 // because the work has implicitly been done by virtue of the task model
2485 // preparing all of the inputs.
2486 //
2487 outputs[RESOLVED_UNIT6] = unit;
2488 }
2489
2490 /**
2491 * Return a map from the names of the inputs of this kind of task to the task
2492 * input descriptors describing those inputs for a task with the given
2493 * [libSource].
2494 */
2495 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
2496 LibrarySpecificUnit unit = target;
2497 return <String, TaskInput>{
2498 INFERRED_VARIABLES_INPUT: INFERABLE_STATIC_VARIABLES_IN_UNIT
2499 .of(unit)
2500 .toListOf(INFERRED_STATIC_VARIABLE),
2501 UNIT_INPUT: RESOLVED_UNIT5.of(unit)
2502 };
2503 }
2504
2505 /**
2506 * Create a [InferStaticVariableTypesInUnitTask] based on the given [target] i n the
2507 * given [context].
2508 */
2509 static InferStaticVariableTypesInUnitTask createTask(
2510 AnalysisContext context, AnalysisTarget target) {
2511 return new InferStaticVariableTypesInUnitTask(context, target);
2512 }
2513 }
2514
2515 /**
2516 * A task that computes the type of an inferrable static variable and
2517 * stores it in the element model.
2518 */
2519 class InferStaticVariableTypeTask extends InferStaticVariableTask {
2520 /**
2521 * The name of the input which ensures that dependent values have their type
2522 * inferred before the target.
2523 */
2524 static const String DEPENDENCIES_INPUT = 'DEPENDENCIES_INPUT';
2525
2526 /**
2527 * The name of the [TYPE_PROVIDER] input.
2528 */
2529 static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
2530
2531 /**
2532 * The name of the [RESOLVED_UNIT5] input.
2533 */
2534 static const String UNIT_INPUT = 'UNIT_INPUT';
2535
2536 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
2537 'InferStaticVariableTypeTask',
2538 createTask,
2539 buildInputs,
2540 <ResultDescriptor>[INFERRED_STATIC_VARIABLE]);
2541
2542 InferStaticVariableTypeTask(
2543 InternalAnalysisContext context, VariableElement variable)
2544 : super(context, variable);
2545
2546 @override
2547 TaskDescriptor get descriptor => DESCRIPTOR;
2548
2549 @override
2550 bool get handlesDependencyCycles => true;
2551
2552 @override
2553 void internalPerform() {
2554 //
2555 // Prepare inputs.
2556 //
2557 // Note: DEPENDENCIES_INPUT is not needed. It is merely a bookkeeping
2558 // dependency to ensure that the variables that this variable references
2559 // have types inferred before inferring the type of this variable.
2560 //
2561 VariableElementImpl variable = target;
2562 CompilationUnit unit = getRequiredInput(UNIT_INPUT);
2563 TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
2564 //
2565 // Re-resolve the variable's initializer so that the inferred types of other
2566 // variables will be propagated.
2567 //
2568 NodeLocator locator = new NodeLocator(variable.nameOffset);
2569 AstNode node = locator.searchWithin(unit);
2570 VariableDeclaration declaration =
2571 node.getAncestor((AstNode ancestor) => ancestor is VariableDeclaration);
2572 if (declaration == null || declaration.name != node) {
2573 throw new AnalysisException(
2574 "NodeLocator failed to find a variable's declaration");
2575 }
2576 RecordingErrorListener errorListener = new RecordingErrorListener();
2577 Expression initializer = declaration.initializer;
2578 ResolutionContext resolutionContext =
2579 ResolutionContextBuilder.contextFor(initializer, errorListener);
2580 ResolverVisitor visitor = new ResolverVisitor(
2581 variable.library, variable.source, typeProvider, errorListener,
2582 nameScope: resolutionContext.scope);
2583 if (resolutionContext.enclosingClassDeclaration != null) {
2584 visitor.prepareToResolveMembersInClass(
2585 resolutionContext.enclosingClassDeclaration);
2586 }
2587 visitor.initForIncrementalResolution();
Paul Berry 2015/08/29 01:14:55 It seems weird that we both manually initialize th
Brian Wilkerson 2015/08/31 15:08:52 The method initForIncrementalResolution() is also
2588 initializer.accept(visitor);
2589 //
2590 // Record the type of the variable.
2591 //
2592 DartType newType = initializer.staticType;
2593 variable.type = newType;
2594 (variable.initializer as ExecutableElementImpl).returnType = newType;
2595 if (variable is PropertyInducingElementImpl) {
2596 setReturnType(variable.getter, newType);
2597 setParameterType(variable.setter, newType);
2598 }
2599 //
2600 // Record outputs.
2601 //
2602 outputs[INFERRED_STATIC_VARIABLE] = variable;
2603 }
2604
2605 /**
2606 * Return a map from the names of the inputs of this kind of task to the task
2607 * input descriptors describing those inputs for a task with the given
2608 * [target].
2609 */
2610 static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
2611 VariableElement variable = target;
2612 LibrarySpecificUnit unit =
2613 new LibrarySpecificUnit(variable.library.source, variable.source);
2614 return <String, TaskInput>{
2615 DEPENDENCIES_INPUT: INFERABLE_STATIC_VARIABLE_DEPENDENCIES
2616 .of(variable)
2617 .toListOf(INFERRED_STATIC_VARIABLE),
2618 TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
2619 UNIT_INPUT: RESOLVED_UNIT5.of(unit)
2620 };
2621 }
2622
2623 /**
2624 * Create a [InferStaticVariableTypeTask] based on the given [target] in the
2625 * given [context].
2626 */
2627 static InferStaticVariableTypeTask createTask(
2628 AnalysisContext context, AnalysisTarget target) {
2629 return new InferStaticVariableTypeTask(context, target);
2630 }
2631 }
2632
2633 /**
2404 * A task computes all of the errors of all of the units for a single 2634 * A task computes all of the errors of all of the units for a single
2405 * library source and sets the [LIBRARY_ERRORS_READY] flag. 2635 * library source and sets the [LIBRARY_ERRORS_READY] flag.
2406 */ 2636 */
2407 class LibraryErrorsReadyTask extends SourceBasedAnalysisTask { 2637 class LibraryErrorsReadyTask extends SourceBasedAnalysisTask {
2408 /** 2638 /**
2409 * The task descriptor describing this kind of task. 2639 * The task descriptor describing this kind of task.
2410 */ 2640 */
2411 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( 2641 static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
2412 'LibraryErrorsReadyTask', 2642 'LibraryErrorsReadyTask',
2413 createTask, 2643 createTask,
(...skipping 1306 matching lines...) Expand 10 before | Expand all | Expand 10 after
3720 3950
3721 @override 3951 @override
3722 bool moveNext() { 3952 bool moveNext() {
3723 if (_newSources.isEmpty) { 3953 if (_newSources.isEmpty) {
3724 return false; 3954 return false;
3725 } 3955 }
3726 currentTarget = _newSources.removeLast(); 3956 currentTarget = _newSources.removeLast();
3727 return true; 3957 return true;
3728 } 3958 }
3729 } 3959 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698