Chromium Code Reviews| Index: pkg/analyzer/lib/src/task/dart.dart |
| diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart |
| index 2aae1a1f3dcb828444726b8985bd423ea4a1dbc9..4465b2467c17e083f7340c253c8f64297d53f6cb 100644 |
| --- a/pkg/analyzer/lib/src/task/dart.dart |
| +++ b/pkg/analyzer/lib/src/task/dart.dart |
| @@ -338,6 +338,36 @@ final ListResultDescriptor<AnalysisError> PARSE_ERRORS = |
| 'PARSE_ERRORS', AnalysisError.NO_ERRORS); |
| /** |
| + * A list of the [VariableElement]s whose type should be known to propagate |
| + * the type of another variable (the target). |
| + * |
| + * The result is only available for [VariableElement]s. |
| + */ |
| +final ListResultDescriptor<VariableElement> PROPAGABLE_VARIABLE_DEPENDENCIES = |
| + new ListResultDescriptor<VariableElement>( |
| + 'PROPAGABLE_VARIABLE_DEPENDENCIES', null); |
| + |
| +/** |
| + * A list of the [VariableElement]s defined in a unit whose type might be |
| + * propagated. This includes variables defined at the library level as well as |
| + * static and instance members inside classes. |
| + * |
| + * The result is only available for [LibrarySpecificUnit]s. |
| + */ |
| +final ListResultDescriptor<VariableElement> PROPAGABLE_VARIABLES_IN_UNIT = |
| + new ListResultDescriptor<VariableElement>( |
| + 'PROPAGABLE_VARIABLES_IN_UNIT', null); |
| + |
| +/** |
| + * An propagable variable ([VariableElement]) whose type has been propagated. |
| + * |
| + * The result is only available for [VariableElement]s. |
| + */ |
| +final ResultDescriptor<VariableElement> PROPAGATED_VARIABLE = |
| + new ResultDescriptor<VariableElement>('PROPAGATED_VARIABLE', null, |
| + cachingPolicy: ELEMENT_CACHING_POLICY); |
| + |
| +/** |
| * The flag specifying that [LIBRARY_ELEMENT2] is ready for a library and its |
| * import/export closure. |
| * |
| @@ -365,7 +395,7 @@ final ResultDescriptor<bool> READY_RESOLVED_UNIT = |
| new ResultDescriptor<bool>('READY_RESOLVED_UNIT', false); |
| /** |
| - * The flag specifying that [RESOLVED_UNIT10] is ready for all of the units of a |
| + * The flag specifying that [RESOLVED_UNIT11] is ready for all of the units of a |
| * library and its import/export closure. |
| * |
| * The result is only available for [Source]s representing a library. |
| @@ -374,7 +404,7 @@ final ResultDescriptor<bool> READY_RESOLVED_UNIT10 = |
| new ResultDescriptor<bool>('READY_RESOLVED_UNIT10', false); |
| /** |
| - * The flag specifying that [RESOLVED_UNIT9] is ready for all of the units of a |
| + * The flag specifying that [RESOLVED_UNIT10] is ready for all of the units of a |
| * library and its import/export closure. |
| * |
| * The result is only available for [Source]s representing a library. |
| @@ -427,7 +457,7 @@ final ResultDescriptor<CompilationUnit> RESOLVED_UNIT1 = |
| /** |
| * The resolved [CompilationUnit] associated with a compilation unit, with |
| - * constants resolved. |
| + * constants not yet resolved. |
| * |
| * The result is only available for [LibrarySpecificUnit]s. |
| */ |
| @@ -436,6 +466,16 @@ final ResultDescriptor<CompilationUnit> RESOLVED_UNIT10 = |
| cachingPolicy: AST_CACHING_POLICY); |
| /** |
| + * The resolved [CompilationUnit] associated with a compilation unit, with |
| + * constants resolved. |
| + * |
| + * The result is only available for [LibrarySpecificUnit]s. |
| + */ |
| +final ResultDescriptor<CompilationUnit> RESOLVED_UNIT11 = |
| + new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT11', null, |
| + cachingPolicy: AST_CACHING_POLICY); |
| + |
| +/** |
| * The partially resolved [CompilationUnit] associated with a compilation unit. |
| * |
| * Tasks that use this value as an input can assume that the [SimpleIdentifier]s |
| @@ -493,7 +533,8 @@ final ResultDescriptor<CompilationUnit> RESOLVED_UNIT5 = |
| * The partially resolved [CompilationUnit] associated with a compilation unit. |
| * |
| * In addition to what is true of a [RESOLVED_UNIT5], tasks that use this value |
| - * as an input can assume that the types of static variables have been inferred. |
| + * as an input can assume that the types of final variables have been |
| + * propagated. |
| * |
| * The result is only available for [LibrarySpecificUnit]s. |
| */ |
| @@ -505,8 +546,7 @@ final ResultDescriptor<CompilationUnit> RESOLVED_UNIT6 = |
| * The partially resolved [CompilationUnit] associated with a compilation unit. |
| * |
| * In addition to what is true of a [RESOLVED_UNIT6], tasks that use this value |
| - * as an input can assume that the initializers of instance variables have been |
| - * re-resolved. |
| + * as an input can assume that the types of static variables have been inferred. |
| * |
| * The result is only available for [LibrarySpecificUnit]s. |
| */ |
| @@ -515,9 +555,11 @@ final ResultDescriptor<CompilationUnit> RESOLVED_UNIT7 = |
| cachingPolicy: AST_CACHING_POLICY); |
| /** |
| - * The resolved [CompilationUnit] associated with a compilation unit in which |
| - * the types of class members have been inferred in addition to everything that |
| - * is true of a [RESOLVED_UNIT7]. |
| + * The partially resolved [CompilationUnit] associated with a compilation unit. |
| + * |
| + * In addition to what is true of a [RESOLVED_UNIT7], tasks that use this value |
| + * as an input can assume that the initializers of instance variables have been |
| + * re-resolved. |
| * |
| * The result is only available for [LibrarySpecificUnit]s. |
| */ |
| @@ -526,8 +568,9 @@ final ResultDescriptor<CompilationUnit> RESOLVED_UNIT8 = |
| cachingPolicy: AST_CACHING_POLICY); |
| /** |
| - * The resolved [CompilationUnit] associated with a compilation unit, with |
| - * constants not yet resolved. |
| + * The resolved [CompilationUnit] associated with a compilation unit in which |
| + * the types of class members have been inferred in addition to everything that |
| + * is true of a [RESOLVED_UNIT8]. |
| * |
| * The result is only available for [LibrarySpecificUnit]s. |
| */ |
| @@ -1638,7 +1681,7 @@ class ComputeConstantDependenciesTask extends ConstantEvaluationAnalysisTask { |
| 'Cannot build inputs for a ${target.runtimeType}'); |
| } |
| return <String, TaskInput>{ |
| - 'resolvedUnit': RESOLVED_UNIT9 |
| + 'resolvedUnit': RESOLVED_UNIT10 |
| .of(new LibrarySpecificUnit(librarySource, target.source)), |
| TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request) |
| }; |
| @@ -1940,6 +1983,92 @@ class ComputeLibraryCycleTask extends SourceBasedAnalysisTask { |
| } |
| /** |
| + * A task that computes the [PROPAGABLE_VARIABLE_DEPENDENCIES] for a variable. |
| + */ |
| +class ComputePropagableVariableDependenciesTask |
| + extends ConstantEvaluationAnalysisTask { |
| + /** |
| + * The name of the [RESOLVED_UNIT5] input. |
| + */ |
| + static const String UNIT_INPUT = 'UNIT_INPUT'; |
| + |
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( |
| + 'ComputePropagableVariableDependenciesTask', |
| + createTask, |
| + buildInputs, |
| + <ResultDescriptor>[PROPAGABLE_VARIABLE_DEPENDENCIES]); |
| + |
| + ComputePropagableVariableDependenciesTask( |
| + InternalAnalysisContext context, VariableElement variable) |
| + : super(context, variable); |
| + |
| + @override |
| + TaskDescriptor get descriptor => DESCRIPTOR; |
| + |
| + @override |
| + void internalPerform() { |
| + // |
| + // Prepare inputs. |
| + // |
| + VariableElement variable = target; |
| + CompilationUnit unit = getRequiredInput(UNIT_INPUT); |
| + // |
| + // Compute dependencies. |
| + // |
| + NodeLocator locator = new NodeLocator(variable.nameOffset); |
| + AstNode node = locator.searchWithin(unit); |
| + VariableDeclaration declaration = |
| + node.getAncestor((AstNode ancestor) => ancestor is VariableDeclaration); |
| + if (declaration == null || declaration.name != node) { |
| + throw new AnalysisException( |
| + "NodeLocator failed to find a variable's declaration"); |
| + } |
| + VariableGatherer gatherer = new VariableGatherer(_isPropagable); |
| + declaration.initializer.accept(gatherer); |
| + // |
| + // Record outputs. |
| + // |
| + outputs[PROPAGABLE_VARIABLE_DEPENDENCIES] = gatherer.results.toList(); |
| + } |
| + |
| + /** |
| + * Return `true` if the given [variable] is a variable whose type can be |
| + * propagated. |
| + */ |
| + bool _isPropagable(VariableElement variable) => |
| + (variable.isConst || variable.isFinal) && |
| + variable.hasImplicitType && |
| + variable.initializer != null; |
| + |
| + /** |
| + * Return a map from the names of the inputs of this kind of task to the task |
| + * input descriptors describing those inputs for a task with the |
| + * given [target]. |
| + */ |
| + static Map<String, TaskInput> buildInputs(AnalysisTarget target) { |
| + if (target is VariableElement) { |
| + CompilationUnitElementImpl unit = target |
| + .getAncestor((Element element) => element is CompilationUnitElement); |
| + return <String, TaskInput>{ |
| + UNIT_INPUT: RESOLVED_UNIT5 |
| + .of(new LibrarySpecificUnit(unit.librarySource, unit.source)) |
| + }; |
| + } |
| + throw new AnalysisException( |
| + 'Cannot build inputs for a ${target.runtimeType}'); |
| + } |
| + |
| + /** |
| + * Create a [ComputePropagableVariableDependenciesTask] based on the |
| + * given [target] in the given [context]. |
| + */ |
| + static ComputePropagableVariableDependenciesTask createTask( |
| + AnalysisContext context, AnalysisTarget target) { |
| + return new ComputePropagableVariableDependenciesTask(context, target); |
| + } |
| +} |
| + |
| +/** |
| * A base class for analysis tasks whose target is expected to be a |
| * [ConstantEvaluationTarget]. |
| */ |
| @@ -2202,11 +2331,11 @@ class DartErrorsTask extends SourceBasedAnalysisTask { |
| } |
| /** |
| - * A task that builds [RESOLVED_UNIT10] for a unit. |
| + * A task that builds [RESOLVED_UNIT11] for a unit. |
| */ |
| class EvaluateUnitConstantsTask extends SourceBasedAnalysisTask { |
| /** |
| - * The name of the [RESOLVED_UNIT9] input. |
| + * The name of the [RESOLVED_UNIT10] input. |
| */ |
| static const String UNIT_INPUT = 'UNIT_INPUT'; |
| @@ -2222,7 +2351,7 @@ class EvaluateUnitConstantsTask extends SourceBasedAnalysisTask { |
| 'EvaluateUnitConstantsTask', |
| createTask, |
| buildInputs, |
| - <ResultDescriptor>[RESOLVED_UNIT10]); |
| + <ResultDescriptor>[RESOLVED_UNIT11]); |
| EvaluateUnitConstantsTask(AnalysisContext context, LibrarySpecificUnit target) |
| : super(context, target); |
| @@ -2235,7 +2364,7 @@ class EvaluateUnitConstantsTask extends SourceBasedAnalysisTask { |
| // No actual work needs to be performed; the task manager will ensure that |
| // all constants are evaluated before this method is called. |
| CompilationUnit unit = getRequiredInput(UNIT_INPUT); |
| - outputs[RESOLVED_UNIT10] = unit; |
| + outputs[RESOLVED_UNIT11] = unit; |
| } |
| /** |
| @@ -2247,7 +2376,7 @@ class EvaluateUnitConstantsTask extends SourceBasedAnalysisTask { |
| LibrarySpecificUnit unit = target; |
| return <String, TaskInput>{ |
| 'libraryElement': LIBRARY_ELEMENT.of(unit.library), |
| - UNIT_INPUT: RESOLVED_UNIT9.of(unit), |
| + UNIT_INPUT: RESOLVED_UNIT10.of(unit), |
| CONSTANT_VALUES: |
| COMPILATION_UNIT_CONSTANTS.of(unit).toListOf(CONSTANT_VALUE) |
| }; |
| @@ -2371,7 +2500,7 @@ class ExportNamespaceBuilder { |
| */ |
| class GatherUsedImportedElementsTask extends SourceBasedAnalysisTask { |
| /** |
| - * The name of the [RESOLVED_UNIT9] input. |
| + * The name of the [RESOLVED_UNIT10] input. |
| */ |
| static const String UNIT_INPUT = 'UNIT_INPUT'; |
| @@ -2415,7 +2544,7 @@ class GatherUsedImportedElementsTask extends SourceBasedAnalysisTask { |
| */ |
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) { |
| LibrarySpecificUnit unit = target; |
| - return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT9.of(unit)}; |
| + return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT10.of(unit)}; |
| } |
| /** |
| @@ -2433,7 +2562,7 @@ class GatherUsedImportedElementsTask extends SourceBasedAnalysisTask { |
| */ |
| class GatherUsedLocalElementsTask extends SourceBasedAnalysisTask { |
| /** |
| - * The name of the [RESOLVED_UNIT9] input. |
| + * The name of the [RESOLVED_UNIT10] input. |
| */ |
| static const String UNIT_INPUT = 'UNIT_INPUT'; |
| @@ -2477,7 +2606,7 @@ class GatherUsedLocalElementsTask extends SourceBasedAnalysisTask { |
| */ |
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) { |
| LibrarySpecificUnit unit = target; |
| - return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT9.of(unit)}; |
| + return <String, TaskInput>{UNIT_INPUT: RESOLVED_UNIT10.of(unit)}; |
| } |
| /** |
| @@ -2495,7 +2624,7 @@ class GatherUsedLocalElementsTask extends SourceBasedAnalysisTask { |
| */ |
| class GenerateHintsTask extends SourceBasedAnalysisTask { |
| /** |
| - * The name of the [RESOLVED_UNIT9] input. |
| + * The name of the [RESOLVED_UNIT10] input. |
| */ |
| static const String RESOLVED_UNIT_INPUT = 'RESOLVED_UNIT'; |
| @@ -2701,7 +2830,7 @@ class InferInstanceMembersInUnitTask extends SourceBasedAnalysisTask { |
| static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT'; |
| /** |
| - * The name of the input whose value is the [RESOLVED_UNIT6] for the |
| + * The name of the input whose value is the [RESOLVED_UNIT7] for the |
| * compilation unit. |
| */ |
| static const String UNIT_INPUT = 'UNIT_INPUT'; |
| @@ -2713,7 +2842,7 @@ class InferInstanceMembersInUnitTask extends SourceBasedAnalysisTask { |
| 'InferInstanceMembersInUnitTask', |
| createTask, |
| buildInputs, |
| - <ResultDescriptor>[RESOLVED_UNIT8]); |
| + <ResultDescriptor>[RESOLVED_UNIT9]); |
| /** |
| * Initialize a newly created task to build a library element for the given |
| @@ -2744,7 +2873,7 @@ class InferInstanceMembersInUnitTask extends SourceBasedAnalysisTask { |
| // |
| // Record outputs. |
| // |
| - outputs[RESOLVED_UNIT8] = unit; |
| + outputs[RESOLVED_UNIT9] = unit; |
| } |
| /** |
| @@ -2755,7 +2884,7 @@ class InferInstanceMembersInUnitTask extends SourceBasedAnalysisTask { |
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) { |
| LibrarySpecificUnit unit = target; |
| return <String, TaskInput>{ |
| - UNIT_INPUT: RESOLVED_UNIT7.of(unit), |
| + UNIT_INPUT: RESOLVED_UNIT8.of(unit), |
| TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request), |
| // In strong mode, add additional dependencies to enforce inference |
| // ordering. |
| @@ -2763,12 +2892,12 @@ class InferInstanceMembersInUnitTask extends SourceBasedAnalysisTask { |
| // Require that field re-resolution be complete for all units in the |
| // current library cycle. |
| 'orderLibraryCycleTasks': LIBRARY_CYCLE_UNITS.of(unit).toList( |
| - (CompilationUnitElementImpl unit) => RESOLVED_UNIT7 |
| + (CompilationUnitElementImpl unit) => RESOLVED_UNIT8 |
| .of(new LibrarySpecificUnit(unit.librarySource, unit.source))), |
| // Require that full inference be complete for all dependencies of the |
| // current library cycle. |
| 'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList( |
| - (CompilationUnitElementImpl unit) => RESOLVED_UNIT8 |
| + (CompilationUnitElementImpl unit) => RESOLVED_UNIT9 |
| .of(new LibrarySpecificUnit(unit.librarySource, unit.source))) |
| }; |
| } |
| @@ -2816,7 +2945,7 @@ abstract class InferStaticVariableTask extends ConstantEvaluationAnalysisTask { |
| */ |
| class InferStaticVariableTypesInUnitTask extends SourceBasedAnalysisTask { |
| /** |
| - * The name of the input whose value is the [RESOLVED_UNIT5] for the |
| + * The name of the input whose value is the [RESOLVED_UNIT6] for the |
| * compilation unit. |
| */ |
| static const String UNIT_INPUT = 'UNIT_INPUT'; |
| @@ -2834,7 +2963,7 @@ class InferStaticVariableTypesInUnitTask extends SourceBasedAnalysisTask { |
| 'InferStaticVariableTypesInUnitTask', |
| createTask, |
| buildInputs, |
| - <ResultDescriptor>[RESOLVED_UNIT6]); |
| + <ResultDescriptor>[RESOLVED_UNIT7]); |
| /** |
| * Initialize a newly created task to build a library element for the given |
| @@ -2858,7 +2987,7 @@ class InferStaticVariableTypesInUnitTask extends SourceBasedAnalysisTask { |
| // because the work has implicitly been done by virtue of the task model |
| // preparing all of the inputs. |
| // |
| - outputs[RESOLVED_UNIT6] = unit; |
| + outputs[RESOLVED_UNIT7] = unit; |
| } |
| /** |
| @@ -2872,7 +3001,7 @@ class InferStaticVariableTypesInUnitTask extends SourceBasedAnalysisTask { |
| INFERRED_VARIABLES_INPUT: INFERABLE_STATIC_VARIABLES_IN_UNIT |
| .of(unit) |
| .toListOf(INFERRED_STATIC_VARIABLE), |
| - UNIT_INPUT: RESOLVED_UNIT5.of(unit) |
| + UNIT_INPUT: RESOLVED_UNIT6.of(unit) |
| }; |
| } |
| @@ -2903,7 +3032,7 @@ class InferStaticVariableTypeTask extends InferStaticVariableTask { |
| static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT'; |
| /** |
| - * The name of the [RESOLVED_UNIT5] input. |
| + * The name of the [RESOLVED_UNIT6] input. |
| */ |
| static const String UNIT_INPUT = 'UNIT_INPUT'; |
| @@ -3001,14 +3130,14 @@ class InferStaticVariableTypeTask extends InferStaticVariableTask { |
| .of(variable) |
| .toListOf(INFERRED_STATIC_VARIABLE), |
| TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request), |
| - UNIT_INPUT: RESOLVED_UNIT5.of(unit), |
| + UNIT_INPUT: RESOLVED_UNIT6.of(unit), |
| // In strong mode, add additional dependencies to enforce inference |
| // ordering. |
| // Require that full inference be complete for all dependencies of the |
| // current library cycle. |
| 'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList( |
| - (CompilationUnitElementImpl unit) => RESOLVED_UNIT8 |
| + (CompilationUnitElementImpl unit) => RESOLVED_UNIT9 |
| .of(new LibrarySpecificUnit(unit.librarySource, unit.source))) |
| }; |
| } |
| @@ -3418,8 +3547,11 @@ class PartiallyResolveUnitReferencesTask extends SourceBasedAnalysisTask { |
| static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( |
| 'PartiallyResolveUnitReferencesTask', |
| createTask, |
| - buildInputs, |
| - <ResultDescriptor>[INFERABLE_STATIC_VARIABLES_IN_UNIT, RESOLVED_UNIT5]); |
| + buildInputs, <ResultDescriptor>[ |
| + INFERABLE_STATIC_VARIABLES_IN_UNIT, |
| + PROPAGABLE_VARIABLES_IN_UNIT, |
| + RESOLVED_UNIT5 |
| + ]); |
| PartiallyResolveUnitReferencesTask( |
| InternalAnalysisContext context, AnalysisTarget target) |
| @@ -3440,21 +3572,21 @@ class PartiallyResolveUnitReferencesTask extends SourceBasedAnalysisTask { |
| // |
| // Resolve references and record outputs. |
| // |
| + InheritanceManager inheritanceManager = |
| + new InheritanceManager(libraryElement); |
| + PartialResolverVisitor visitor = new PartialResolverVisitor(libraryElement, |
| + unitElement.source, typeProvider, AnalysisErrorListener.NULL_LISTENER, |
| + inheritanceManager: inheritanceManager); |
| + unit.accept(visitor); |
| + // |
| + // Record outputs. |
| + // |
| if (context.analysisOptions.strongMode) { |
| - InheritanceManager inheritanceManager = |
| - new InheritanceManager(libraryElement); |
| - PartialResolverVisitor visitor = new PartialResolverVisitor( |
| - libraryElement, |
| - unitElement.source, |
| - typeProvider, |
| - AnalysisErrorListener.NULL_LISTENER, |
| - inheritanceManager: inheritanceManager); |
| - unit.accept(visitor); |
| - |
| - outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT] = visitor.variablesAndFields; |
| + outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT] = visitor.staticVariables; |
| } else { |
| - outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT] = []; |
| + outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT] = VariableElement.EMPTY_LIST; |
| } |
| + outputs[PROPAGABLE_VARIABLES_IN_UNIT] = visitor.propagableVariables; |
| outputs[RESOLVED_UNIT5] = unit; |
| } |
| @@ -3476,7 +3608,7 @@ class PartiallyResolveUnitReferencesTask extends SourceBasedAnalysisTask { |
| // Require that full inference be complete for all dependencies of the |
| // current library cycle. |
| 'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList( |
| - (CompilationUnitElementImpl unit) => RESOLVED_UNIT8 |
| + (CompilationUnitElementImpl unit) => RESOLVED_UNIT9 |
| .of(new LibrarySpecificUnit(unit.librarySource, unit.source))) |
| }; |
| } |
| @@ -3492,6 +3624,174 @@ class PartiallyResolveUnitReferencesTask extends SourceBasedAnalysisTask { |
| } |
| /** |
| + * A task that ensures that all of the propagable variables in a compilation |
| + * unit have had their type propagated. |
| + */ |
| +class PropagateVariableTypesInUnitTask extends SourceBasedAnalysisTask { |
| + /** |
| + * The name of the input whose value is the [RESOLVED_UNIT5] for the |
| + * compilation unit. |
| + */ |
| + static const String UNIT_INPUT = 'UNIT_INPUT'; |
| + |
| + /** |
| + * The task descriptor describing this kind of task. |
| + */ |
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( |
| + 'PropagateVariableTypesInUnitTask', |
| + createTask, |
| + buildInputs, |
| + <ResultDescriptor>[RESOLVED_UNIT6]); |
| + |
| + PropagateVariableTypesInUnitTask( |
| + InternalAnalysisContext context, LibrarySpecificUnit unit) |
| + : super(context, unit); |
| + |
| + @override |
| + TaskDescriptor get descriptor => DESCRIPTOR; |
| + |
| + @override |
| + void internalPerform() { |
| + // |
| + // Prepare inputs. |
| + // |
| + CompilationUnit unit = getRequiredInput(UNIT_INPUT); |
| + // |
| + // Record outputs. There is no additional work to be done at this time |
| + // because the work has implicitly been done by virtue of the task model |
| + // preparing all of the inputs. |
| + // |
| + outputs[RESOLVED_UNIT6] = unit; |
| + } |
| + |
| + /** |
| + * Return a map from the names of the inputs of this kind of task to the task |
| + * input descriptors describing those inputs for a task with the given |
| + * [target]. |
| + */ |
| + static Map<String, TaskInput> buildInputs(AnalysisTarget target) { |
| + LibrarySpecificUnit unit = target; |
| + return <String, TaskInput>{ |
| + 'variables': |
| + PROPAGABLE_VARIABLES_IN_UNIT.of(unit).toListOf(PROPAGATED_VARIABLE), |
| + UNIT_INPUT: RESOLVED_UNIT5.of(unit) |
| + }; |
| + } |
| + |
| + /** |
| + * Create a [PropagateVariableTypesInUnitTask] based on the given [target] |
| + * in the given [context]. |
| + */ |
| + static PropagateVariableTypesInUnitTask createTask( |
| + AnalysisContext context, AnalysisTarget target) { |
| + return new PropagateVariableTypesInUnitTask(context, target); |
| + } |
| +} |
| + |
| +/** |
| + * A task that computes the propagated type of an propagable variable and |
| + * stores it in the element model. |
| + */ |
| +class PropagateVariableTypeTask extends InferStaticVariableTask { |
| + /** |
| + * The name of the [TYPE_PROVIDER] input. |
| + */ |
| + static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT'; |
| + |
| + /** |
| + * The name of the [RESOLVED_UNIT5] input. |
| + */ |
| + static const String UNIT_INPUT = 'UNIT_INPUT'; |
| + |
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( |
| + 'PropagateVariableTypeTask', |
| + createTask, |
| + buildInputs, |
| + <ResultDescriptor>[PROPAGATED_VARIABLE]); |
| + |
| + PropagateVariableTypeTask( |
| + InternalAnalysisContext context, VariableElement variable) |
| + : super(context, variable); |
| + |
| + @override |
| + TaskDescriptor get descriptor => DESCRIPTOR; |
| + |
| + @override |
| + bool get handlesDependencyCycles => true; |
| + |
| + @override |
| + void internalPerform() { |
| + // |
| + // Prepare inputs. |
| + // |
| + PropertyInducingElementImpl variable = target; |
| + TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT); |
| + CompilationUnit unit = getRequiredInput(UNIT_INPUT); |
| + |
| + // If we're not in a dependency cycle, and we have no type annotation, |
| + // re-resolve the right hand side and do inference. |
| + if (dependencyCycle == null && variable.hasImplicitType) { |
| + VariableDeclaration declaration = getDeclaration(unit); |
| + // |
| + // Re-resolve the variable's initializer so that the inferred types |
|
Brian Wilkerson
2015/11/21 15:11:26
"inferred" --> "propagated"?
|
| + // of other variables will be propagated. |
| + // |
| + Expression initializer = declaration.initializer; |
| + ResolutionContext resolutionContext = ResolutionContextBuilder.contextFor( |
| + initializer, AnalysisErrorListener.NULL_LISTENER); |
| + ResolverVisitor visitor = new ResolverVisitor(variable.library, |
| + variable.source, typeProvider, AnalysisErrorListener.NULL_LISTENER, |
| + nameScope: resolutionContext.scope); |
| + if (resolutionContext.enclosingClassDeclaration != null) { |
| + visitor.prepareToResolveMembersInClass( |
| + resolutionContext.enclosingClassDeclaration); |
| + } |
| + visitor.initForIncrementalResolution(); |
| + initializer.accept(visitor); |
| + // |
| + // Record the type of the variable. |
| + // |
| + DartType newType = initializer.bestType; |
|
Brian Wilkerson
2015/11/21 15:11:26
I think this wants to be the propagatedType, not t
scheglov
2015/11/21 17:37:23
Actually in the most cases the initializer is a va
|
| + if (newType == null || newType.isBottom || newType.isDynamic) { |
| + newType = null; |
| + } |
| + variable.propagatedType = newType; |
| + } |
| + // |
| + // Record outputs. |
| + // |
| + outputs[PROPAGATED_VARIABLE] = variable; |
| + } |
| + |
| + /** |
| + * Return a map from the names of the inputs of this kind of task to the task |
| + * input descriptors describing those inputs for a task with the given |
| + * [target]. |
| + */ |
| + static Map<String, TaskInput> buildInputs(AnalysisTarget target) { |
| + VariableElement variable = target; |
| + LibrarySpecificUnit unit = |
| + new LibrarySpecificUnit(variable.library.source, variable.source); |
| + return <String, TaskInput>{ |
| + 'dependencies': PROPAGABLE_VARIABLE_DEPENDENCIES |
| + .of(variable) |
| + .toListOf(PROPAGATED_VARIABLE), |
| + TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request), |
| + UNIT_INPUT: RESOLVED_UNIT5.of(unit), |
| + }; |
| + } |
| + |
| + /** |
| + * Create a [PropagateVariableTypeTask] based on the given [target] in the |
| + * given [context]. |
| + */ |
| + static PropagateVariableTypeTask createTask( |
| + AnalysisContext context, AnalysisTarget target) { |
| + return new PropagateVariableTypeTask(context, target); |
| + } |
| +} |
| + |
| +/** |
| * The helper for building the public [Namespace] of a [LibraryElement]. |
| */ |
| class PublicNamespaceBuilder { |
| @@ -3617,7 +3917,7 @@ class ReadyLibraryElement5Task extends SourceBasedAnalysisTask { |
| } |
| /** |
| - * A task that ensures that [RESOLVED_UNIT10] is ready for every unit of the |
| + * A task that ensures that [RESOLVED_UNIT11] is ready for every unit of the |
| * target library source and its import/export closure. |
| */ |
| class ReadyResolvedUnit10Task extends SourceBasedAnalysisTask { |
| @@ -3646,7 +3946,7 @@ class ReadyResolvedUnit10Task extends SourceBasedAnalysisTask { |
| Source source = target; |
| return <String, TaskInput>{ |
| 'thisLibraryUnitsReady': |
| - LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT10), |
| + LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT11), |
| 'directlyImportedLibrariesReady': |
| IMPORTED_LIBRARIES.of(source).toListOf(READY_RESOLVED_UNIT10), |
| 'directlyExportedLibrariesReady': |
| @@ -3661,7 +3961,7 @@ class ReadyResolvedUnit10Task extends SourceBasedAnalysisTask { |
| } |
| /** |
| - * A task that ensures that [RESOLVED_UNIT9] is ready for every unit of the |
| + * A task that ensures that [RESOLVED_UNIT10] is ready for every unit of the |
| * target library source and its import/export closure. |
| */ |
| class ReadyResolvedUnit9Task extends SourceBasedAnalysisTask { |
| @@ -3689,7 +3989,7 @@ class ReadyResolvedUnit9Task extends SourceBasedAnalysisTask { |
| Source source = target; |
| return <String, TaskInput>{ |
| 'thisLibraryUnitsReady': |
| - LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT9), |
| + LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT10), |
| 'directlyImportedLibrariesReady': |
| IMPORTED_LIBRARIES.of(source).toListOf(READY_RESOLVED_UNIT9), |
| 'directlyExportedLibrariesReady': |
| @@ -3860,7 +4160,7 @@ class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask { |
| static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT'; |
| /** |
| - * The name of the input whose value is the [RESOLVED_UNIT6] for the |
| + * The name of the input whose value is the [RESOLVED_UNIT7] for the |
| * compilation unit. |
| */ |
| static const String UNIT_INPUT = 'UNIT_INPUT'; |
| @@ -3872,7 +4172,7 @@ class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask { |
| 'ResolveInstanceFieldsInUnitTask', |
| createTask, |
| buildInputs, |
| - <ResultDescriptor>[RESOLVED_UNIT7]); |
| + <ResultDescriptor>[RESOLVED_UNIT8]); |
| /** |
| * Initialize a newly created task to build a library element for the given |
| @@ -3920,7 +4220,7 @@ class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask { |
| // |
| // Record outputs. |
| // |
| - outputs[RESOLVED_UNIT7] = unit; |
| + outputs[RESOLVED_UNIT8] = unit; |
| } |
| /** |
| @@ -3931,7 +4231,7 @@ class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask { |
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) { |
| LibrarySpecificUnit unit = target; |
| return <String, TaskInput>{ |
| - UNIT_INPUT: RESOLVED_UNIT6.of(unit), |
| + UNIT_INPUT: RESOLVED_UNIT7.of(unit), |
| LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library), |
| TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request), |
| // In strong mode, add additional dependencies to enforce inference |
| @@ -3940,12 +4240,12 @@ class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask { |
| // Require that static variable inference be complete for all units in |
| // the current library cycle. |
| 'orderLibraryCycleTasks': LIBRARY_CYCLE_UNITS.of(unit).toList( |
| - (CompilationUnitElementImpl unit) => RESOLVED_UNIT6 |
| + (CompilationUnitElementImpl unit) => RESOLVED_UNIT7 |
| .of(new LibrarySpecificUnit(unit.librarySource, unit.source))), |
| // Require that full inference be complete for all dependencies of the |
| // current library cycle. |
| 'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES.of(unit).toList( |
| - (CompilationUnitElementImpl unit) => RESOLVED_UNIT8 |
| + (CompilationUnitElementImpl unit) => RESOLVED_UNIT9 |
| .of(new LibrarySpecificUnit(unit.librarySource, unit.source))) |
| }; |
| } |
| @@ -3961,7 +4261,7 @@ class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask { |
| } |
| /** |
| - * A task that finishes resolution by requesting [RESOLVED_UNIT9] for every |
| + * A task that finishes resolution by requesting [RESOLVED_UNIT10] for every |
| * unit in the libraries closure and produces [LIBRARY_ELEMENT]. |
| */ |
| class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask { |
| @@ -3971,7 +4271,7 @@ class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask { |
| static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; |
| /** |
| - * The name of the list of [RESOLVED_UNIT9] input. |
| + * The name of the list of [RESOLVED_UNIT10] input. |
| */ |
| static const String UNITS_INPUT = 'UNITS_INPUT'; |
| @@ -4019,7 +4319,7 @@ class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask { |
| Source source = target; |
| return <String, TaskInput>{ |
| LIBRARY_INPUT: LIBRARY_ELEMENT5.of(source), |
| - UNITS_INPUT: LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT9), |
| + UNITS_INPUT: LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT10), |
| 'thisLibraryClosureIsReady': READY_RESOLVED_UNIT9.of(source), |
| }; |
| } |
| @@ -4123,7 +4423,7 @@ class ResolveUnitTask extends SourceBasedAnalysisTask { |
| static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT'; |
| /** |
| - * The name of the [RESOLVED_UNIT8] input. |
| + * The name of the [RESOLVED_UNIT9] input. |
| */ |
| static const String UNIT_INPUT = 'UNIT_INPUT'; |
| @@ -4131,7 +4431,7 @@ class ResolveUnitTask extends SourceBasedAnalysisTask { |
| 'ResolveUnitTask', |
| createTask, |
| buildInputs, |
| - <ResultDescriptor>[RESOLVE_UNIT_ERRORS, RESOLVED_UNIT9]); |
| + <ResultDescriptor>[RESOLVE_UNIT_ERRORS, RESOLVED_UNIT10]); |
| ResolveUnitTask( |
| InternalAnalysisContext context, LibrarySpecificUnit compilationUnit) |
| @@ -4164,7 +4464,7 @@ class ResolveUnitTask extends SourceBasedAnalysisTask { |
| // updated version of the element model. |
| // |
| outputs[RESOLVE_UNIT_ERRORS] = errorListener.errors; |
| - outputs[RESOLVED_UNIT9] = unit; |
| + outputs[RESOLVED_UNIT10] = unit; |
| } |
| /** |
| @@ -4177,14 +4477,14 @@ class ResolveUnitTask extends SourceBasedAnalysisTask { |
| return <String, TaskInput>{ |
| LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library), |
| TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request), |
| - UNIT_INPUT: RESOLVED_UNIT8.of(unit), |
| + UNIT_INPUT: RESOLVED_UNIT9.of(unit), |
| // In strong mode, add additional dependencies to enforce inference |
| // ordering. |
| // Require that inference be complete for all units in the |
| // current library cycle. |
| 'orderLibraryCycleTasks': LIBRARY_CYCLE_UNITS.of(unit).toList( |
| - (CompilationUnitElementImpl unit) => RESOLVED_UNIT8 |
| + (CompilationUnitElementImpl unit) => RESOLVED_UNIT9 |
| .of(new LibrarySpecificUnit(unit.librarySource, unit.source))) |
| }; |
| } |
| @@ -4493,7 +4793,7 @@ class ScanDartTask extends SourceBasedAnalysisTask { |
| */ |
| class StrongModeVerifyUnitTask extends SourceBasedAnalysisTask { |
| /** |
| - * The name of the [RESOLVED_UNIT10] input. |
| + * The name of the [RESOLVED_UNIT11] input. |
| */ |
| static const String UNIT_INPUT = 'UNIT_INPUT'; |
| @@ -4545,7 +4845,7 @@ class StrongModeVerifyUnitTask extends SourceBasedAnalysisTask { |
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) { |
| LibrarySpecificUnit unit = target; |
| return <String, TaskInput>{ |
| - UNIT_INPUT: RESOLVED_UNIT10.of(unit), |
| + UNIT_INPUT: RESOLVED_UNIT11.of(unit), |
| TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request), |
| 'thisLibraryClosureIsReady': READY_RESOLVED_UNIT10.of(unit.library), |
| }; |