| Index: packages/analyzer/lib/src/task/dart.dart
|
| diff --git a/packages/analyzer/lib/src/task/dart.dart b/packages/analyzer/lib/src/task/dart.dart
|
| index b87f7763338f8bf316b1c20dcced7f3d227295d5..a2e46887d6165e8e0ea59978f99d18fc86ea2a73 100644
|
| --- a/packages/analyzer/lib/src/task/dart.dart
|
| +++ b/packages/analyzer/lib/src/task/dart.dart
|
| @@ -6,31 +6,43 @@ library analyzer.src.task.dart;
|
|
|
| import 'dart:collection';
|
|
|
| +import 'package:analyzer/dart/ast/ast.dart';
|
| +import 'package:analyzer/dart/ast/token.dart';
|
| +import 'package:analyzer/dart/ast/visitor.dart';
|
| +import 'package:analyzer/dart/element/element.dart';
|
| +import 'package:analyzer/dart/element/type.dart';
|
| +import 'package:analyzer/error/error.dart';
|
| +import 'package:analyzer/error/listener.dart';
|
| +import 'package:analyzer/exception/exception.dart';
|
| import 'package:analyzer/src/context/cache.dart';
|
| -import 'package:analyzer/src/generated/ast.dart';
|
| +import 'package:analyzer/src/dart/ast/ast.dart'
|
| + show NamespaceDirectiveImpl, UriBasedDirectiveImpl, UriValidationCode;
|
| +import 'package:analyzer/src/dart/ast/utilities.dart';
|
| +import 'package:analyzer/src/dart/element/builder.dart';
|
| +import 'package:analyzer/src/dart/element/element.dart';
|
| +import 'package:analyzer/src/dart/resolver/inheritance_manager.dart';
|
| +import 'package:analyzer/src/dart/scanner/reader.dart';
|
| +import 'package:analyzer/src/dart/scanner/scanner.dart';
|
| +import 'package:analyzer/src/error/codes.dart';
|
| +import 'package:analyzer/src/error/pending_error.dart';
|
| import 'package:analyzer/src/generated/constant.dart';
|
| -import 'package:analyzer/src/generated/element.dart';
|
| -import 'package:analyzer/src/generated/engine.dart'
|
| - hide AnalysisCache, AnalysisTask;
|
| -import 'package:analyzer/src/generated/error.dart';
|
| +import 'package:analyzer/src/generated/engine.dart';
|
| import 'package:analyzer/src/generated/error_verifier.dart';
|
| import 'package:analyzer/src/generated/incremental_resolver.dart';
|
| -import 'package:analyzer/src/generated/java_engine.dart';
|
| import 'package:analyzer/src/generated/parser.dart';
|
| import 'package:analyzer/src/generated/resolver.dart';
|
| -import 'package:analyzer/src/generated/scanner.dart';
|
| import 'package:analyzer/src/generated/sdk.dart';
|
| import 'package:analyzer/src/generated/source.dart';
|
| -import 'package:analyzer/src/generated/visitors.dart';
|
| +import 'package:analyzer/src/generated/utilities_dart.dart';
|
| import 'package:analyzer/src/plugin/engine_plugin.dart';
|
| import 'package:analyzer/src/services/lint.dart';
|
| import 'package:analyzer/src/task/driver.dart';
|
| import 'package:analyzer/src/task/general.dart';
|
| import 'package:analyzer/src/task/html.dart';
|
| +import 'package:analyzer/src/task/incremental_element_builder.dart';
|
| import 'package:analyzer/src/task/inputs.dart';
|
| import 'package:analyzer/src/task/model.dart';
|
| import 'package:analyzer/src/task/strong/checker.dart';
|
| -import 'package:analyzer/src/task/strong/rules.dart';
|
| import 'package:analyzer/src/task/strong_mode.dart';
|
| import 'package:analyzer/task/dart.dart';
|
| import 'package:analyzer/task/general.dart';
|
| @@ -39,21 +51,66 @@ import 'package:analyzer/task/model.dart';
|
| /**
|
| * The [ResultCachingPolicy] for ASTs.
|
| */
|
| -const ResultCachingPolicy AST_CACHING_POLICY =
|
| - const SimpleResultCachingPolicy(8192, 8192);
|
| +const ResultCachingPolicy<CompilationUnit> AST_CACHING_POLICY =
|
| + const SimpleResultCachingPolicy(16384, 32);
|
| +
|
| +/**
|
| + * The [ResultCachingPolicy] for fully resolved ASTs. It is separated from
|
| + * [AST_CACHING_POLICY] because we want to keep some number of fully resolved
|
| + * ASTs when users switch between contexts, and they should not be pushed out
|
| + * of the cache by temporary partially resolved ASTs.
|
| + */
|
| +const ResultCachingPolicy<CompilationUnit> AST_RESOLVED_CACHING_POLICY =
|
| + const SimpleResultCachingPolicy(1024, 32);
|
| +
|
| +/**
|
| + * The [ResultCachingPolicy] for ASTs that can be reused when a library
|
| + * on which the source depends is changed. It is worth to keep some number
|
| + * of these ASTs in memory in order to avoid parsing sources. In contrast,
|
| + * none of [AST_CACHING_POLICY] managed ASTs can be reused after a change, so
|
| + * it is worth to keep them in memory while analysis is being performed, but
|
| + * once analysis is done, they can be flushed.
|
| + */
|
| +const ResultCachingPolicy<CompilationUnit> AST_REUSABLE_CACHING_POLICY =
|
| + const SimpleResultCachingPolicy(1024, 64);
|
| +
|
| +/**
|
| + * The [ResultCachingPolicy] for lists of [ConstantEvaluationTarget]s.
|
| + */
|
| +const ResultCachingPolicy<List<ConstantEvaluationTarget>>
|
| + CONSTANT_EVALUATION_TARGET_LIST_POLICY =
|
| + const SimpleResultCachingPolicy(-1, -1);
|
| +
|
| +/**
|
| + * The [ResultCachingPolicy] for [ConstantEvaluationTarget]s.
|
| + */
|
| +const ResultCachingPolicy<ConstantEvaluationTarget>
|
| + CONSTANT_EVALUATION_TARGET_POLICY = const SimpleResultCachingPolicy(-1, -1);
|
|
|
| /**
|
| * The [ResultCachingPolicy] for [Element]s.
|
| */
|
| -const ResultCachingPolicy ELEMENT_CACHING_POLICY =
|
| +const ResultCachingPolicy<Element> ELEMENT_CACHING_POLICY =
|
| const SimpleResultCachingPolicy(-1, -1);
|
|
|
| /**
|
| * The [ResultCachingPolicy] for [TOKEN_STREAM].
|
| */
|
| -const ResultCachingPolicy TOKEN_STREAM_CACHING_POLICY =
|
| +const ResultCachingPolicy<Token> TOKEN_STREAM_CACHING_POLICY =
|
| const SimpleResultCachingPolicy(1, 1);
|
|
|
| +/**
|
| + * The [ResultCachingPolicy] for [UsedImportedElements]s.
|
| + */
|
| +const ResultCachingPolicy<UsedImportedElements> USED_IMPORTED_ELEMENTS_POLICY =
|
| + const SimpleResultCachingPolicy(-1, -1);
|
| +
|
| +/**
|
| + * The [ResultCachingPolicy] for [UsedLocalElements]s.
|
| + */
|
| +const ResultCachingPolicy<UsedLocalElements> USED_LOCAL_ELEMENTS_POLICY =
|
| + const SimpleResultCachingPolicy(-1, -1);
|
| +
|
| /**
|
| * The errors produced while resolving a library directives.
|
| *
|
| @@ -80,15 +137,15 @@ final ListResultDescriptor<AnalysisError> BUILD_LIBRARY_ERRORS =
|
| * A list of the [ConstantEvaluationTarget]s defined in a unit. This includes
|
| * constants defined at top level, statically inside classes, and local to
|
| * functions, as well as constant constructors, annotations, and default values
|
| - * of parameters to constant constructors.
|
| + * of parameters.
|
| *
|
| * The result is only available for [LibrarySpecificUnit]s.
|
| */
|
| -final ListResultDescriptor<
|
| - ConstantEvaluationTarget> COMPILATION_UNIT_CONSTANTS =
|
| +final ListResultDescriptor<ConstantEvaluationTarget>
|
| + COMPILATION_UNIT_CONSTANTS =
|
| new ListResultDescriptor<ConstantEvaluationTarget>(
|
| 'COMPILATION_UNIT_CONSTANTS', null,
|
| - cachingPolicy: ELEMENT_CACHING_POLICY);
|
| + cachingPolicy: CONSTANT_EVALUATION_TARGET_LIST_POLICY);
|
|
|
| /**
|
| * The element model associated with a single compilation unit.
|
| @@ -112,6 +169,29 @@ final ListResultDescriptor<ConstantEvaluationTarget> CONSTANT_DEPENDENCIES =
|
| new ListResultDescriptor<ConstantEvaluationTarget>(
|
| 'CONSTANT_DEPENDENCIES', const <ConstantEvaluationTarget>[]);
|
|
|
| +/**
|
| + * The flag specifying that the target constant element expression AST is
|
| + * resolved, i.e. identifiers have all required elements set.
|
| + *
|
| + * The result is only available for targets representing a
|
| + * [ConstantEvaluationTarget] (i.e. a constant variable declaration, a constant
|
| + * constructor, or a parameter element with a default value).
|
| + */
|
| +final ResultDescriptor<bool> CONSTANT_EXPRESSION_RESOLVED =
|
| + new ResultDescriptor<bool>('CONSTANT_EXPRESSION_RESOLVED', false);
|
| +
|
| +/**
|
| + * The list of [ConstantEvaluationTarget]s on which constant expressions of a
|
| + * unit depend.
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ListResultDescriptor<ConstantEvaluationTarget>
|
| + CONSTANT_EXPRESSIONS_DEPENDENCIES =
|
| + new ListResultDescriptor<ConstantEvaluationTarget>(
|
| + 'CONSTANT_EXPRESSIONS_DEPENDENCIES',
|
| + const <ConstantEvaluationTarget>[]);
|
| +
|
| /**
|
| * A [ConstantEvaluationTarget] that has been successfully constant-evaluated.
|
| *
|
| @@ -122,7 +202,7 @@ final ListResultDescriptor<ConstantEvaluationTarget> CONSTANT_DEPENDENCIES =
|
| */
|
| final ResultDescriptor<ConstantEvaluationTarget> CONSTANT_VALUE =
|
| new ResultDescriptor<ConstantEvaluationTarget>('CONSTANT_VALUE', null,
|
| - cachingPolicy: ELEMENT_CACHING_POLICY);
|
| + cachingPolicy: CONSTANT_EVALUATION_TARGET_POLICY);
|
|
|
| /**
|
| * The sources representing the libraries that include a given source as a part.
|
| @@ -132,6 +212,150 @@ final ResultDescriptor<ConstantEvaluationTarget> CONSTANT_VALUE =
|
| final ListResultDescriptor<Source> CONTAINING_LIBRARIES =
|
| new ListResultDescriptor<Source>('CONTAINING_LIBRARIES', Source.EMPTY_LIST);
|
|
|
| +/**
|
| + * The flag specifying that [RESOLVED_UNIT] has been been computed for this
|
| + * compilation unit (without requiring that the AST for it still be in cache).
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ResultDescriptor<bool> CREATED_RESOLVED_UNIT =
|
| + new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT', false);
|
| +
|
| +/**
|
| + * The flag specifying that [RESOLVED_UNIT1] has been been computed for this
|
| + * compilation unit (without requiring that the AST for it still be in cache).
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ResultDescriptor<bool> CREATED_RESOLVED_UNIT1 =
|
| + new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT1', false);
|
| +
|
| +/**
|
| + * The flag specifying that [RESOLVED_UNIT10] has been been computed for this
|
| + * compilation unit (without requiring that the AST for it still be in cache).
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ResultDescriptor<bool> CREATED_RESOLVED_UNIT10 =
|
| + new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT10', false);
|
| +
|
| +/**
|
| + * The flag specifying that [RESOLVED_UNIT11] has been been computed for this
|
| + * compilation unit (without requiring that the AST for it still be in cache).
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ResultDescriptor<bool> CREATED_RESOLVED_UNIT11 =
|
| + new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT11', false);
|
| +
|
| +/**
|
| + * The flag specifying that [RESOLVED_UNIT12] has been been computed for this
|
| + * compilation unit (without requiring that the AST for it still be in cache).
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ResultDescriptor<bool> CREATED_RESOLVED_UNIT12 =
|
| + new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT12', false);
|
| +
|
| +/**
|
| + * The flag specifying that [RESOLVED_UNIT2] has been been computed for this
|
| + * compilation unit (without requiring that the AST for it still be in cache).
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ResultDescriptor<bool> CREATED_RESOLVED_UNIT2 =
|
| + new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT2', false);
|
| +
|
| +/**
|
| + * The flag specifying that [RESOLVED_UNIT3] has been been computed for this
|
| + * compilation unit (without requiring that the AST for it still be in cache).
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ResultDescriptor<bool> CREATED_RESOLVED_UNIT3 =
|
| + new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT3', false);
|
| +
|
| +/**
|
| + * The flag specifying that [RESOLVED_UNIT4] has been been computed for this
|
| + * compilation unit (without requiring that the AST for it still be in cache).
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ResultDescriptor<bool> CREATED_RESOLVED_UNIT4 =
|
| + new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT4', false);
|
| +
|
| +/**
|
| + * The flag specifying that [RESOLVED_UNIT5] has been been computed for this
|
| + * compilation unit (without requiring that the AST for it still be in cache).
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ResultDescriptor<bool> CREATED_RESOLVED_UNIT5 =
|
| + new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT5', false);
|
| +
|
| +/**
|
| + * The flag specifying that [RESOLVED_UNIT6] has been been computed for this
|
| + * compilation unit (without requiring that the AST for it still be in cache).
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ResultDescriptor<bool> CREATED_RESOLVED_UNIT6 =
|
| + new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT6', false);
|
| +
|
| +/**
|
| + * The flag specifying that [RESOLVED_UNIT7] has been been computed for this
|
| + * compilation unit (without requiring that the AST for it still be in cache).
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ResultDescriptor<bool> CREATED_RESOLVED_UNIT7 =
|
| + new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT7', false);
|
| +
|
| +/**
|
| + * The flag specifying that [RESOLVED_UNIT8] has been been computed for this
|
| + * compilation unit (without requiring that the AST for it still be in cache).
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ResultDescriptor<bool> CREATED_RESOLVED_UNIT8 =
|
| + new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT8', false);
|
| +
|
| +/**
|
| + * The flag specifying that [RESOLVED_UNIT9] has been been computed for this
|
| + * compilation unit (without requiring that the AST for it still be in cache).
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ResultDescriptor<bool> CREATED_RESOLVED_UNIT9 =
|
| + new ResultDescriptor<bool>('CREATED_RESOLVED_UNIT9', false);
|
| +
|
| +/**
|
| + * All [AnalysisError]s results for [Source]s.
|
| + */
|
| +final List<ListResultDescriptor<AnalysisError>> ERROR_SOURCE_RESULTS =
|
| + <ListResultDescriptor<AnalysisError>>[
|
| + BUILD_DIRECTIVES_ERRORS,
|
| + BUILD_LIBRARY_ERRORS,
|
| + PARSE_ERRORS,
|
| + SCAN_ERRORS,
|
| +];
|
| +
|
| +/**
|
| + * All [AnalysisError]s results in for [LibrarySpecificUnit]s.
|
| + */
|
| +final List<ListResultDescriptor<AnalysisError>> ERROR_UNIT_RESULTS =
|
| + <ListResultDescriptor<AnalysisError>>[
|
| + HINTS,
|
| + LIBRARY_UNIT_ERRORS,
|
| + LINTS,
|
| + RESOLVE_TYPE_BOUNDS_ERRORS,
|
| + RESOLVE_TYPE_NAMES_ERRORS,
|
| + RESOLVE_UNIT_ERRORS,
|
| + STRONG_MODE_ERRORS,
|
| + VARIABLE_REFERENCE_ERRORS,
|
| + VERIFY_ERRORS
|
| +];
|
| +
|
| /**
|
| * The sources representing the export closure of a library.
|
| * The [Source]s include only library sources, not their units.
|
| @@ -153,13 +377,10 @@ final ListResultDescriptor<AnalysisError> HINTS =
|
| 'HINT_ERRORS', AnalysisError.NO_ERRORS);
|
|
|
| /**
|
| - * The sources representing the combined import/export closure of a library.
|
| - * The [Source]s include only library sources, not their units.
|
| - *
|
| - * The result is only available for [Source]s representing a library.
|
| + * The ignore information for a [Source].
|
| */
|
| -final ListResultDescriptor<Source> IMPORT_EXPORT_SOURCE_CLOSURE =
|
| - new ListResultDescriptor<Source>('IMPORT_EXPORT_SOURCE_CLOSURE', null);
|
| +final ResultDescriptor<IgnoreInfo> IGNORE_INFO =
|
| + new ResultDescriptor<IgnoreInfo>('IGNORE_INFO', null);
|
|
|
| /**
|
| * A list of the [VariableElement]s whose type should be inferred that another
|
| @@ -168,8 +389,8 @@ final ListResultDescriptor<Source> IMPORT_EXPORT_SOURCE_CLOSURE =
|
| * The result is only available for [VariableElement]s, and only when strong
|
| * mode is enabled.
|
| */
|
| -final ListResultDescriptor<
|
| - VariableElement> INFERABLE_STATIC_VARIABLE_DEPENDENCIES =
|
| +final ListResultDescriptor<VariableElement>
|
| + INFERABLE_STATIC_VARIABLE_DEPENDENCIES =
|
| new ListResultDescriptor<VariableElement>(
|
| 'INFERABLE_STATIC_VARIABLE_DEPENDENCIES', null);
|
|
|
| @@ -186,7 +407,7 @@ final ListResultDescriptor<VariableElement> INFERABLE_STATIC_VARIABLES_IN_UNIT =
|
| 'INFERABLE_STATIC_VARIABLES_IN_UNIT', null);
|
|
|
| /**
|
| - * An inferrable static variable ([VariableElement]) whose type has been
|
| + * An inferable static variable ([VariableElement]) whose type has been
|
| * inferred.
|
| *
|
| * The result is only available for [VariableElement]s, and only when strong
|
| @@ -202,36 +423,35 @@ final ResultDescriptor<VariableElement> INFERRED_STATIC_VARIABLE =
|
| *
|
| * Only non-empty in strongMode.
|
| *
|
| - * The result is only available for [LibrarySpecificUnit]s.
|
| + * The result is only available for [Source]s representing a library.
|
| */
|
| final ListResultDescriptor<LibraryElement> LIBRARY_CYCLE =
|
| new ListResultDescriptor<LibraryElement>('LIBRARY_CYCLE', null);
|
|
|
| /**
|
| - * A list of the [CompilationUnitElement]s that comprise all of the parts and
|
| + * A list of the [LibrarySpecificUnit]s that comprise all of the parts and
|
| * libraries in the direct import/export dependencies of the library cycle
|
| * of the target, with the intra-component dependencies excluded.
|
| *
|
| * Only non-empty in strongMode.
|
| *
|
| - * The result is only available for [LibrarySpecificUnit]s.
|
| + * The result is only available for [Source]s representing a library.
|
| */
|
| -final ListResultDescriptor<CompilationUnitElement> LIBRARY_CYCLE_DEPENDENCIES =
|
| - new ListResultDescriptor<CompilationUnitElement>(
|
| +final ListResultDescriptor<LibrarySpecificUnit> LIBRARY_CYCLE_DEPENDENCIES =
|
| + new ListResultDescriptor<LibrarySpecificUnit>(
|
| 'LIBRARY_CYCLE_DEPENDENCIES', null);
|
|
|
| /**
|
| - * A list of the [CompilationUnitElement]s (including all parts) that make up
|
| + * A list of the [LibrarySpecificUnit]s (including all parts) that make up
|
| * the strongly connected component in the import/export graph in which the
|
| * target resides.
|
| *
|
| * Only non-empty in strongMode.
|
| *
|
| - * The result is only available for [LibrarySpecificUnit]s.
|
| + * The result is only available for [Source]s representing a library.
|
| */
|
| -final ListResultDescriptor<CompilationUnitElement> LIBRARY_CYCLE_UNITS =
|
| - new ListResultDescriptor<CompilationUnitElement>(
|
| - 'LIBRARY_CYCLE_UNITS', null);
|
| +final ListResultDescriptor<LibrarySpecificUnit> LIBRARY_CYCLE_UNITS =
|
| + new ListResultDescriptor<LibrarySpecificUnit>('LIBRARY_CYCLE_UNITS', null);
|
|
|
| /**
|
| * The partial [LibraryElement] associated with a library.
|
| @@ -248,7 +468,7 @@ final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT1 =
|
| /**
|
| * The partial [LibraryElement] associated with a library.
|
| *
|
| - * In addition to [LIBRARY_ELEMENT1] [LibraryElement.imports] and
|
| + * In addition to [LIBRARY_ELEMENT1] also [LibraryElement.imports] and
|
| * [LibraryElement.exports] are set.
|
| *
|
| * The result is only available for [Source]s representing a library.
|
| @@ -286,7 +506,7 @@ final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT4 =
|
| /**
|
| * The partial [LibraryElement] associated with a library.
|
| *
|
| - * [LIBRARY_ELEMENT4] plus resolved types for every element.
|
| + * [LIBRARY_ELEMENT5] plus resolved types type parameter bounds.
|
| *
|
| * The result is only available for [Source]s representing a library.
|
| */
|
| @@ -294,6 +514,67 @@ final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT5 =
|
| new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT5', null,
|
| cachingPolicy: ELEMENT_CACHING_POLICY);
|
|
|
| +/**
|
| + * The partial [LibraryElement] associated with a library.
|
| + *
|
| + * [LIBRARY_ELEMENT5] plus resolved types for every element.
|
| + *
|
| + * The result is only available for [Source]s representing a library.
|
| + */
|
| +final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT6 =
|
| + new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT6', null,
|
| + cachingPolicy: ELEMENT_CACHING_POLICY);
|
| +
|
| +/**
|
| + * The partial [LibraryElement] associated with a library.
|
| + *
|
| + * [LIBRARY_ELEMENT6] plus [RESOLVED_UNIT7] for all library units.
|
| + *
|
| + * The result is only available for [Source]s representing a library.
|
| + */
|
| +final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT7 =
|
| + new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT7', null,
|
| + cachingPolicy: ELEMENT_CACHING_POLICY);
|
| +
|
| +/**
|
| + * The partial [LibraryElement] associated with a library.
|
| + *
|
| + * [LIBRARY_ELEMENT7] for the library and its import/export closure.
|
| + *
|
| + * The result is only available for [Source]s representing a library.
|
| + */
|
| +final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT8 =
|
| + new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT8', null,
|
| + cachingPolicy: ELEMENT_CACHING_POLICY);
|
| +
|
| +/**
|
| + * The partial [LibraryElement] associated with a library.
|
| + *
|
| + * The same as a [LIBRARY_ELEMENT8].
|
| + *
|
| + * The result is only available for [Source]s representing a library.
|
| + */
|
| +final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT9 =
|
| + new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT9', null,
|
| + cachingPolicy: ELEMENT_CACHING_POLICY);
|
| +
|
| +/**
|
| + * List of all `LIBRARY_ELEMENT` results.
|
| + */
|
| +final List<ResultDescriptor<LibraryElement>> LIBRARY_ELEMENT_RESULTS =
|
| + <ResultDescriptor<LibraryElement>>[
|
| + LIBRARY_ELEMENT1,
|
| + LIBRARY_ELEMENT2,
|
| + LIBRARY_ELEMENT3,
|
| + LIBRARY_ELEMENT4,
|
| + LIBRARY_ELEMENT5,
|
| + LIBRARY_ELEMENT6,
|
| + LIBRARY_ELEMENT7,
|
| + LIBRARY_ELEMENT8,
|
| + LIBRARY_ELEMENT9,
|
| + LIBRARY_ELEMENT
|
| +];
|
| +
|
| /**
|
| * The flag specifying whether all analysis errors are computed in a specific
|
| * library.
|
| @@ -303,6 +584,18 @@ final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT5 =
|
| final ResultDescriptor<bool> LIBRARY_ERRORS_READY =
|
| new ResultDescriptor<bool>('LIBRARY_ERRORS_READY', false);
|
|
|
| +/**
|
| + * The [LibrarySpecificUnit]s that a library consists of.
|
| + *
|
| + * The list will include the defining unit and units for [INCLUDED_PARTS].
|
| + * So, it is never empty or `null`.
|
| + *
|
| + * The result is only available for [Source]s representing a library.
|
| + */
|
| +final ListResultDescriptor<LibrarySpecificUnit> LIBRARY_SPECIFIC_UNITS =
|
| + new ListResultDescriptor<LibrarySpecificUnit>(
|
| + 'LIBRARY_SPECIFIC_UNITS', LibrarySpecificUnit.EMPTY_LIST);
|
| +
|
| /**
|
| * The analysis errors associated with a compilation unit in a specific library.
|
| *
|
| @@ -334,6 +627,51 @@ final ListResultDescriptor<AnalysisError> PARSE_ERRORS =
|
| new ListResultDescriptor<AnalysisError>(
|
| 'PARSE_ERRORS', AnalysisError.NO_ERRORS);
|
|
|
| +/**
|
| + * The list of [PendingError]s for a compilation unit.
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ListResultDescriptor<PendingError> PENDING_ERRORS =
|
| + new ListResultDescriptor<PendingError>(
|
| + 'PENDING_ERRORS', const <PendingError>[]);
|
| +
|
| +/**
|
| + * The flag specifying that [LIBRARY_ELEMENT2] is ready for a library and its
|
| + * import/export closure.
|
| + *
|
| + * The result is only available for [Source]s representing a library.
|
| + */
|
| +final ResultDescriptor<bool> READY_LIBRARY_ELEMENT2 =
|
| + new ResultDescriptor<bool>('READY_LIBRARY_ELEMENT2', false);
|
| +
|
| +/**
|
| + * The flag specifying that [LIBRARY_ELEMENT6] is ready for a library and its
|
| + * import/export closure.
|
| + *
|
| + * The result is only available for [Source]s representing a library.
|
| + */
|
| +final ResultDescriptor<bool> READY_LIBRARY_ELEMENT6 =
|
| + new ResultDescriptor<bool>('READY_LIBRARY_ELEMENT6', false);
|
| +
|
| +/**
|
| + * The flag specifying that [LIBRARY_ELEMENT7] is ready for a library and its
|
| + * import/export closure.
|
| + *
|
| + * The result is only available for [Source]s representing a library.
|
| + */
|
| +final ResultDescriptor<bool> READY_LIBRARY_ELEMENT7 =
|
| + new ResultDescriptor<bool>('READY_LIBRARY_ELEMENT7', false);
|
| +
|
| +/**
|
| + * The flag specifying that [RESOLVED_UNIT] is ready for all of the units of a
|
| + * library.
|
| + *
|
| + * The result is only available for [Source]s representing a library.
|
| + */
|
| +final ResultDescriptor<bool> READY_RESOLVED_UNIT =
|
| + new ResultDescriptor<bool>('READY_RESOLVED_UNIT', false);
|
| +
|
| /**
|
| * The names (resolved and not) referenced by a unit.
|
| *
|
| @@ -342,6 +680,38 @@ final ListResultDescriptor<AnalysisError> PARSE_ERRORS =
|
| final ResultDescriptor<ReferencedNames> REFERENCED_NAMES =
|
| new ResultDescriptor<ReferencedNames>('REFERENCED_NAMES', null);
|
|
|
| +/**
|
| + * The sources of the Dart files that a library references.
|
| + *
|
| + * The list is the union of [IMPORTED_LIBRARIES], [EXPORTED_LIBRARIES] and
|
| + * [UNITS] of the defining unit and [INCLUDED_PARTS]. Never empty or `null`.
|
| + *
|
| + * The result is only available for [Source]s representing a library.
|
| + */
|
| +final ListResultDescriptor<Source> REFERENCED_SOURCES =
|
| + new ListResultDescriptor<Source>('REFERENCED_SOURCES', Source.EMPTY_LIST);
|
| +
|
| +/**
|
| + * The list of [ConstantEvaluationTarget]s on which error verification depends.
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ListResultDescriptor<ConstantEvaluationTarget> REQUIRED_CONSTANTS =
|
| + new ListResultDescriptor<ConstantEvaluationTarget>(
|
| + 'REQUIRED_CONSTANTS', const <ConstantEvaluationTarget>[]);
|
| +
|
| +/**
|
| + * The errors produced while resolving bounds of type parameters of classes,
|
| + * class and function aliases.
|
| + *
|
| + * The list will be empty if there were no errors, but will not be `null`.
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ListResultDescriptor<AnalysisError> RESOLVE_TYPE_BOUNDS_ERRORS =
|
| + new ListResultDescriptor<AnalysisError>(
|
| + 'RESOLVE_TYPE_BOUNDS_ERRORS', AnalysisError.NO_ERRORS);
|
| +
|
| /**
|
| * The errors produced while resolving type names.
|
| *
|
| @@ -375,6 +745,27 @@ final ListResultDescriptor<AnalysisError> RESOLVE_UNIT_ERRORS =
|
| */
|
| final ResultDescriptor<CompilationUnit> RESOLVED_UNIT1 =
|
| new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT1', null,
|
| + cachingPolicy: AST_REUSABLE_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_UNIT9].
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ResultDescriptor<CompilationUnit> RESOLVED_UNIT10 =
|
| + new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT10', null,
|
| + cachingPolicy: AST_CACHING_POLICY);
|
| +
|
| +/**
|
| + * The resolved [CompilationUnit] associated with a compilation unit, with
|
| + * constants not yet resolved.
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s.
|
| + */
|
| +final ResultDescriptor<CompilationUnit> RESOLVED_UNIT11 =
|
| + new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT11', null,
|
| cachingPolicy: AST_CACHING_POLICY);
|
|
|
| /**
|
| @@ -383,43 +774,41 @@ final ResultDescriptor<CompilationUnit> RESOLVED_UNIT1 =
|
| *
|
| * The result is only available for [LibrarySpecificUnit]s.
|
| */
|
| -final ResultDescriptor<CompilationUnit> RESOLVED_UNIT10 =
|
| - new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT10', null,
|
| +final ResultDescriptor<CompilationUnit> RESOLVED_UNIT12 =
|
| + new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT12', 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
|
| - * at all declaration sites have been bound to the element defined by the
|
| - * declaration, including the constants defined in an 'enum' declaration.
|
| + * In addition to what is true of a [RESOLVED_UNIT1], tasks that use this value
|
| + * as an input can assume that its directives have been resolved.
|
| *
|
| * The result is only available for [LibrarySpecificUnit]s.
|
| */
|
| final ResultDescriptor<CompilationUnit> RESOLVED_UNIT2 =
|
| new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT2', null,
|
| - cachingPolicy: AST_CACHING_POLICY);
|
| + cachingPolicy: AST_REUSABLE_CACHING_POLICY);
|
|
|
| /**
|
| * The partially resolved [CompilationUnit] associated with a compilation unit.
|
| *
|
| - * In addition to what is true of a [RESOLVED_UNIT2], tasks that use this value
|
| - * as an input can assume that the types associated with declarations have been
|
| - * resolved. This includes the types of superclasses, mixins, interfaces,
|
| - * fields, return types, parameters, and local variables.
|
| + * Tasks that use this value as an input can assume that the [SimpleIdentifier]s
|
| + * at all declaration sites have been bound to the element defined by the
|
| + * declaration, including the constants defined in an 'enum' declaration.
|
| *
|
| * The result is only available for [LibrarySpecificUnit]s.
|
| */
|
| final ResultDescriptor<CompilationUnit> RESOLVED_UNIT3 =
|
| new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT3', null,
|
| - cachingPolicy: AST_CACHING_POLICY);
|
| + cachingPolicy: AST_REUSABLE_CACHING_POLICY);
|
|
|
| /**
|
| * The partially resolved [CompilationUnit] associated with a compilation unit.
|
| *
|
| * In addition to what is true of a [RESOLVED_UNIT3], tasks that use this value
|
| - * as an input can assume that references to local variables and formal
|
| - * parameters have been resolved.
|
| + * as an input can assume that the types associated with type bounds have been
|
| + * resolved.
|
| *
|
| * The result is only available for [LibrarySpecificUnit]s.
|
| */
|
| @@ -431,9 +820,9 @@ final ResultDescriptor<CompilationUnit> RESOLVED_UNIT4 =
|
| * The partially resolved [CompilationUnit] associated with a compilation unit.
|
| *
|
| * In addition to what is true of a [RESOLVED_UNIT4], tasks that use this value
|
| - * as an input can assume that elements and types associated with expressions
|
| - * outside of method bodies (essentially initializers) have been initially
|
| - * resolved.
|
| + * as an input can assume that the types associated with declarations have been
|
| + * resolved. This includes the types of superclasses, mixins, interfaces,
|
| + * fields, return types, parameters, and local variables.
|
| *
|
| * The result is only available for [LibrarySpecificUnit]s.
|
| */
|
| @@ -445,7 +834,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 references to local variables and formal
|
| + * parameters have been resolved.
|
| *
|
| * The result is only available for [LibrarySpecificUnit]s.
|
| */
|
| @@ -457,8 +847,9 @@ 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 elements and types associated with expressions
|
| + * outside of method bodies (essentially initializers) have been initially
|
| + * resolved.
|
| *
|
| * The result is only available for [LibrarySpecificUnit]s.
|
| */
|
| @@ -467,9 +858,10 @@ 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 types of static variables have been inferred.
|
| *
|
| * The result is only available for [LibrarySpecificUnit]s.
|
| */
|
| @@ -478,8 +870,11 @@ final ResultDescriptor<CompilationUnit> RESOLVED_UNIT8 =
|
| cachingPolicy: AST_CACHING_POLICY);
|
|
|
| /**
|
| - * The resolved [CompilationUnit] associated with a compilation unit, with
|
| - * constants not yet resolved.
|
| + * The partially resolved [CompilationUnit] associated with a compilation unit.
|
| + *
|
| + * In addition to what is true of a [RESOLVED_UNIT8], 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.
|
| */
|
| @@ -487,6 +882,26 @@ final ResultDescriptor<CompilationUnit> RESOLVED_UNIT9 =
|
| new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT9', null,
|
| cachingPolicy: AST_CACHING_POLICY);
|
|
|
| +/**
|
| + * List of all `RESOLVED_UNITx` results.
|
| + */
|
| +final List<ResultDescriptor<CompilationUnit>> RESOLVED_UNIT_RESULTS =
|
| + <ResultDescriptor<CompilationUnit>>[
|
| + RESOLVED_UNIT1,
|
| + RESOLVED_UNIT2,
|
| + RESOLVED_UNIT3,
|
| + RESOLVED_UNIT4,
|
| + RESOLVED_UNIT5,
|
| + RESOLVED_UNIT6,
|
| + RESOLVED_UNIT7,
|
| + RESOLVED_UNIT8,
|
| + RESOLVED_UNIT9,
|
| + RESOLVED_UNIT10,
|
| + RESOLVED_UNIT11,
|
| + RESOLVED_UNIT12,
|
| + RESOLVED_UNIT
|
| +];
|
| +
|
| /**
|
| * The errors produced while scanning a compilation unit.
|
| *
|
| @@ -498,6 +913,28 @@ final ListResultDescriptor<AnalysisError> SCAN_ERRORS =
|
| new ListResultDescriptor<AnalysisError>(
|
| 'SCAN_ERRORS', AnalysisError.NO_ERRORS);
|
|
|
| +/**
|
| + * The errors produced while resolving a static [VariableElement] initializer.
|
| + *
|
| + * The result is only available for [VariableElement]s, and only when strong
|
| + * mode is enabled.
|
| + */
|
| +final ListResultDescriptor<AnalysisError> STATIC_VARIABLE_RESOLUTION_ERRORS =
|
| + new ListResultDescriptor<AnalysisError>(
|
| + 'STATIC_VARIABLE_RESOLUTION_ERRORS', AnalysisError.NO_ERRORS);
|
| +
|
| +/**
|
| + * A list of the [AnalysisError]s reported while resolving static
|
| + * [INFERABLE_STATIC_VARIABLES_IN_UNIT] defined in a unit.
|
| + *
|
| + * The result is only available for [LibrarySpecificUnit]s, and only when strong
|
| + * mode is enabled.
|
| + */
|
| +final ListResultDescriptor<AnalysisError>
|
| + STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT =
|
| + new ListResultDescriptor<AnalysisError>(
|
| + 'STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT', AnalysisError.NO_ERRORS);
|
| +
|
| /**
|
| * The additional strong mode errors produced while verifying a
|
| * compilation unit.
|
| @@ -523,14 +960,14 @@ final ResultDescriptor<TypeProvider> TYPE_PROVIDER =
|
| */
|
| final ResultDescriptor<UsedImportedElements> USED_IMPORTED_ELEMENTS =
|
| new ResultDescriptor<UsedImportedElements>('USED_IMPORTED_ELEMENTS', null,
|
| - cachingPolicy: ELEMENT_CACHING_POLICY);
|
| + cachingPolicy: USED_IMPORTED_ELEMENTS_POLICY);
|
|
|
| /**
|
| * The [UsedLocalElements] of a [LibrarySpecificUnit].
|
| */
|
| final ResultDescriptor<UsedLocalElements> USED_LOCAL_ELEMENTS =
|
| new ResultDescriptor<UsedLocalElements>('USED_LOCAL_ELEMENTS', null,
|
| - cachingPolicy: ELEMENT_CACHING_POLICY);
|
| + cachingPolicy: USED_LOCAL_ELEMENTS_POLICY);
|
|
|
| /**
|
| * The errors produced while resolving variable references in a compilation unit.
|
| @@ -554,11 +991,21 @@ final ListResultDescriptor<AnalysisError> VERIFY_ERRORS =
|
| new ListResultDescriptor<AnalysisError>(
|
| 'VERIFY_ERRORS', AnalysisError.NO_ERRORS);
|
|
|
| +/**
|
| + * Return a list of unique errors for the [Source] of the given [target].
|
| + */
|
| +List<AnalysisError> getTargetSourceErrors(
|
| + RecordingErrorListener listener, AnalysisTarget target) {
|
| + Source source = target.source;
|
| + List<AnalysisError> errors = listener.getErrorsForSource(source);
|
| + return getUniqueErrors(errors);
|
| +}
|
| +
|
| /**
|
| * Return a list of errors containing the errors from the given [errors] list
|
| * but with duplications removed.
|
| */
|
| -List<AnalysisError> removeDuplicateErrors(List<AnalysisError> errors) {
|
| +List<AnalysisError> getUniqueErrors(List<AnalysisError> errors) {
|
| if (errors.isEmpty) {
|
| return errors;
|
| }
|
| @@ -583,6 +1030,7 @@ class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask {
|
| buildInputs, <ResultDescriptor>[
|
| COMPILATION_UNIT_CONSTANTS,
|
| COMPILATION_UNIT_ELEMENT,
|
| + CREATED_RESOLVED_UNIT1,
|
| RESOLVED_UNIT1
|
| ]);
|
|
|
| @@ -606,13 +1054,24 @@ class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask {
|
| Source source = getRequiredSource();
|
| CompilationUnit unit = getRequiredInput(PARSED_UNIT_INPUT_NAME);
|
| //
|
| + // Try to get the existing CompilationUnitElement.
|
| + //
|
| + CompilationUnitElement element;
|
| + {
|
| + InternalAnalysisContext internalContext =
|
| + context as InternalAnalysisContext;
|
| + AnalysisCache analysisCache = internalContext.analysisCache;
|
| + CacheEntry cacheEntry = internalContext.getCacheEntry(target);
|
| + element = analysisCache.getValue(target, COMPILATION_UNIT_ELEMENT);
|
| + if (element == null &&
|
| + internalContext.aboutToComputeResult(
|
| + cacheEntry, COMPILATION_UNIT_ELEMENT)) {
|
| + element = analysisCache.getValue(target, COMPILATION_UNIT_ELEMENT);
|
| + }
|
| + }
|
| + //
|
| // Build or reuse CompilationUnitElement.
|
| //
|
| -// unit = AstCloner.clone(unit);
|
| - AnalysisCache analysisCache =
|
| - (context as InternalAnalysisContext).analysisCache;
|
| - CompilationUnitElement element =
|
| - analysisCache.getValue(target, COMPILATION_UNIT_ELEMENT);
|
| if (element == null) {
|
| CompilationUnitBuilder builder = new CompilationUnitBuilder();
|
| element = builder.buildCompilationUnit(
|
| @@ -623,17 +1082,17 @@ class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask {
|
| //
|
| // Prepare constants.
|
| //
|
| - ConstantFinder constantFinder =
|
| - new ConstantFinder(context, source, librarySpecificUnit.library);
|
| + ConstantFinder constantFinder = new ConstantFinder();
|
| unit.accept(constantFinder);
|
| - List<ConstantEvaluationTarget> constants = new List<
|
| - ConstantEvaluationTarget>.from(constantFinder.constantsToCompute);
|
| + List<ConstantEvaluationTarget> constants =
|
| + constantFinder.constantsToCompute.toList();
|
| //
|
| // Record outputs.
|
| //
|
| outputs[COMPILATION_UNIT_CONSTANTS] = constants;
|
| outputs[COMPILATION_UNIT_ELEMENT] = element;
|
| outputs[RESOLVED_UNIT1] = unit;
|
| + outputs[CREATED_RESOLVED_UNIT1] = true;
|
| }
|
|
|
| /**
|
| @@ -672,6 +1131,12 @@ class BuildDirectiveElementsTask extends SourceBasedAnalysisTask {
|
| */
|
| static const String UNIT_INPUT_NAME = 'UNIT_INPUT_NAME';
|
|
|
| + /**
|
| + * The input with a map from referenced sources to their modification times.
|
| + */
|
| + static const String SOURCES_MODIFICATION_TIME_INPUT_NAME =
|
| + 'SOURCES_MODIFICATION_TIME_INPUT_NAME';
|
| +
|
| /**
|
| * The input with a list of [LIBRARY_ELEMENT3]s of imported libraries.
|
| */
|
| @@ -714,12 +1179,13 @@ class BuildDirectiveElementsTask extends SourceBasedAnalysisTask {
|
|
|
| @override
|
| void internalPerform() {
|
| - List<AnalysisError> errors = <AnalysisError>[];
|
| //
|
| // Prepare inputs.
|
| //
|
| LibraryElementImpl libraryElement = getRequiredInput(LIBRARY_INPUT);
|
| CompilationUnit libraryUnit = getRequiredInput(UNIT_INPUT_NAME);
|
| + Map<Source, int> sourceModificationTimeMap =
|
| + getRequiredInput(SOURCES_MODIFICATION_TIME_INPUT_NAME);
|
| Map<Source, LibraryElement> importLibraryMap =
|
| getRequiredInput(IMPORTS_LIBRARY_ELEMENT_INPUT_NAME);
|
| Map<Source, LibraryElement> exportLibraryMap =
|
| @@ -728,113 +1194,44 @@ class BuildDirectiveElementsTask extends SourceBasedAnalysisTask {
|
| getRequiredInput(IMPORTS_SOURCE_KIND_INPUT_NAME);
|
| Map<Source, SourceKind> exportSourceKindMap =
|
| getRequiredInput(EXPORTS_SOURCE_KIND_INPUT_NAME);
|
| - Source librarySource = libraryElement.source;
|
| //
|
| - // Resolve directives.
|
| + // Try to get the existing LibraryElement.
|
| //
|
| - HashMap<String, PrefixElementImpl> nameToPrefixMap =
|
| - new HashMap<String, PrefixElementImpl>();
|
| - List<ImportElement> imports = <ImportElement>[];
|
| - List<ExportElement> exports = <ExportElement>[];
|
| - bool explicitlyImportsCore = false;
|
| - for (Directive directive in libraryUnit.directives) {
|
| - if (directive is ImportDirective) {
|
| - ImportDirective importDirective = directive;
|
| - String uriContent = importDirective.uriContent;
|
| - if (DartUriResolver.isDartExtUri(uriContent)) {
|
| - libraryElement.hasExtUri = true;
|
| - }
|
| - Source importedSource = importDirective.source;
|
| - if (importedSource != null && context.exists(importedSource)) {
|
| - // The imported source will be null if the URI in the import
|
| - // directive was invalid.
|
| - LibraryElement importedLibrary = importLibraryMap[importedSource];
|
| - if (importedLibrary != null) {
|
| - if (importedLibrary.isDartCore) {
|
| - explicitlyImportsCore = true;
|
| - }
|
| - ImportElementImpl importElement =
|
| - new ImportElementImpl(directive.offset);
|
| - StringLiteral uriLiteral = importDirective.uri;
|
| - if (uriLiteral != null) {
|
| - importElement.uriOffset = uriLiteral.offset;
|
| - importElement.uriEnd = uriLiteral.end;
|
| - }
|
| - importElement.uri = uriContent;
|
| - importElement.deferred = importDirective.deferredKeyword != null;
|
| - importElement.combinators = _buildCombinators(importDirective);
|
| - importElement.importedLibrary = importedLibrary;
|
| - SimpleIdentifier prefixNode = directive.prefix;
|
| - if (prefixNode != null) {
|
| - importElement.prefixOffset = prefixNode.offset;
|
| - String prefixName = prefixNode.name;
|
| - PrefixElementImpl prefix = nameToPrefixMap[prefixName];
|
| - if (prefix == null) {
|
| - prefix = new PrefixElementImpl.forNode(prefixNode);
|
| - nameToPrefixMap[prefixName] = prefix;
|
| - }
|
| - importElement.prefix = prefix;
|
| - prefixNode.staticElement = prefix;
|
| - }
|
| - directive.element = importElement;
|
| - imports.add(importElement);
|
| - if (importSourceKindMap[importedSource] != SourceKind.LIBRARY) {
|
| - ErrorCode errorCode = (importElement.isDeferred
|
| - ? StaticWarningCode.IMPORT_OF_NON_LIBRARY
|
| - : CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY);
|
| - errors.add(new AnalysisError(importedSource, uriLiteral.offset,
|
| - uriLiteral.length, errorCode, [uriLiteral.toSource()]));
|
| - }
|
| - }
|
| - }
|
| - } else if (directive is ExportDirective) {
|
| - ExportDirective exportDirective = directive;
|
| - Source exportedSource = exportDirective.source;
|
| - if (exportedSource != null && context.exists(exportedSource)) {
|
| - // The exported source will be null if the URI in the export
|
| - // directive was invalid.
|
| - LibraryElement exportedLibrary = exportLibraryMap[exportedSource];
|
| - if (exportedLibrary != null) {
|
| - ExportElementImpl exportElement =
|
| - new ExportElementImpl(directive.offset);
|
| - StringLiteral uriLiteral = exportDirective.uri;
|
| - if (uriLiteral != null) {
|
| - exportElement.uriOffset = uriLiteral.offset;
|
| - exportElement.uriEnd = uriLiteral.end;
|
| - }
|
| - exportElement.uri = exportDirective.uriContent;
|
| - exportElement.combinators = _buildCombinators(exportDirective);
|
| - exportElement.exportedLibrary = exportedLibrary;
|
| - directive.element = exportElement;
|
| - exports.add(exportElement);
|
| - if (exportSourceKindMap[exportedSource] != SourceKind.LIBRARY) {
|
| - errors.add(new AnalysisError(
|
| - exportedSource,
|
| - uriLiteral.offset,
|
| - uriLiteral.length,
|
| - CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
|
| - [uriLiteral.toSource()]));
|
| - }
|
| - }
|
| - }
|
| + LibraryElement element;
|
| + {
|
| + InternalAnalysisContext internalContext =
|
| + context as InternalAnalysisContext;
|
| + AnalysisCache analysisCache = internalContext.analysisCache;
|
| + CacheEntry cacheEntry = internalContext.getCacheEntry(target);
|
| + element = analysisCache.getValue(target, LIBRARY_ELEMENT2);
|
| + if (element == null &&
|
| + internalContext.aboutToComputeResult(cacheEntry, LIBRARY_ELEMENT2)) {
|
| + element = analysisCache.getValue(target, LIBRARY_ELEMENT2);
|
| }
|
| }
|
| //
|
| - // Ensure "dart:core" import.
|
| + // Build or reuse the directive elements.
|
| //
|
| - Source coreLibrarySource = context.sourceFactory.forUri(DartSdk.DART_CORE);
|
| - if (!explicitlyImportsCore && coreLibrarySource != librarySource) {
|
| - ImportElementImpl importElement = new ImportElementImpl(-1);
|
| - importElement.importedLibrary = importLibraryMap[coreLibrarySource];
|
| - importElement.synthetic = true;
|
| - imports.add(importElement);
|
| + List<AnalysisError> errors;
|
| + if (element == null) {
|
| + DirectiveElementBuilder builder = new DirectiveElementBuilder(
|
| + context,
|
| + libraryElement,
|
| + sourceModificationTimeMap,
|
| + importLibraryMap,
|
| + importSourceKindMap,
|
| + exportLibraryMap,
|
| + exportSourceKindMap);
|
| + libraryUnit.accept(builder);
|
| + // See the commentary in the computation of the LIBRARY_CYCLE result
|
| + // for details on library cycle invalidation.
|
| + libraryElement.invalidateLibraryCycles();
|
| + errors = builder.errors;
|
| + } else {
|
| + DirectiveResolver resolver = new DirectiveResolver();
|
| + libraryUnit.accept(resolver);
|
| }
|
| //
|
| - // Populate the library element.
|
| - //
|
| - libraryElement.imports = imports;
|
| - libraryElement.exports = exports;
|
| - //
|
| // Record outputs.
|
| //
|
| outputs[LIBRARY_ELEMENT2] = libraryElement;
|
| @@ -852,6 +1249,8 @@ class BuildDirectiveElementsTask extends SourceBasedAnalysisTask {
|
| LIBRARY_INPUT: LIBRARY_ELEMENT1.of(source),
|
| UNIT_INPUT_NAME:
|
| RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, source)),
|
| + SOURCES_MODIFICATION_TIME_INPUT_NAME:
|
| + REFERENCED_SOURCES.of(source).toMapOf(MODIFICATION_TIME),
|
| IMPORTS_LIBRARY_ELEMENT_INPUT_NAME:
|
| IMPORTED_LIBRARIES.of(source).toMapOf(LIBRARY_ELEMENT1),
|
| EXPORTS_LIBRARY_ELEMENT_INPUT_NAME:
|
| @@ -871,36 +1270,6 @@ class BuildDirectiveElementsTask extends SourceBasedAnalysisTask {
|
| AnalysisContext context, AnalysisTarget target) {
|
| return new BuildDirectiveElementsTask(context, target);
|
| }
|
| -
|
| - /**
|
| - * Build the element model representing the combinators declared by
|
| - * the given [directive].
|
| - */
|
| - static List<NamespaceCombinator> _buildCombinators(
|
| - NamespaceDirective directive) {
|
| - List<NamespaceCombinator> combinators = <NamespaceCombinator>[];
|
| - for (Combinator combinator in directive.combinators) {
|
| - if (combinator is ShowCombinator) {
|
| - ShowElementCombinatorImpl show = new ShowElementCombinatorImpl();
|
| - show.offset = combinator.offset;
|
| - show.end = combinator.end;
|
| - show.shownNames = _getIdentifiers(combinator.shownNames);
|
| - combinators.add(show);
|
| - } else if (combinator is HideCombinator) {
|
| - HideElementCombinatorImpl hide = new HideElementCombinatorImpl();
|
| - hide.hiddenNames = _getIdentifiers(combinator.hiddenNames);
|
| - combinators.add(hide);
|
| - }
|
| - }
|
| - return combinators;
|
| - }
|
| -
|
| - /**
|
| - * Return the lexical identifiers associated with the given [identifiers].
|
| - */
|
| - static List<String> _getIdentifiers(NodeList<SimpleIdentifier> identifiers) {
|
| - return identifiers.map((identifier) => identifier.name).toList();
|
| - }
|
| }
|
|
|
| /**
|
| @@ -925,7 +1294,7 @@ class BuildEnumMemberElementsTask extends SourceBasedAnalysisTask {
|
| 'BuildEnumMemberElementsTask',
|
| createTask,
|
| buildInputs,
|
| - <ResultDescriptor>[RESOLVED_UNIT2]);
|
| + <ResultDescriptor>[CREATED_RESOLVED_UNIT3, RESOLVED_UNIT3]);
|
|
|
| BuildEnumMemberElementsTask(
|
| InternalAnalysisContext context, AnalysisTarget target)
|
| @@ -942,11 +1311,30 @@ class BuildEnumMemberElementsTask extends SourceBasedAnalysisTask {
|
| TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
|
| CompilationUnit unit = getRequiredInput(UNIT_INPUT);
|
| //
|
| + // Build the enum members if they have not already been created.
|
| + //
|
| + EnumDeclaration findFirstEnum() {
|
| + NodeList<CompilationUnitMember> members = unit.declarations;
|
| + int length = members.length;
|
| + for (int i = 0; i < length; i++) {
|
| + CompilationUnitMember member = members[i];
|
| + if (member is EnumDeclaration) {
|
| + return member;
|
| + }
|
| + }
|
| + return null;
|
| + }
|
| +
|
| + EnumDeclaration firstEnum = findFirstEnum();
|
| + if (firstEnum != null && firstEnum.element.accessors.isEmpty) {
|
| + EnumMemberBuilder builder = new EnumMemberBuilder(typeProvider);
|
| + unit.accept(builder);
|
| + }
|
| + //
|
| // Record outputs.
|
| //
|
| - EnumMemberBuilder builder = new EnumMemberBuilder(typeProvider);
|
| - unit.accept(builder);
|
| - outputs[RESOLVED_UNIT2] = unit;
|
| + outputs[CREATED_RESOLVED_UNIT3] = true;
|
| + outputs[RESOLVED_UNIT3] = unit;
|
| }
|
|
|
| /**
|
| @@ -958,7 +1346,7 @@ class BuildEnumMemberElementsTask extends SourceBasedAnalysisTask {
|
| LibrarySpecificUnit unit = target;
|
| return <String, TaskInput>{
|
| TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
|
| - UNIT_INPUT: RESOLVED_UNIT1.of(unit)
|
| + UNIT_INPUT: RESOLVED_UNIT2.of(unit)
|
| };
|
| }
|
|
|
| @@ -1003,8 +1391,9 @@ class BuildExportNamespaceTask extends SourceBasedAnalysisTask {
|
| //
|
| // Compute export namespace.
|
| //
|
| - ExportNamespaceBuilder builder = new ExportNamespaceBuilder();
|
| - Namespace namespace = builder.build(library);
|
| + library.exportNamespace = null;
|
| + NamespaceBuilder builder = new NamespaceBuilder();
|
| + Namespace namespace = builder.createExportNamespaceForLibrary(library);
|
| library.exportNamespace = namespace;
|
| //
|
| // Update entry point.
|
| @@ -1060,6 +1449,11 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask {
|
| */
|
| static const String PARTS_UNIT_INPUT = 'PARTS_UNIT_INPUT';
|
|
|
| + /**
|
| + * The name of the input whose value is the modification time of the source.
|
| + */
|
| + static const String MODIFICATION_TIME_INPUT = 'MODIFICATION_TIME_INPUT';
|
| +
|
| /**
|
| * The task descriptor describing this kind of task.
|
| */
|
| @@ -1096,6 +1490,7 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask {
|
| CompilationUnit definingCompilationUnit =
|
| getRequiredInput(DEFINING_UNIT_INPUT);
|
| List<CompilationUnit> partUnits = getRequiredInput(PARTS_UNIT_INPUT);
|
| + int modificationTime = getRequiredInput(MODIFICATION_TIME_INPUT);
|
| //
|
| // Process inputs.
|
| //
|
| @@ -1103,7 +1498,9 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask {
|
| definingCompilationUnit.element;
|
| Map<Source, CompilationUnit> partUnitMap =
|
| new HashMap<Source, CompilationUnit>();
|
| - for (CompilationUnit partUnit in partUnits) {
|
| + int partLength = partUnits.length;
|
| + for (int i = 0; i < partLength; i++) {
|
| + CompilationUnit partUnit = partUnits[i];
|
| Source partSource = partUnit.element.source;
|
| partUnitMap[partSource] = partUnit;
|
| }
|
| @@ -1118,23 +1515,23 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask {
|
| List<Directive> directivesToResolve = <Directive>[];
|
| List<CompilationUnitElementImpl> sourcedCompilationUnits =
|
| <CompilationUnitElementImpl>[];
|
| - for (Directive directive in definingCompilationUnit.directives) {
|
| + NodeList<Directive> directives = definingCompilationUnit.directives;
|
| + int directiveLength = directives.length;
|
| + for (int i = 0; i < directiveLength; i++) {
|
| + Directive directive = directives[i];
|
| if (directive is LibraryDirective) {
|
| - if (libraryNameNode == null) {
|
| - libraryNameNode = directive.name;
|
| - directivesToResolve.add(directive);
|
| - }
|
| + libraryNameNode = directive.name;
|
| + directivesToResolve.add(directive);
|
| } else if (directive is PartDirective) {
|
| - PartDirective partDirective = directive;
|
| - StringLiteral partUri = partDirective.uri;
|
| - Source partSource = partDirective.source;
|
| + StringLiteral partUri = directive.uri;
|
| + Source partSource = directive.uriSource;
|
| hasPartDirective = true;
|
| CompilationUnit partUnit = partUnitMap[partSource];
|
| if (partUnit != null) {
|
| CompilationUnitElementImpl partElement = partUnit.element;
|
| partElement.uriOffset = partUri.offset;
|
| partElement.uriEnd = partUri.end;
|
| - partElement.uri = partDirective.uriContent;
|
| + partElement.uri = directive.uriContent;
|
| //
|
| // Validate that the part contains a part-of directive with the same
|
| // name as the library.
|
| @@ -1193,16 +1590,52 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask {
|
| InternalAnalysisContext internalContext = context;
|
| owningContext = internalContext.getContextFor(librarySource);
|
| }
|
| - LibraryElementImpl libraryElement =
|
| - new LibraryElementImpl.forNode(owningContext, libraryNameNode);
|
| - libraryElement.definingCompilationUnit = definingCompilationUnitElement;
|
| - libraryElement.entryPoint = entryPoint;
|
| - libraryElement.parts = sourcedCompilationUnits;
|
| - for (Directive directive in directivesToResolve) {
|
| - directive.element = libraryElement;
|
| + //
|
| + // Try to get the existing LibraryElement.
|
| + //
|
| + LibraryElementImpl libraryElement;
|
| + {
|
| + InternalAnalysisContext internalContext =
|
| + context as InternalAnalysisContext;
|
| + AnalysisCache analysisCache = internalContext.analysisCache;
|
| + CacheEntry cacheEntry = internalContext.getCacheEntry(target);
|
| + libraryElement = analysisCache.getValue(target, LIBRARY_ELEMENT1)
|
| + as LibraryElementImpl;
|
| + if (libraryElement == null &&
|
| + internalContext.aboutToComputeResult(cacheEntry, LIBRARY_ELEMENT1)) {
|
| + libraryElement = analysisCache.getValue(target, LIBRARY_ELEMENT1)
|
| + as LibraryElementImpl;
|
| + }
|
| }
|
| - if (sourcedCompilationUnits.isNotEmpty) {
|
| - _patchTopLevelAccessors(libraryElement);
|
| + //
|
| + // Create a new LibraryElement.
|
| + //
|
| + if (libraryElement == null) {
|
| + libraryElement =
|
| + new LibraryElementImpl.forNode(owningContext, libraryNameNode);
|
| + libraryElement.synthetic = modificationTime < 0;
|
| + libraryElement.definingCompilationUnit = definingCompilationUnitElement;
|
| + libraryElement.entryPoint = entryPoint;
|
| + libraryElement.parts = sourcedCompilationUnits;
|
| + libraryElement.hasExtUri = _hasExtUri(definingCompilationUnit);
|
| + BuildLibraryElementUtils.patchTopLevelAccessors(libraryElement);
|
| + // set the library documentation to the docs associated with the first
|
| + // directive in the compilation unit.
|
| + if (definingCompilationUnit.directives.isNotEmpty) {
|
| + setElementDocumentationComment(
|
| + libraryElement, definingCompilationUnit.directives.first);
|
| + }
|
| + }
|
| + //
|
| + // Resolve the relevant directives to the library element.
|
| + //
|
| + // TODO(brianwilkerson) This updates the state of the AST structures but
|
| + // does not associate a new result with it.
|
| + //
|
| + int length = directivesToResolve.length;
|
| + for (int i = 0; i < length; i++) {
|
| + Directive directive = directivesToResolve[i];
|
| + directive.element = libraryElement;
|
| }
|
| //
|
| // Record outputs.
|
| @@ -1212,31 +1645,15 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask {
|
| outputs[IS_LAUNCHABLE] = entryPoint != null;
|
| }
|
|
|
| - /**
|
| - * Add all of the non-synthetic [getters] and [setters] defined in the given
|
| - * [unit] that have no corresponding accessor to one of the given collections.
|
| - */
|
| - void _collectAccessors(Map<String, PropertyAccessorElement> getters,
|
| - List<PropertyAccessorElement> setters, CompilationUnitElement unit) {
|
| - for (PropertyAccessorElement accessor in unit.accessors) {
|
| - if (accessor.isGetter) {
|
| - if (!accessor.isSynthetic && accessor.correspondingSetter == null) {
|
| - getters[accessor.displayName] = accessor;
|
| - }
|
| - } else {
|
| - if (!accessor.isSynthetic && accessor.correspondingGetter == null) {
|
| - setters.add(accessor);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| /**
|
| * Return the top-level [FunctionElement] entry point, or `null` if the given
|
| * [element] does not define an entry point.
|
| */
|
| FunctionElement _findEntryPoint(CompilationUnitElementImpl element) {
|
| - for (FunctionElement function in element.functions) {
|
| + List<FunctionElement> functions = element.functions;
|
| + int length = functions.length;
|
| + for (int i = 0; i < length; i++) {
|
| + FunctionElement function = functions[i];
|
| if (function.isEntryPoint) {
|
| return function;
|
| }
|
| @@ -1250,7 +1667,10 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask {
|
| */
|
| String _getPartLibraryName(Source partSource, CompilationUnit partUnit,
|
| List<Directive> directivesToResolve) {
|
| - for (Directive directive in partUnit.directives) {
|
| + NodeList<Directive> directives = partUnit.directives;
|
| + int length = directives.length;
|
| + for (int i = 0; i < length; i++) {
|
| + Directive directive = directives[i];
|
| if (directive is PartOfDirective) {
|
| directivesToResolve.add(directive);
|
| LibraryIdentifier libraryName = directive.libraryName;
|
| @@ -1263,30 +1683,21 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask {
|
| }
|
|
|
| /**
|
| - * Look through all of the compilation units defined for the given [library],
|
| - * looking for getters and setters that are defined in different compilation
|
| - * units but that have the same names. If any are found, make sure that they
|
| - * have the same variable element.
|
| + * Return `true` if the given compilation [unit] contains at least one
|
| + * import directive with a `dart-ext:` URI.
|
| */
|
| - void _patchTopLevelAccessors(LibraryElementImpl library) {
|
| - HashMap<String, PropertyAccessorElement> getters =
|
| - new HashMap<String, PropertyAccessorElement>();
|
| - List<PropertyAccessorElement> setters = <PropertyAccessorElement>[];
|
| - _collectAccessors(getters, setters, library.definingCompilationUnit);
|
| - for (CompilationUnitElement unit in library.parts) {
|
| - _collectAccessors(getters, setters, unit);
|
| - }
|
| - for (PropertyAccessorElement setter in setters) {
|
| - PropertyAccessorElement getter = getters[setter.displayName];
|
| - if (getter != null) {
|
| - TopLevelVariableElementImpl variable = getter.variable;
|
| - TopLevelVariableElementImpl setterVariable = setter.variable;
|
| - CompilationUnitElementImpl setterUnit = setterVariable.enclosingElement;
|
| - setterUnit.replaceTopLevelVariable(setterVariable, variable);
|
| - variable.setter = setter;
|
| - (setter as PropertyAccessorElementImpl).variable = variable;
|
| + bool _hasExtUri(CompilationUnit unit) {
|
| + NodeList<Directive> directives = unit.directives;
|
| + int length = directives.length;
|
| + for (int i = 0; i < length; i++) {
|
| + Directive directive = directives[i];
|
| + if (directive is ImportDirective) {
|
| + if (DartUriResolver.isDartExtUri(directive.uriContent)) {
|
| + return true;
|
| + }
|
| }
|
| }
|
| + return false;
|
| }
|
|
|
| /**
|
| @@ -1301,7 +1712,8 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask {
|
| RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, source)),
|
| PARTS_UNIT_INPUT: INCLUDED_PARTS.of(source).toList((Source unit) {
|
| return RESOLVED_UNIT1.of(new LibrarySpecificUnit(source, unit));
|
| - })
|
| + }),
|
| + MODIFICATION_TIME_INPUT: MODIFICATION_TIME.of(source)
|
| };
|
| }
|
|
|
| @@ -1343,7 +1755,8 @@ class BuildPublicNamespaceTask extends SourceBasedAnalysisTask {
|
| @override
|
| void internalPerform() {
|
| LibraryElementImpl library = getRequiredInput(LIBRARY_INPUT);
|
| - library.publicNamespace = new PublicNamespaceBuilder().build(library);
|
| + NamespaceBuilder builder = new NamespaceBuilder();
|
| + library.publicNamespace = builder.createPublicNamespaceForLibrary(library);
|
| outputs[LIBRARY_ELEMENT3] = library;
|
| }
|
|
|
| @@ -1423,66 +1836,6 @@ class BuildSourceExportClosureTask extends SourceBasedAnalysisTask {
|
| }
|
| }
|
|
|
| -/**
|
| - * A task that builds [IMPORT_EXPORT_SOURCE_CLOSURE] of a library, and also
|
| - * sets [IS_CLIENT].
|
| - */
|
| -class BuildSourceImportExportClosureTask extends SourceBasedAnalysisTask {
|
| - /**
|
| - * The name of the import/export closure.
|
| - */
|
| - static const String IMPORT_EXPORT_INPUT = 'IMPORT_EXPORT_INPUT';
|
| -
|
| - /**
|
| - * The task descriptor describing this kind of task.
|
| - */
|
| - static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| - 'BuildSourceImportExportClosureTask',
|
| - createTask,
|
| - buildInputs,
|
| - <ResultDescriptor>[IMPORT_EXPORT_SOURCE_CLOSURE, IS_CLIENT]);
|
| -
|
| - BuildSourceImportExportClosureTask(
|
| - InternalAnalysisContext context, AnalysisTarget target)
|
| - : super(context, target);
|
| -
|
| - @override
|
| - TaskDescriptor get descriptor => DESCRIPTOR;
|
| -
|
| - @override
|
| - void internalPerform() {
|
| - List<Source> importExportClosure = getRequiredInput(IMPORT_EXPORT_INPUT);
|
| - Source htmlSource = context.sourceFactory.forUri(DartSdk.DART_HTML);
|
| - //
|
| - // Record outputs.
|
| - //
|
| - outputs[IMPORT_EXPORT_SOURCE_CLOSURE] = importExportClosure;
|
| - outputs[IS_CLIENT] = importExportClosure.contains(htmlSource);
|
| - }
|
| -
|
| - /**
|
| - * 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 library [libSource].
|
| - */
|
| - static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| - Source source = target;
|
| - return <String, TaskInput>{
|
| - IMPORT_EXPORT_INPUT:
|
| - new _ImportExportSourceClosureTaskInput(source, LIBRARY_ELEMENT2)
|
| - };
|
| - }
|
| -
|
| - /**
|
| - * Create a [BuildSourceImportExportClosureTask] based on the given [target]
|
| - * in the given [context].
|
| - */
|
| - static BuildSourceImportExportClosureTask createTask(
|
| - AnalysisContext context, AnalysisTarget target) {
|
| - return new BuildSourceImportExportClosureTask(context, target);
|
| - }
|
| -}
|
| -
|
| /**
|
| * A task that builds [TYPE_PROVIDER] for a context.
|
| */
|
| @@ -1516,7 +1869,7 @@ class BuildTypeProviderTask extends SourceBasedAnalysisTask {
|
| @override
|
| void internalPerform() {
|
| LibraryElement coreLibrary = getRequiredInput(CORE_INPUT);
|
| - LibraryElement asyncLibrary = getRequiredInput(ASYNC_INPUT);
|
| + LibraryElement asyncLibrary = getOptionalInput(ASYNC_INPUT);
|
| Namespace coreNamespace = coreLibrary.publicNamespace;
|
| Namespace asyncNamespace = asyncLibrary.publicNamespace;
|
| //
|
| @@ -1533,6 +1886,9 @@ class BuildTypeProviderTask extends SourceBasedAnalysisTask {
|
| SourceFactory sourceFactory = contextTarget.context.sourceFactory;
|
| Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE);
|
| Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC);
|
| + if (asyncSource == null) {
|
| + return <String, TaskInput>{CORE_INPUT: LIBRARY_ELEMENT3.of(coreSource)};
|
| + }
|
| return <String, TaskInput>{
|
| CORE_INPUT: LIBRARY_ELEMENT3.of(coreSource),
|
| ASYNC_INPUT: LIBRARY_ELEMENT3.of(asyncSource)
|
| @@ -1552,11 +1908,6 @@ class BuildTypeProviderTask extends SourceBasedAnalysisTask {
|
| * A task that computes [CONSTANT_DEPENDENCIES] for a constant.
|
| */
|
| class ComputeConstantDependenciesTask extends ConstantEvaluationAnalysisTask {
|
| - /**
|
| - * The name of the [RESOLVED_UNIT9] input.
|
| - */
|
| - static const String UNIT_INPUT = 'UNIT_INPUT';
|
| -
|
| /**
|
| * The name of the [TYPE_PROVIDER] input.
|
| */
|
| @@ -1580,10 +1931,6 @@ class ComputeConstantDependenciesTask extends ConstantEvaluationAnalysisTask {
|
| //
|
| // Prepare inputs.
|
| //
|
| - // Note: UNIT_INPUT is not needed. It is merely a bookkeeping dependency
|
| - // to ensure that resolution has occurred before we attempt to determine
|
| - // constant dependencies.
|
| - //
|
| ConstantEvaluationTarget constant = target;
|
| TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
|
| //
|
| @@ -1605,23 +1952,10 @@ class ComputeConstantDependenciesTask extends ConstantEvaluationAnalysisTask {
|
| * given [target].
|
| */
|
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| - if (target is Element) {
|
| - CompilationUnitElementImpl unit = target
|
| - .getAncestor((Element element) => element is CompilationUnitElement);
|
| - return <String, TaskInput>{
|
| - UNIT_INPUT: RESOLVED_UNIT9
|
| - .of(new LibrarySpecificUnit(unit.librarySource, target.source)),
|
| - TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
|
| - };
|
| - } else if (target is ConstantEvaluationTarget_Annotation) {
|
| - return <String, TaskInput>{
|
| - UNIT_INPUT: RESOLVED_UNIT9
|
| - .of(new LibrarySpecificUnit(target.librarySource, target.source)),
|
| - TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
|
| - };
|
| - }
|
| - throw new AnalysisException(
|
| - 'Cannot build inputs for a ${target.runtimeType}');
|
| + return <String, TaskInput>{
|
| + 'constantExpressionResolved': CONSTANT_EXPRESSION_RESOLVED.of(target),
|
| + TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
|
| + };
|
| }
|
|
|
| /**
|
| @@ -1689,7 +2023,9 @@ class ComputeConstantValueTask extends ConstantEvaluationAnalysisTask {
|
| } else {
|
| List<ConstantEvaluationTarget> constantsInCycle =
|
| <ConstantEvaluationTarget>[];
|
| - for (WorkItem workItem in dependencyCycle) {
|
| + int length = dependencyCycle.length;
|
| + for (int i = 0; i < length; i++) {
|
| + WorkItem workItem = dependencyCycle[i];
|
| if (workItem.descriptor == DESCRIPTOR) {
|
| constantsInCycle.add(workItem.target);
|
| }
|
| @@ -1732,9 +2068,9 @@ class ComputeConstantValueTask extends ConstantEvaluationAnalysisTask {
|
| * static variable whose type should be inferred.
|
| */
|
| class ComputeInferableStaticVariableDependenciesTask
|
| - extends ConstantEvaluationAnalysisTask {
|
| + extends InferStaticVariableTask {
|
| /**
|
| - * The name of the [RESOLVED_UNIT5] input.
|
| + * The name of the [RESOLVED_UNIT7] input.
|
| */
|
| static const String UNIT_INPUT = 'UNIT_INPUT';
|
|
|
| @@ -1756,19 +2092,11 @@ class ComputeInferableStaticVariableDependenciesTask
|
| //
|
| // 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");
|
| - }
|
| + VariableDeclaration declaration = getDeclaration(unit);
|
| VariableGatherer gatherer = new VariableGatherer(_isInferableStatic);
|
| declaration.initializer.accept(gatherer);
|
| //
|
| @@ -1781,7 +2109,8 @@ class ComputeInferableStaticVariableDependenciesTask
|
| * Return `true` if the given [variable] is a static variable whose type
|
| * should be inferred.
|
| */
|
| - bool _isInferableStatic(VariableElement variable) => variable.isStatic &&
|
| + bool _isInferableStatic(VariableElement variable) =>
|
| + variable.isStatic &&
|
| variable.hasImplicitType &&
|
| variable.initializer != null;
|
|
|
| @@ -1795,7 +2124,7 @@ class ComputeInferableStaticVariableDependenciesTask
|
| CompilationUnitElementImpl unit = target
|
| .getAncestor((Element element) => element is CompilationUnitElement);
|
| return <String, TaskInput>{
|
| - UNIT_INPUT: RESOLVED_UNIT5
|
| + UNIT_INPUT: RESOLVED_UNIT7
|
| .of(new LibrarySpecificUnit(unit.librarySource, unit.source))
|
| };
|
| }
|
| @@ -1842,27 +2171,59 @@ class ComputeLibraryCycleTask extends SourceBasedAnalysisTask {
|
|
|
| @override
|
| void internalPerform() {
|
| + // The computation of library cycles is necessarily non-local, since we
|
| + // in general have to look at all of the reachable libraries
|
| + // in order to find the strongly connected components. Repeating this
|
| + // computation for every node would be quadratic. The libraryCycle getter
|
| + // will avoid this by computing the library cycles for every reachable
|
| + // library and recording it in the element model. This means that this
|
| + // task implicitly produces the output for many other targets. This
|
| + // can't be expressed in the task model right now: instead, we just
|
| + // run tasks for those other targets, and they pick up the recorded
|
| + // version off of the element model. Unfortunately, this means that
|
| + // the task model will not handle the invalidation of the recorded
|
| + // results for us. Instead, we must explicitly invalidate the recorded
|
| + // library cycle information when we add or subtract edges from the
|
| + // import/export graph. Any update that changes the
|
| + // import/export graph will induce a recomputation of the LIBRARY_ELEMENT2
|
| + // result for the changed node. This recomputation is responsible for
|
| + // conservatively invalidating the library cycle information recorded
|
| + // in the element model. The LIBRARY_CYCLE results that have been cached
|
| + // by the task model are conservatively invalidated by the
|
| + // IMPORT_EXPORT_SOURCE_CLOSURE dependency below. If anything reachable
|
| + // from a node is changed, its LIBRARY_CYCLE results will be re-computed
|
| + // here (possibly re-using the result from the element model if invalidation
|
| + // did not cause it to be erased). In summary, task model dependencies
|
| + // on the import/export source closure ensure that this method will be
|
| + // re-run if anything reachable from this target has been invalidated,
|
| + // and the invalidation code (invalidateLibraryCycles) will ensure that
|
| + // element model results will be re-used here only if they are still valid.
|
| if (context.analysisOptions.strongMode) {
|
| - LibraryElementImpl library = getRequiredInput(LIBRARY_ELEMENT_INPUT);
|
| + LibraryElement library = getRequiredInput(LIBRARY_ELEMENT_INPUT);
|
| List<LibraryElement> component = library.libraryCycle;
|
| - Set<LibraryElement> filter = new Set<LibraryElement>.from(component);
|
| + Set<LibraryElement> filter = component.toSet();
|
| Set<CompilationUnitElement> deps = new Set<CompilationUnitElement>();
|
| - void addLibrary(l) {
|
| + void addLibrary(LibraryElement l) {
|
| if (!filter.contains(l)) {
|
| deps.addAll(l.units);
|
| }
|
| }
|
| - for (LibraryElement l in component) {
|
| - l.importedLibraries.forEach(addLibrary);
|
| - l.exportedLibraries.forEach(addLibrary);
|
| - }
|
|
|
| + int length = component.length;
|
| + for (int i = 0; i < length; i++) {
|
| + LibraryElement library = component[i];
|
| + library.importedLibraries.forEach(addLibrary);
|
| + library.exportedLibraries.forEach(addLibrary);
|
| + }
|
| //
|
| // Record outputs.
|
| //
|
| + LibrarySpecificUnit unitToLSU(CompilationUnitElement unit) =>
|
| + new LibrarySpecificUnit(unit.librarySource, unit.source);
|
| outputs[LIBRARY_CYCLE] = component;
|
| - outputs[LIBRARY_CYCLE_UNITS] = component.expand((l) => l.units).toList();
|
| - outputs[LIBRARY_CYCLE_DEPENDENCIES] = deps.toList();
|
| + outputs[LIBRARY_CYCLE_UNITS] =
|
| + component.expand((l) => l.units).map(unitToLSU).toList();
|
| + outputs[LIBRARY_CYCLE_DEPENDENCIES] = deps.map(unitToLSU).toList();
|
| } else {
|
| outputs[LIBRARY_CYCLE] = [];
|
| outputs[LIBRARY_CYCLE_UNITS] = [];
|
| @@ -1876,12 +2237,10 @@ class ComputeLibraryCycleTask extends SourceBasedAnalysisTask {
|
| * given [target].
|
| */
|
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| - LibrarySpecificUnit unit = target;
|
| + Source librarySource = target;
|
| return <String, TaskInput>{
|
| - 'resolveReachableLibraries': IMPORT_EXPORT_SOURCE_CLOSURE
|
| - .of(unit.library)
|
| - .toListOf(LIBRARY_ELEMENT2),
|
| - LIBRARY_ELEMENT_INPUT: LIBRARY_ELEMENT2.of(unit.library)
|
| + LIBRARY_ELEMENT_INPUT: LIBRARY_ELEMENT2.of(librarySource),
|
| + 'resolveReachableLibraries': READY_LIBRARY_ELEMENT2.of(librarySource),
|
| };
|
| }
|
|
|
| @@ -1895,6 +2254,73 @@ class ComputeLibraryCycleTask extends SourceBasedAnalysisTask {
|
| }
|
| }
|
|
|
| +/**
|
| + * A task that builds [REQUIRED_CONSTANTS] for a unit.
|
| + */
|
| +class ComputeRequiredConstantsTask extends SourceBasedAnalysisTask {
|
| + /**
|
| + * The name of the [RESOLVED_UNIT] input.
|
| + */
|
| + static const String UNIT_INPUT = 'UNIT_INPUT';
|
| +
|
| + /**
|
| + * The task descriptor describing this kind of task.
|
| + */
|
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| + 'ComputeRequiredConstantsTask',
|
| + createTask,
|
| + buildInputs,
|
| + <ResultDescriptor>[PENDING_ERRORS, REQUIRED_CONSTANTS]);
|
| +
|
| + ComputeRequiredConstantsTask(
|
| + InternalAnalysisContext context, AnalysisTarget target)
|
| + : super(context, target);
|
| +
|
| + @override
|
| + TaskDescriptor get descriptor => DESCRIPTOR;
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + Source source = getRequiredSource();
|
| + //
|
| + // Prepare inputs.
|
| + //
|
| + CompilationUnit unit = getRequiredInput(UNIT_INPUT);
|
| + //
|
| + // Use the ErrorVerifier to compute errors.
|
| + //
|
| + RequiredConstantsComputer computer = new RequiredConstantsComputer(source);
|
| + unit.accept(computer);
|
| + List<PendingError> pendingErrors = computer.pendingErrors;
|
| + List<ConstantEvaluationTarget> requiredConstants =
|
| + computer.requiredConstants;
|
| + //
|
| + // Record outputs.
|
| + //
|
| + outputs[PENDING_ERRORS] = pendingErrors;
|
| + outputs[REQUIRED_CONSTANTS] = requiredConstants;
|
| + }
|
| +
|
| + /**
|
| + * 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>{UNIT_INPUT: RESOLVED_UNIT.of(unit)};
|
| + }
|
| +
|
| + /**
|
| + * Create a [ComputeRequiredConstantsTask] based on the given [target] in
|
| + * the given [context].
|
| + */
|
| + static ComputeRequiredConstantsTask createTask(
|
| + AnalysisContext context, AnalysisTarget target) {
|
| + return new ComputeRequiredConstantsTask(context, target);
|
| + }
|
| +}
|
| +
|
| /**
|
| * A base class for analysis tasks whose target is expected to be a
|
| * [ConstantEvaluationTarget].
|
| @@ -1980,96 +2406,332 @@ class ContainingLibrariesTask extends SourceBasedAnalysisTask {
|
| * The description for a change in a Dart source.
|
| */
|
| class DartDelta extends Delta {
|
| - bool hasDirectiveChange = false;
|
| -
|
| - final Set<String> addedNames = new Set<String>();
|
| final Set<String> changedNames = new Set<String>();
|
| - final Set<String> removedNames = new Set<String>();
|
| + final Map<Source, Set<String>> changedPrivateNames = <Source, Set<String>>{};
|
|
|
| - final Set<Source> invalidatedSources = new Set<Source>();
|
| -
|
| - DartDelta(Source source) : super(source) {
|
| - invalidatedSources.add(source);
|
| - }
|
| + final Map<String, ClassElementDelta> changedClasses =
|
| + <String, ClassElementDelta>{};
|
|
|
| - void elementAdded(Element element) {
|
| - addedNames.add(element.name);
|
| - }
|
| + /**
|
| + * The cache of libraries in which all results are invalid.
|
| + */
|
| + final Set<Source> librariesWithAllInvalidResults = new Set<Source>();
|
|
|
| - void elementChanged(Element element) {
|
| - changedNames.add(element.name);
|
| - }
|
| + /**
|
| + * The cache of libraries in which all results are valid.
|
| + */
|
| + final Set<Source> librariesWithAllValidResults = new Set<Source>();
|
|
|
| - void elementRemoved(Element element) {
|
| - removedNames.add(element.name);
|
| - }
|
| + /**
|
| + * The cache of libraries with all, but [HINTS] and [VERIFY_ERRORS] results
|
| + * are valid.
|
| + */
|
| + final Set<Source> libraryWithInvalidErrors = new Set<Source>();
|
|
|
| - bool isNameAffected(String name) {
|
| - return addedNames.contains(name) ||
|
| - changedNames.contains(name) ||
|
| - removedNames.contains(name);
|
| - }
|
| + /**
|
| + * This set is cleared in every [gatherEnd], and [gatherChanges] uses it
|
| + * to find changes in every source only once per visit process.
|
| + */
|
| + final Set<Source> currentVisitUnits = new Set<Source>();
|
|
|
| - bool nameChanged(String name) {
|
| - return changedNames.add(name);
|
| - }
|
| + DartDelta(Source source) : super(source);
|
|
|
| @override
|
| - DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
|
| - ResultDescriptor descriptor) {
|
| - if (hasDirectiveChange) {
|
| - return DeltaResult.INVALIDATE;
|
| - }
|
| - // Prepare target source.
|
| - Source targetSource = null;
|
| - if (target is Source) {
|
| - targetSource = target;
|
| - }
|
| - if (target is LibrarySpecificUnit) {
|
| - targetSource = target.library;
|
| + bool get shouldGatherChanges => true;
|
| +
|
| + /**
|
| + * Add names that are changed in the given [references].
|
| + * Return `true` if any change was added.
|
| + */
|
| + bool addChangedElements(ReferencedNames references, Source refLibrary) {
|
| + int numberOfChanges = 0;
|
| + int lastNumberOfChange = -1;
|
| + while (numberOfChanges != lastNumberOfChange) {
|
| + lastNumberOfChange = numberOfChanges;
|
| + // Classes that extend changed classes are also changed.
|
| + // If there is a delta for a superclass, use it for the subclass.
|
| + // Otherwise mark the subclass as "general name change".
|
| + references.superToSubs.forEach((String superName, Set<String> subNames) {
|
| + ClassElementDelta superDelta = changedClasses[superName];
|
| + for (String subName in subNames) {
|
| + if (superDelta != null) {
|
| + ClassElementDelta subDelta = changedClasses.putIfAbsent(subName,
|
| + () => new ClassElementDelta(null, refLibrary, subName));
|
| + _log(() => '$subName in $refLibrary has delta because of its '
|
| + 'superclass $superName has delta');
|
| + if (subDelta.superDeltas.add(superDelta)) {
|
| + numberOfChanges++;
|
| + }
|
| + } else if (isChanged(refLibrary, superName)) {
|
| + if (nameChanged(refLibrary, subName)) {
|
| + _log(() => '$subName in $refLibrary is changed because its '
|
| + 'superclass $superName is changed');
|
| + numberOfChanges++;
|
| + }
|
| + }
|
| + }
|
| + });
|
| + // If a user element uses a changed top-level element, then the user is
|
| + // also changed. Note that if a changed class with delta is used, this
|
| + // does not make the user changed - classes with delta keep their
|
| + // original elements, so resolution of their names does not change.
|
| + references.userToDependsOn.forEach((user, dependencies) {
|
| + for (String dependency in dependencies) {
|
| + if (isChangedOrClassMember(refLibrary, dependency)) {
|
| + if (nameChanged(refLibrary, user)) {
|
| + _log(() => '$user in $refLibrary is changed because '
|
| + 'of $dependency in $dependencies');
|
| + numberOfChanges++;
|
| + }
|
| + }
|
| + }
|
| + });
|
| }
|
| - if (target is Element) {
|
| - targetSource = target.source;
|
| + return numberOfChanges != 0;
|
| + }
|
| +
|
| + void classChanged(ClassElementDelta classDelta) {
|
| + changedClasses[classDelta.name] = classDelta;
|
| + }
|
| +
|
| + void elementChanged(Element element) {
|
| + Source librarySource = element.library.source;
|
| + nameChanged(librarySource, element.name);
|
| + }
|
| +
|
| + @override
|
| + bool gatherChanges(InternalAnalysisContext context, AnalysisTarget target,
|
| + ResultDescriptor descriptor, Object value) {
|
| + // Prepare target source.
|
| + Source targetUnit = target.source;
|
| + Source targetLibrary = target.librarySource;
|
| + if (target is Source) {
|
| + if (context.getKindOf(target) == SourceKind.LIBRARY) {
|
| + targetLibrary = target;
|
| + }
|
| }
|
| - // Keep results that are updated incrementally.
|
| - // If we want to analyze only some references to the source being changed,
|
| - // we need to keep the same instances of CompilationUnitElement and
|
| - // LibraryElement.
|
| - if (targetSource == source) {
|
| - if (ParseDartTask.DESCRIPTOR.results.contains(descriptor)) {
|
| - return DeltaResult.KEEP_CONTINUE;
|
| + // We don't know what to do with the given target.
|
| + if (targetUnit == null || targetUnit != targetLibrary) {
|
| + return false;
|
| + }
|
| + // Attempt to find new changed names for the unit only once.
|
| + if (!currentVisitUnits.add(targetUnit)) {
|
| + return false;
|
| + }
|
| + // Add changes.
|
| + ReferencedNames referencedNames =
|
| + context.getResult(targetUnit, REFERENCED_NAMES);
|
| + if (referencedNames == null) {
|
| + return false;
|
| + }
|
| + return addChangedElements(referencedNames, targetLibrary);
|
| + }
|
| +
|
| + @override
|
| + void gatherEnd() {
|
| + currentVisitUnits.clear();
|
| + }
|
| +
|
| + bool hasAffectedHintsVerifyErrors(
|
| + ReferencedNames references, Source refLibrary) {
|
| + for (String superName in references.superToSubs.keys) {
|
| + if (isChangedOrClass(refLibrary, superName)) {
|
| + _log(() => '$refLibrary hints/verify errors are affected because '
|
| + '${references.superToSubs[superName]} subclasses $superName');
|
| + return true;
|
| }
|
| - if (BuildCompilationUnitElementTask.DESCRIPTOR.results
|
| - .contains(descriptor)) {
|
| - return DeltaResult.KEEP_CONTINUE;
|
| + }
|
| + for (String name in references.names) {
|
| + ClassElementDelta classDelta = changedClasses[name];
|
| + if (classDelta != null && classDelta.hasAnnotationChanges) {
|
| + _log(() => '$refLibrary hints/verify errors are affected because '
|
| + '$name has a class delta with annotation changes');
|
| + return true;
|
| }
|
| - if (BuildLibraryElementTask.DESCRIPTOR.results.contains(descriptor)) {
|
| - return DeltaResult.KEEP_CONTINUE;
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + bool hasAffectedReferences(ReferencedNames references, Source refLibrary) {
|
| + // Resolution must be performed when a referenced element changes.
|
| + for (String name in references.names) {
|
| + if (isChangedOrClassMember(refLibrary, name)) {
|
| + _log(() => '$refLibrary is affected by $name');
|
| + return true;
|
| + }
|
| + }
|
| + // Resolution must be performed when the unnamed constructor of
|
| + // an instantiated class is added/changed/removed.
|
| + // TODO(scheglov) Use only instantiations with default constructor.
|
| + for (String name in references.instantiatedNames) {
|
| + for (ClassElementDelta classDelta in changedClasses.values) {
|
| + if (classDelta.name == name && classDelta.hasUnnamedConstructorChange) {
|
| + _log(() =>
|
| + '$refLibrary is affected by the default constructor of $name');
|
| + return true;
|
| + }
|
| }
|
| - return DeltaResult.INVALIDATE;
|
| }
|
| - // Use the target library dependency information to decide whether
|
| - // the delta affects the library.
|
| - if (targetSource != null) {
|
| - List<Source> librarySources =
|
| - context.getLibrariesContaining(targetSource);
|
| - for (Source librarySource in librarySources) {
|
| - AnalysisCache cache = context.analysisCache;
|
| - ReferencedNames referencedNames =
|
| - cache.getValue(librarySource, REFERENCED_NAMES);
|
| - if (referencedNames == null) {
|
| - return DeltaResult.INVALIDATE;
|
| + for (String name in references.extendedUsedUnnamedConstructorNames) {
|
| + for (ClassElementDelta classDelta in changedClasses.values) {
|
| + if (classDelta.name == name && classDelta.hasUnnamedConstructorChange) {
|
| + _log(() =>
|
| + '$refLibrary is affected by the default constructor of $name');
|
| + return true;
|
| }
|
| - referencedNames.addChangedElements(this);
|
| - if (referencedNames.isAffectedBy(this)) {
|
| - return DeltaResult.INVALIDATE;
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + /**
|
| + * Return `true` if the given [name], used in a unit of the [librarySource],
|
| + * is affected by a changed top-level element, excluding classes.
|
| + */
|
| + bool isChanged(Source librarySource, String name) {
|
| + if (_isPrivateName(name)) {
|
| + if (changedPrivateNames[librarySource]?.contains(name) ?? false) {
|
| + return true;
|
| + }
|
| + }
|
| + return changedNames.contains(name);
|
| + }
|
| +
|
| + /**
|
| + * Return `true` if the given [name], used in a unit of the [librarySource],
|
| + * is affected by a changed top-level element or a class.
|
| + */
|
| + bool isChangedOrClass(Source librarySource, String name) {
|
| + if (isChanged(librarySource, name)) {
|
| + return true;
|
| + }
|
| + return changedClasses[name] != null;
|
| + }
|
| +
|
| + /**
|
| + * Return `true` if the given [name], used in a unit of the [librarySource],
|
| + * is affected by a changed top-level element or a class member.
|
| + */
|
| + bool isChangedOrClassMember(Source librarySource, String name) {
|
| + if (isChanged(librarySource, name)) {
|
| + return true;
|
| + }
|
| + // TODO(scheglov) Optimize this.
|
| + for (ClassElementDelta classDelta in changedClasses.values) {
|
| + if (classDelta.hasChanges(librarySource, name)) {
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + /**
|
| + * Register the fact that the given [name], defined in the [librarySource]
|
| + * is changed. Return `true` if the [name] is a new name, not yet registered.
|
| + */
|
| + bool nameChanged(Source librarySource, String name) {
|
| + if (_isPrivateName(name)) {
|
| + return changedPrivateNames
|
| + .putIfAbsent(librarySource, () => new Set<String>())
|
| + .add(name);
|
| + } else {
|
| + return changedNames.add(name);
|
| + }
|
| + }
|
| +
|
| + @override
|
| + DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
|
| + ResultDescriptor descriptor, Object value) {
|
| + // Always invalidate compounding results.
|
| + if (descriptor == LIBRARY_ELEMENT4 ||
|
| + descriptor == READY_LIBRARY_ELEMENT6 ||
|
| + descriptor == READY_LIBRARY_ELEMENT7) {
|
| + return DeltaResult.INVALIDATE_KEEP_DEPENDENCIES;
|
| + }
|
| + // Prepare target source.
|
| + Source targetUnit = target.source;
|
| + Source targetLibrary = target.librarySource;
|
| + if (target is Source) {
|
| + if (context.getKindOf(target) == SourceKind.LIBRARY) {
|
| + targetLibrary = target;
|
| + }
|
| + }
|
| + // We don't know what to do with the given target, invalidate it.
|
| + if (targetUnit == null || targetUnit != targetLibrary) {
|
| + return DeltaResult.INVALIDATE;
|
| + }
|
| + // Keep results that don't change: any library.
|
| + if (_isTaskResult(ScanDartTask.DESCRIPTOR, descriptor) ||
|
| + _isTaskResult(ParseDartTask.DESCRIPTOR, descriptor) ||
|
| + _isTaskResult(BuildCompilationUnitElementTask.DESCRIPTOR, descriptor) ||
|
| + _isTaskResult(BuildLibraryElementTask.DESCRIPTOR, descriptor) ||
|
| + _isTaskResult(BuildDirectiveElementsTask.DESCRIPTOR, descriptor) ||
|
| + _isTaskResult(ResolveDirectiveElementsTask.DESCRIPTOR, descriptor) ||
|
| + _isTaskResult(BuildEnumMemberElementsTask.DESCRIPTOR, descriptor) ||
|
| + _isTaskResult(BuildSourceExportClosureTask.DESCRIPTOR, descriptor) ||
|
| + _isTaskResult(ReadyLibraryElement2Task.DESCRIPTOR, descriptor) ||
|
| + _isTaskResult(ComputeLibraryCycleTask.DESCRIPTOR, descriptor)) {
|
| + return DeltaResult.KEEP_CONTINUE;
|
| + }
|
| + // Keep results that don't change: changed library.
|
| + if (targetUnit == source) {
|
| + return DeltaResult.INVALIDATE;
|
| + }
|
| + // Keep results that don't change: dependent library.
|
| + if (targetUnit != source) {
|
| + if (_isTaskResult(BuildPublicNamespaceTask.DESCRIPTOR, descriptor)) {
|
| + return DeltaResult.KEEP_CONTINUE;
|
| + }
|
| + }
|
| + // Handle in-library results only for now.
|
| + if (targetLibrary != null) {
|
| + // Use cached library results.
|
| + if (librariesWithAllInvalidResults.contains(targetLibrary)) {
|
| + return DeltaResult.INVALIDATE;
|
| + }
|
| + if (librariesWithAllValidResults.contains(targetLibrary)) {
|
| + return DeltaResult.KEEP_CONTINUE;
|
| + }
|
| + // The library is almost, but not completely valid.
|
| + // Some error results are invalid.
|
| + if (libraryWithInvalidErrors.contains(targetLibrary)) {
|
| + if (descriptor == HINTS || descriptor == VERIFY_ERRORS) {
|
| + return DeltaResult.INVALIDATE_NO_DELTA;
|
| }
|
| + return DeltaResult.KEEP_CONTINUE;
|
| + }
|
| + // Compute the library result.
|
| + ReferencedNames referencedNames =
|
| + context.getResult(targetUnit, REFERENCED_NAMES);
|
| + if (referencedNames == null) {
|
| + return DeltaResult.INVALIDATE_NO_DELTA;
|
| + }
|
| + if (hasAffectedReferences(referencedNames, targetLibrary)) {
|
| + librariesWithAllInvalidResults.add(targetLibrary);
|
| + return DeltaResult.INVALIDATE;
|
| + }
|
| + if (hasAffectedHintsVerifyErrors(referencedNames, targetLibrary)) {
|
| + libraryWithInvalidErrors.add(targetLibrary);
|
| + return DeltaResult.KEEP_CONTINUE;
|
| }
|
| - return DeltaResult.STOP;
|
| + librariesWithAllValidResults.add(targetLibrary);
|
| + return DeltaResult.KEEP_CONTINUE;
|
| }
|
| // We don't know what to do with the given target, invalidate it.
|
| return DeltaResult.INVALIDATE;
|
| }
|
| +
|
| + void _log(String getMessage()) {
|
| +// String message = getMessage();
|
| +// print(message);
|
| + }
|
| +
|
| + static bool _isPrivateName(String name) => name.startsWith('_');
|
| +
|
| + static bool _isTaskResult(
|
| + TaskDescriptor taskDescriptor, ResultDescriptor result) {
|
| + return taskDescriptor.results.contains(result);
|
| + }
|
| }
|
|
|
| /**
|
| @@ -2083,6 +2745,16 @@ class DartErrorsTask extends SourceBasedAnalysisTask {
|
| static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('DartErrorsTask',
|
| createTask, buildInputs, <ResultDescriptor>[DART_ERRORS]);
|
|
|
| + /**
|
| + * The name of the [IGNORE_INFO_INPUT] input.
|
| + */
|
| + static const String IGNORE_INFO_INPUT = 'IGNORE_INFO_INPUT';
|
| +
|
| + /**
|
| + * The name of the [LINE_INFO_INPUT] input.
|
| + */
|
| + static const String LINE_INFO_INPUT = 'LINE_INFO_INPUT';
|
| +
|
| DartErrorsTask(InternalAnalysisContext context, AnalysisTarget target)
|
| : super(context, target);
|
|
|
| @@ -2096,21 +2768,49 @@ class DartErrorsTask extends SourceBasedAnalysisTask {
|
| // Prepare inputs.
|
| //
|
| EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin;
|
| - for (ResultDescriptor result in enginePlugin.dartErrorsForSource) {
|
| + List<ResultDescriptor> errorsForSource = enginePlugin.dartErrorsForSource;
|
| + int sourceLength = errorsForSource.length;
|
| + for (int i = 0; i < sourceLength; i++) {
|
| + ResultDescriptor result = errorsForSource[i];
|
| String inputName = result.name + '_input';
|
| errorLists.add(getRequiredInput(inputName));
|
| }
|
| - for (ResultDescriptor result in enginePlugin.dartErrorsForUnit) {
|
| + List<ResultDescriptor> errorsForUnit = enginePlugin.dartErrorsForUnit;
|
| + int unitLength = errorsForUnit.length;
|
| + for (int i = 0; i < unitLength; i++) {
|
| + ResultDescriptor result = errorsForUnit[i];
|
| String inputName = result.name + '_input';
|
| Map<Source, List<AnalysisError>> errorMap = getRequiredInput(inputName);
|
| for (List<AnalysisError> errors in errorMap.values) {
|
| errorLists.add(errors);
|
| }
|
| }
|
| +
|
| + //
|
| + // Filter ignored errors.
|
| + //
|
| + List<AnalysisError> errors =
|
| + _filterIgnores(AnalysisError.mergeLists(errorLists));
|
| +
|
| //
|
| // Record outputs.
|
| //
|
| - outputs[DART_ERRORS] = AnalysisError.mergeLists(errorLists);
|
| + outputs[DART_ERRORS] = errors;
|
| + }
|
| +
|
| + List<AnalysisError> _filterIgnores(List<AnalysisError> errors) {
|
| + if (errors.isEmpty) {
|
| + return errors;
|
| + }
|
| +
|
| + IgnoreInfo ignoreInfo = getRequiredInput(IGNORE_INFO_INPUT);
|
| + if (!ignoreInfo.hasIgnores) {
|
| + return errors;
|
| + }
|
| +
|
| + LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT);
|
| +
|
| + return filterIgnored(errors, ignoreInfo, lineInfo);
|
| }
|
|
|
| /**
|
| @@ -2121,14 +2821,22 @@ class DartErrorsTask extends SourceBasedAnalysisTask {
|
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| Source source = target;
|
| Map<String, TaskInput> inputs = <String, TaskInput>{};
|
| + inputs[LINE_INFO_INPUT] = LINE_INFO.of(source);
|
| + inputs[IGNORE_INFO_INPUT] = IGNORE_INFO.of(source);
|
| EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin;
|
| // for Source
|
| - for (ResultDescriptor result in enginePlugin.dartErrorsForSource) {
|
| + List<ResultDescriptor> errorsForSource = enginePlugin.dartErrorsForSource;
|
| + int sourceLength = errorsForSource.length;
|
| + for (int i = 0; i < sourceLength; i++) {
|
| + ResultDescriptor result = errorsForSource[i];
|
| String inputName = result.name + '_input';
|
| inputs[inputName] = result.of(source);
|
| }
|
| // for LibrarySpecificUnit
|
| - for (ResultDescriptor result in enginePlugin.dartErrorsForUnit) {
|
| + List<ResultDescriptor> errorsForUnit = enginePlugin.dartErrorsForUnit;
|
| + int unitLength = errorsForUnit.length;
|
| + for (int i = 0; i < unitLength; i++) {
|
| + ResultDescriptor result = errorsForUnit[i];
|
| String inputName = result.name + '_input';
|
| inputs[inputName] =
|
| CONTAINING_LIBRARIES.of(source).toMap((Source library) {
|
| @@ -2147,14 +2855,35 @@ class DartErrorsTask extends SourceBasedAnalysisTask {
|
| AnalysisContext context, AnalysisTarget target) {
|
| return new DartErrorsTask(context, target);
|
| }
|
| +
|
| + /**
|
| + * Return a new list with items from [errors] which are not filtered out by
|
| + * the [ignoreInfo].
|
| + */
|
| + static List<AnalysisError> filterIgnored(
|
| + List<AnalysisError> errors, IgnoreInfo ignoreInfo, LineInfo lineInfo) {
|
| + if (errors.isEmpty || !ignoreInfo.hasIgnores) {
|
| + return errors;
|
| + }
|
| +
|
| + bool isIgnored(AnalysisError error) {
|
| + int errorLine = lineInfo.getLocation(error.offset).lineNumber;
|
| + String errorCode = error.errorCode.name.toLowerCase();
|
| + // Ignores can be on the line or just preceding the error.
|
| + return ignoreInfo.ignoredAt(errorCode, errorLine) ||
|
| + ignoreInfo.ignoredAt(errorCode, errorLine - 1);
|
| + }
|
| +
|
| + return errors.where((AnalysisError e) => !isIgnored(e)).toList();
|
| + }
|
| }
|
|
|
| /**
|
| - * A task that builds [RESOLVED_UNIT10] for a unit.
|
| + * A task that builds [RESOLVED_UNIT12] for a unit.
|
| */
|
| class EvaluateUnitConstantsTask extends SourceBasedAnalysisTask {
|
| /**
|
| - * The name of the [RESOLVED_UNIT9] input.
|
| + * The name of the [RESOLVED_UNIT11] input.
|
| */
|
| static const String UNIT_INPUT = 'UNIT_INPUT';
|
|
|
| @@ -2170,7 +2899,7 @@ class EvaluateUnitConstantsTask extends SourceBasedAnalysisTask {
|
| 'EvaluateUnitConstantsTask',
|
| createTask,
|
| buildInputs,
|
| - <ResultDescriptor>[RESOLVED_UNIT10]);
|
| + <ResultDescriptor>[CREATED_RESOLVED_UNIT12, RESOLVED_UNIT12]);
|
|
|
| EvaluateUnitConstantsTask(AnalysisContext context, LibrarySpecificUnit target)
|
| : super(context, target);
|
| @@ -2183,7 +2912,8 @@ 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_UNIT12] = unit;
|
| + outputs[CREATED_RESOLVED_UNIT12] = true;
|
| }
|
|
|
| /**
|
| @@ -2194,10 +2924,12 @@ class EvaluateUnitConstantsTask extends SourceBasedAnalysisTask {
|
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| LibrarySpecificUnit unit = target;
|
| return <String, TaskInput>{
|
| - 'libraryElement': LIBRARY_ELEMENT.of(unit.library),
|
| - UNIT_INPUT: RESOLVED_UNIT9.of(unit),
|
| + 'libraryElement': LIBRARY_ELEMENT9.of(unit.library),
|
| + UNIT_INPUT: RESOLVED_UNIT11.of(unit),
|
| CONSTANT_VALUES:
|
| - COMPILATION_UNIT_CONSTANTS.of(unit).toListOf(CONSTANT_VALUE)
|
| + COMPILATION_UNIT_CONSTANTS.of(unit).toListOf(CONSTANT_VALUE),
|
| + 'constantExpressionsDependencies':
|
| + CONSTANT_EXPRESSIONS_DEPENDENCIES.of(unit).toListOf(CONSTANT_VALUE)
|
| };
|
| }
|
|
|
| @@ -2211,115 +2943,12 @@ class EvaluateUnitConstantsTask extends SourceBasedAnalysisTask {
|
| }
|
| }
|
|
|
| -/**
|
| - * The helper for building the export [Namespace] of a [LibraryElement].
|
| - */
|
| -class ExportNamespaceBuilder {
|
| - /**
|
| - * Build the export [Namespace] of the given [LibraryElement].
|
| - */
|
| - Namespace build(LibraryElement library) {
|
| - return new Namespace(
|
| - _createExportMapping(library, new HashSet<LibraryElement>()));
|
| - }
|
| -
|
| - /**
|
| - * Create a mapping table representing the export namespace of the given
|
| - * [library].
|
| - *
|
| - * The given [visitedElements] a set of libraries that do not need to be
|
| - * visited when processing the export directives of the given library because
|
| - * all of the names defined by them will be added by another library.
|
| - */
|
| - HashMap<String, Element> _createExportMapping(
|
| - LibraryElement library, HashSet<LibraryElement> visitedElements) {
|
| - visitedElements.add(library);
|
| - try {
|
| - HashMap<String, Element> definedNames = new HashMap<String, Element>();
|
| - // Add names of the export directives.
|
| - for (ExportElement element in library.exports) {
|
| - LibraryElement exportedLibrary = element.exportedLibrary;
|
| - if (exportedLibrary != null &&
|
| - !visitedElements.contains(exportedLibrary)) {
|
| - //
|
| - // The exported library will be null if the URI does not reference a
|
| - // valid library.
|
| - //
|
| - HashMap<String, Element> exportedNames =
|
| - _createExportMapping(exportedLibrary, visitedElements);
|
| - exportedNames = _applyCombinators(exportedNames, element.combinators);
|
| - definedNames.addAll(exportedNames);
|
| - }
|
| - }
|
| - // Add names of the public namespace.
|
| - {
|
| - Namespace publicNamespace = library.publicNamespace;
|
| - if (publicNamespace != null) {
|
| - definedNames.addAll(publicNamespace.definedNames);
|
| - }
|
| - }
|
| - return definedNames;
|
| - } finally {
|
| - visitedElements.remove(library);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Apply the given [combinators] to all of the names in [definedNames].
|
| - */
|
| - static HashMap<String, Element> _applyCombinators(
|
| - HashMap<String, Element> definedNames,
|
| - List<NamespaceCombinator> combinators) {
|
| - for (NamespaceCombinator combinator in combinators) {
|
| - if (combinator is HideElementCombinator) {
|
| - _hide(definedNames, combinator.hiddenNames);
|
| - } else if (combinator is ShowElementCombinator) {
|
| - definedNames = _show(definedNames, combinator.shownNames);
|
| - }
|
| - }
|
| - return definedNames;
|
| - }
|
| -
|
| - /**
|
| - * Hide all of the [hiddenNames] by removing them from the given
|
| - * [definedNames].
|
| - */
|
| - static void _hide(
|
| - HashMap<String, Element> definedNames, List<String> hiddenNames) {
|
| - for (String name in hiddenNames) {
|
| - definedNames.remove(name);
|
| - definedNames.remove('$name=');
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Show only the given [shownNames] by removing all other names from the given
|
| - * [definedNames].
|
| - */
|
| - static HashMap<String, Element> _show(
|
| - HashMap<String, Element> definedNames, List<String> shownNames) {
|
| - HashMap<String, Element> newNames = new HashMap<String, Element>();
|
| - for (String name in shownNames) {
|
| - Element element = definedNames[name];
|
| - if (element != null) {
|
| - newNames[name] = element;
|
| - }
|
| - String setterName = '$name=';
|
| - element = definedNames[setterName];
|
| - if (element != null) {
|
| - newNames[setterName] = element;
|
| - }
|
| - }
|
| - return newNames;
|
| - }
|
| -}
|
| -
|
| /**
|
| * A task that builds [USED_IMPORTED_ELEMENTS] for a unit.
|
| */
|
| class GatherUsedImportedElementsTask extends SourceBasedAnalysisTask {
|
| /**
|
| - * The name of the [RESOLVED_UNIT9] input.
|
| + * The name of the [RESOLVED_UNIT11] input.
|
| */
|
| static const String UNIT_INPUT = 'UNIT_INPUT';
|
|
|
| @@ -2363,7 +2992,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_UNIT11.of(unit)};
|
| }
|
|
|
| /**
|
| @@ -2381,7 +3010,7 @@ class GatherUsedImportedElementsTask extends SourceBasedAnalysisTask {
|
| */
|
| class GatherUsedLocalElementsTask extends SourceBasedAnalysisTask {
|
| /**
|
| - * The name of the [RESOLVED_UNIT9] input.
|
| + * The name of the [RESOLVED_UNIT11] input.
|
| */
|
| static const String UNIT_INPUT = 'UNIT_INPUT';
|
|
|
| @@ -2425,7 +3054,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_UNIT11.of(unit)};
|
| }
|
|
|
| /**
|
| @@ -2443,7 +3072,7 @@ class GatherUsedLocalElementsTask extends SourceBasedAnalysisTask {
|
| */
|
| class GenerateHintsTask extends SourceBasedAnalysisTask {
|
| /**
|
| - * The name of the [RESOLVED_UNIT9] input.
|
| + * The name of the [RESOLVED_UNIT11] input.
|
| */
|
| static const String RESOLVED_UNIT_INPUT = 'RESOLVED_UNIT';
|
|
|
| @@ -2510,6 +3139,7 @@ class GenerateHintsTask extends SourceBasedAnalysisTask {
|
| usedImportedElementsList.forEach(verifier.removeUsedElements);
|
| verifier.generateDuplicateImportHints(errorReporter);
|
| verifier.generateUnusedImportHints(errorReporter);
|
| + verifier.generateUnusedShownNameHints(errorReporter);
|
| }
|
| // Unused local elements.
|
| {
|
| @@ -2524,11 +3154,13 @@ class GenerateHintsTask extends SourceBasedAnalysisTask {
|
| unit.accept(new Dart2JSVerifier(errorReporter));
|
| }
|
| // Dart best practices.
|
| - InheritanceManager inheritanceManager =
|
| - new InheritanceManager(libraryElement);
|
| + InheritanceManager inheritanceManager = new InheritanceManager(
|
| + libraryElement,
|
| + includeAbstractFromSuperclasses: true);
|
| TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
|
|
|
| - unit.accept(new BestPracticesVerifier(errorReporter, typeProvider,
|
| + unit.accept(new BestPracticesVerifier(
|
| + errorReporter, typeProvider, libraryElement, inheritanceManager,
|
| typeSystem: typeSystem));
|
| unit.accept(new OverrideVerifier(errorReporter, inheritanceManager));
|
| // Find to-do comments.
|
| @@ -2549,14 +3181,10 @@ class GenerateHintsTask extends SourceBasedAnalysisTask {
|
| Source libSource = unit.library;
|
| return <String, TaskInput>{
|
| RESOLVED_UNIT_INPUT: RESOLVED_UNIT.of(unit),
|
| - USED_LOCAL_ELEMENTS_INPUT: UNITS.of(libSource).toList((unit) {
|
| - LibrarySpecificUnit target = new LibrarySpecificUnit(libSource, unit);
|
| - return USED_LOCAL_ELEMENTS.of(target);
|
| - }),
|
| - USED_IMPORTED_ELEMENTS_INPUT: UNITS.of(libSource).toList((unit) {
|
| - LibrarySpecificUnit target = new LibrarySpecificUnit(libSource, unit);
|
| - return USED_IMPORTED_ELEMENTS.of(target);
|
| - }),
|
| + USED_LOCAL_ELEMENTS_INPUT:
|
| + LIBRARY_SPECIFIC_UNITS.of(libSource).toListOf(USED_LOCAL_ELEMENTS),
|
| + USED_IMPORTED_ELEMENTS_INPUT:
|
| + LIBRARY_SPECIFIC_UNITS.of(libSource).toListOf(USED_IMPORTED_ELEMENTS),
|
| TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
|
| };
|
| }
|
| @@ -2613,10 +3241,25 @@ class GenerateLintsTask extends SourceBasedAnalysisTask {
|
| //
|
| // Generate lints.
|
| //
|
| + List<AstVisitor> visitors = <AstVisitor>[];
|
| +
|
| + bool timeVisits = analysisOptions.enableTiming;
|
| List<Linter> linters = getLints(context);
|
| - linters.forEach((l) => l.reporter = errorReporter);
|
| - Iterable<AstVisitor> visitors = linters.map((l) => l.getVisitor()).toList();
|
| - unit.accept(new DelegatingAstVisitor(visitors.where((v) => v != null)));
|
| + int length = linters.length;
|
| + for (int i = 0; i < length; i++) {
|
| + Linter linter = linters[i];
|
| + AstVisitor visitor = linter.getVisitor();
|
| + if (visitor != null) {
|
| + linter.reporter = errorReporter;
|
| + if (timeVisits) {
|
| + visitor = new TimedAstVisitor(visitor, lintRegistry.getTimer(linter));
|
| + }
|
| + visitors.add(visitor);
|
| + }
|
| + }
|
| +
|
| + DelegatingAstVisitor dv = new DelegatingAstVisitor(visitors);
|
| + unit.accept(dv);
|
|
|
| //
|
| // Record outputs.
|
| @@ -2643,7 +3286,81 @@ class GenerateLintsTask extends SourceBasedAnalysisTask {
|
| }
|
|
|
| /**
|
| - * A task that ensures that all of the inferrable instance members in a
|
| + * Information about analysis `//ignore:` comments within a source file.
|
| + */
|
| +class IgnoreInfo {
|
| + /**
|
| + * Instance shared by all cases without matches.
|
| + */
|
| + static final IgnoreInfo _EMPTY_INFO = new IgnoreInfo();
|
| +
|
| + /**
|
| + * A regular expression for matching 'ignore' comments. Produces matches
|
| + * containing 2 groups. For example:
|
| + *
|
| + * * ['//ignore: error_code', 'error_code']
|
| + *
|
| + * Resulting codes may be in a list ('error_code_1,error_code2').
|
| + */
|
| + static final RegExp _IGNORE_MATCHER =
|
| + new RegExp(r'//[ ]*ignore:(.*)$', multiLine: true);
|
| +
|
| + final Map<int, List<String>> _ignoreMap = new HashMap<int, List<String>>();
|
| +
|
| + /**
|
| + * Whether this info object defines any ignores.
|
| + */
|
| + bool get hasIgnores => ignores.isNotEmpty;
|
| +
|
| + /**
|
| + * Map of line numbers to associated ignored error codes.
|
| + */
|
| + Map<int, Iterable<String>> get ignores => _ignoreMap;
|
| +
|
| + /**
|
| + * Ignore this [errorCode] at [line].
|
| + */
|
| + void add(int line, String errorCode) {
|
| + _ignoreMap.putIfAbsent(line, () => new List<String>()).add(errorCode);
|
| + }
|
| +
|
| + /**
|
| + * Ignore these [errorCodes] at [line].
|
| + */
|
| + void addAll(int line, Iterable<String> errorCodes) {
|
| + _ignoreMap.putIfAbsent(line, () => new List<String>()).addAll(errorCodes);
|
| + }
|
| +
|
| + /**
|
| + * Test whether this [errorCode] is ignored at the given [line].
|
| + */
|
| + bool ignoredAt(String errorCode, int line) =>
|
| + _ignoreMap[line]?.contains(errorCode) == true;
|
| +
|
| + /**
|
| + * Calculate ignores for the given [content] with line [info].
|
| + */
|
| + static IgnoreInfo calculateIgnores(String content, LineInfo info) {
|
| + Iterable<Match> matches = _IGNORE_MATCHER.allMatches(content);
|
| + if (matches.isEmpty) {
|
| + return _EMPTY_INFO;
|
| + }
|
| +
|
| + IgnoreInfo ignoreInfo = new IgnoreInfo();
|
| + for (Match match in matches) {
|
| + // See _IGNORE_MATCHER for format --- note the possibility of error lists.
|
| + Iterable<String> codes = match
|
| + .group(1)
|
| + .split(',')
|
| + .map((String code) => code.trim().toLowerCase());
|
| + ignoreInfo.addAll(info.getLocation(match.start).lineNumber, codes);
|
| + }
|
| + return ignoreInfo;
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A task that ensures that all of the inferable instance members in a
|
| * compilation unit have had their type inferred.
|
| */
|
| class InferInstanceMembersInUnitTask extends SourceBasedAnalysisTask {
|
| @@ -2653,7 +3370,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_UNIT8] for the
|
| * compilation unit.
|
| */
|
| static const String UNIT_INPUT = 'UNIT_INPUT';
|
| @@ -2665,7 +3382,7 @@ class InferInstanceMembersInUnitTask extends SourceBasedAnalysisTask {
|
| 'InferInstanceMembersInUnitTask',
|
| createTask,
|
| buildInputs,
|
| - <ResultDescriptor>[RESOLVED_UNIT8]);
|
| + <ResultDescriptor>[CREATED_RESOLVED_UNIT10, RESOLVED_UNIT10]);
|
|
|
| /**
|
| * Initialize a newly created task to build a library element for the given
|
| @@ -2689,14 +3406,16 @@ class InferInstanceMembersInUnitTask extends SourceBasedAnalysisTask {
|
| // Infer instance members.
|
| //
|
| if (context.analysisOptions.strongMode) {
|
| - InstanceMemberInferrer inferrer = new InstanceMemberInferrer(typeProvider,
|
| + InstanceMemberInferrer inferrer = new InstanceMemberInferrer(
|
| + typeProvider, new InheritanceManager(unit.element.library),
|
| typeSystem: context.typeSystem);
|
| inferrer.inferCompilationUnit(unit.element);
|
| }
|
| //
|
| // Record outputs.
|
| //
|
| - outputs[RESOLVED_UNIT8] = unit;
|
| + outputs[RESOLVED_UNIT10] = unit;
|
| + outputs[CREATED_RESOLVED_UNIT10] = true;
|
| }
|
|
|
| /**
|
| @@ -2707,21 +3426,20 @@ 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_UNIT9.of(unit),
|
| TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
|
| // In strong mode, add additional dependencies to enforce inference
|
| // ordering.
|
|
|
| // 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
|
| - .of(new LibrarySpecificUnit(unit.librarySource, unit.source))),
|
| + 'orderLibraryCycleTasks':
|
| + LIBRARY_CYCLE_UNITS.of(unit.library).toListOf(CREATED_RESOLVED_UNIT9),
|
| // 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
|
| - .of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
|
| + 'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES
|
| + .of(unit.library)
|
| + .toListOf(CREATED_RESOLVED_UNIT10)
|
| };
|
| }
|
|
|
| @@ -2750,34 +3468,70 @@ abstract class InferStaticVariableTask extends ConstantEvaluationAnalysisTask {
|
| */
|
| VariableDeclaration getDeclaration(CompilationUnit unit) {
|
| VariableElement variable = target;
|
| - NodeLocator locator = new NodeLocator(variable.nameOffset);
|
| - AstNode node = locator.searchWithin(unit);
|
| + int offset = variable.nameOffset;
|
| + AstNode node = new NodeLocator2(offset).searchWithin(unit);
|
| + if (node == null) {
|
| + Source variableSource = variable.source;
|
| + Source unitSource = unit.element.source;
|
| + if (variableSource != unitSource) {
|
| + throw new AnalysisException(
|
| + "Failed to find the AST node for the variable "
|
| + "${variable.displayName} at $offset in $variableSource "
|
| + "because we were looking in $unitSource");
|
| + }
|
| + throw new AnalysisException(
|
| + "Failed to find the AST node for the variable "
|
| + "${variable.displayName} at $offset in $variableSource");
|
| + }
|
| VariableDeclaration declaration =
|
| node.getAncestor((AstNode ancestor) => ancestor is VariableDeclaration);
|
| if (declaration == null || declaration.name != node) {
|
| + Source variableSource = variable.source;
|
| + Source unitSource = unit.element.source;
|
| + if (variableSource != unitSource) {
|
| + if (declaration == null) {
|
| + throw new AnalysisException(
|
| + "Failed to find the declaration of the variable "
|
| + "${variable.displayName} at $offset in $variableSource "
|
| + "because the node was not in a variable declaration "
|
| + "possibly because we were looking in $unitSource");
|
| + }
|
| + throw new AnalysisException(
|
| + "Failed to find the declaration of the variable "
|
| + "${variable.displayName} at $offset in $variableSource "
|
| + "because we were looking in $unitSource");
|
| + }
|
| + if (declaration == null) {
|
| + throw new AnalysisException(
|
| + "Failed to find the declaration of the variable "
|
| + "${variable.displayName} at $offset in $variableSource "
|
| + "because the node was not in a variable declaration");
|
| + }
|
| throw new AnalysisException(
|
| - "Failed to find the declaration of the variable ${variable.displayName} in ${variable.source}");
|
| + "Failed to find the declaration of the variable "
|
| + "${variable.displayName} at $offset in $variableSource "
|
| + "because the node was not the name in a variable declaration");
|
| }
|
| return declaration;
|
| }
|
| }
|
|
|
| /**
|
| - * A task that ensures that all of the inferrable static variables in a
|
| + * A task that ensures that all of the inferable static variables in a
|
| * compilation unit have had their type inferred.
|
| */
|
| 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_UNIT8] for the
|
| * compilation unit.
|
| */
|
| static const String UNIT_INPUT = 'UNIT_INPUT';
|
|
|
| /**
|
| - * The name of the input whose value is a list of the inferrable static
|
| - * variables whose types have been computed.
|
| + * The name of the [STATIC_VARIABLE_RESOLUTION_ERRORS] for all static
|
| + * variables in the compilation unit.
|
| */
|
| - static const String INFERRED_VARIABLES_INPUT = 'INFERRED_VARIABLES_INPUT';
|
| + static const String ERRORS_LIST_INPUT = 'INFERRED_VARIABLES_INPUT';
|
|
|
| /**
|
| * The task descriptor describing this kind of task.
|
| @@ -2785,8 +3539,11 @@ class InferStaticVariableTypesInUnitTask extends SourceBasedAnalysisTask {
|
| static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| 'InferStaticVariableTypesInUnitTask',
|
| createTask,
|
| - buildInputs,
|
| - <ResultDescriptor>[RESOLVED_UNIT6]);
|
| + buildInputs, <ResultDescriptor>[
|
| + CREATED_RESOLVED_UNIT8,
|
| + RESOLVED_UNIT8,
|
| + STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT
|
| + ]);
|
|
|
| /**
|
| * Initialize a newly created task to build a library element for the given
|
| @@ -2805,12 +3562,16 @@ class InferStaticVariableTypesInUnitTask extends SourceBasedAnalysisTask {
|
| // Prepare inputs.
|
| //
|
| CompilationUnit unit = getRequiredInput(UNIT_INPUT);
|
| + List<List<AnalysisError>> errorLists = getRequiredInput(ERRORS_LIST_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;
|
| + outputs[RESOLVED_UNIT8] = unit;
|
| + outputs[CREATED_RESOLVED_UNIT8] = true;
|
| + outputs[STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT] =
|
| + AnalysisError.mergeLists(errorLists);
|
| }
|
|
|
| /**
|
| @@ -2821,10 +3582,13 @@ class InferStaticVariableTypesInUnitTask extends SourceBasedAnalysisTask {
|
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| LibrarySpecificUnit unit = target;
|
| return <String, TaskInput>{
|
| - INFERRED_VARIABLES_INPUT: INFERABLE_STATIC_VARIABLES_IN_UNIT
|
| + 'inferredTypes': INFERABLE_STATIC_VARIABLES_IN_UNIT
|
| .of(unit)
|
| .toListOf(INFERRED_STATIC_VARIABLE),
|
| - UNIT_INPUT: RESOLVED_UNIT5.of(unit)
|
| + ERRORS_LIST_INPUT: INFERABLE_STATIC_VARIABLES_IN_UNIT
|
| + .of(unit)
|
| + .toListOf(STATIC_VARIABLE_RESOLUTION_ERRORS),
|
| + UNIT_INPUT: RESOLVED_UNIT7.of(unit)
|
| };
|
| }
|
|
|
| @@ -2839,7 +3603,7 @@ class InferStaticVariableTypesInUnitTask extends SourceBasedAnalysisTask {
|
| }
|
|
|
| /**
|
| - * A task that computes the type of an inferrable static variable and
|
| + * A task that computes the type of an inferable static variable and
|
| * stores it in the element model.
|
| */
|
| class InferStaticVariableTypeTask extends InferStaticVariableTask {
|
| @@ -2855,15 +3619,17 @@ 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_UNIT8] input.
|
| */
|
| static const String UNIT_INPUT = 'UNIT_INPUT';
|
|
|
| static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| 'InferStaticVariableTypeTask',
|
| createTask,
|
| - buildInputs,
|
| - <ResultDescriptor>[INFERRED_STATIC_VARIABLE]);
|
| + buildInputs, <ResultDescriptor>[
|
| + INFERRED_STATIC_VARIABLE,
|
| + STATIC_VARIABLE_RESOLUTION_ERRORS
|
| + ]);
|
|
|
| InferStaticVariableTypeTask(
|
| InternalAnalysisContext context, VariableElement variable)
|
| @@ -2891,17 +3657,19 @@ class InferStaticVariableTypeTask extends InferStaticVariableTask {
|
|
|
| // If we're not in a dependency cycle, and we have no type annotation,
|
| // re-resolve the right hand side and do inference.
|
| + List<AnalysisError> errors = AnalysisError.NO_ERRORS;
|
| if (dependencyCycle == null && variable.hasImplicitType) {
|
| VariableDeclaration declaration = getDeclaration(unit);
|
| //
|
| // Re-resolve the variable's initializer so that the inferred types
|
| // of other variables will be propagated.
|
| //
|
| + RecordingErrorListener errorListener = new RecordingErrorListener();
|
| Expression initializer = declaration.initializer;
|
| - ResolutionContext resolutionContext = ResolutionContextBuilder.contextFor(
|
| - initializer, AnalysisErrorListener.NULL_LISTENER);
|
| - ResolverVisitor visitor = new ResolverVisitor(variable.library,
|
| - variable.source, typeProvider, AnalysisErrorListener.NULL_LISTENER,
|
| + ResolutionContext resolutionContext =
|
| + ResolutionContextBuilder.contextFor(initializer);
|
| + ResolverVisitor visitor = new ResolverVisitor(
|
| + variable.library, variable.source, typeProvider, errorListener,
|
| nameScope: resolutionContext.scope);
|
| if (resolutionContext.enclosingClassDeclaration != null) {
|
| visitor.prepareToResolveMembersInClass(
|
| @@ -2917,14 +3685,8 @@ class InferStaticVariableTypeTask extends InferStaticVariableTask {
|
| if (newType == null || newType.isBottom) {
|
| newType = typeProvider.dynamicType;
|
| }
|
| - variable.type = newType;
|
| - (variable.initializer as ExecutableElementImpl).returnType = newType;
|
| - if (variable is PropertyInducingElementImpl) {
|
| - setReturnType(variable.getter, newType);
|
| - if (!variable.isFinal && !variable.isConst) {
|
| - setParameterType(variable.setter, newType);
|
| - }
|
| - }
|
| + setFieldType(variable, newType);
|
| + errors = getUniqueErrors(errorListener.errors);
|
| } else {
|
| // TODO(brianwilkerson) For now we simply don't infer any type for
|
| // variables or fields involved in a cycle. We could try to be smarter
|
| @@ -2937,6 +3699,7 @@ class InferStaticVariableTypeTask extends InferStaticVariableTask {
|
| // Record outputs.
|
| //
|
| outputs[INFERRED_STATIC_VARIABLE] = variable;
|
| + outputs[STATIC_VARIABLE_RESOLUTION_ERRORS] = errors;
|
| }
|
|
|
| /**
|
| @@ -2953,15 +3716,15 @@ 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_UNIT7.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
|
| - .of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
|
| + 'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES
|
| + .of(unit.library)
|
| + .toListOf(CREATED_RESOLVED_UNIT10)
|
| };
|
| }
|
|
|
| @@ -3003,12 +3766,13 @@ class LibraryErrorsReadyTask extends SourceBasedAnalysisTask {
|
| /**
|
| * 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 [library].
|
| + * given [target].
|
| */
|
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| Source source = target;
|
| return <String, TaskInput>{
|
| - 'allErrors': UNITS.of(source).toListOf(DART_ERRORS)
|
| + 'allErrors': UNITS.of(source).toListOf(DART_ERRORS),
|
| + 'libraryElement': LIBRARY_ELEMENT.of(source)
|
| };
|
| }
|
|
|
| @@ -3047,6 +3811,12 @@ class LibraryUnitErrorsTask extends SourceBasedAnalysisTask {
|
| */
|
| static const String LINTS_INPUT = 'LINTS';
|
|
|
| + /**
|
| + * The name of the [STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT] input.
|
| + */
|
| + static const String STATIC_VARIABLE_RESOLUTION_ERRORS_INPUT =
|
| + 'STATIC_VARIABLE_RESOLUTION_ERRORS_INPUT';
|
| +
|
| /**
|
| * The name of the [STRONG_MODE_ERRORS] input.
|
| */
|
| @@ -3058,6 +3828,12 @@ class LibraryUnitErrorsTask extends SourceBasedAnalysisTask {
|
| static const String RESOLVE_TYPE_NAMES_ERRORS_INPUT =
|
| 'RESOLVE_TYPE_NAMES_ERRORS';
|
|
|
| + /**
|
| + * The name of the [RESOLVE_TYPE_BOUNDS_ERRORS] input.
|
| + */
|
| + static const String RESOLVE_TYPE_NAMES_ERRORS2_INPUT =
|
| + 'RESOLVE_TYPE_NAMES_ERRORS2';
|
| +
|
| /**
|
| * The name of the [RESOLVE_UNIT_ERRORS] input.
|
| */
|
| @@ -3100,7 +3876,9 @@ class LibraryUnitErrorsTask extends SourceBasedAnalysisTask {
|
| errorLists.add(getRequiredInput(HINTS_INPUT));
|
| errorLists.add(getRequiredInput(LINTS_INPUT));
|
| errorLists.add(getRequiredInput(RESOLVE_TYPE_NAMES_ERRORS_INPUT));
|
| + errorLists.add(getRequiredInput(RESOLVE_TYPE_NAMES_ERRORS2_INPUT));
|
| errorLists.add(getRequiredInput(RESOLVE_UNIT_ERRORS_INPUT));
|
| + errorLists.add(getRequiredInput(STATIC_VARIABLE_RESOLUTION_ERRORS_INPUT));
|
| errorLists.add(getRequiredInput(STRONG_MODE_ERRORS_INPUT));
|
| errorLists.add(getRequiredInput(VARIABLE_REFERENCE_ERRORS_INPUT));
|
| errorLists.add(getRequiredInput(VERIFY_ERRORS_INPUT));
|
| @@ -3121,7 +3899,10 @@ class LibraryUnitErrorsTask extends SourceBasedAnalysisTask {
|
| HINTS_INPUT: HINTS.of(unit),
|
| LINTS_INPUT: LINTS.of(unit),
|
| RESOLVE_TYPE_NAMES_ERRORS_INPUT: RESOLVE_TYPE_NAMES_ERRORS.of(unit),
|
| + RESOLVE_TYPE_NAMES_ERRORS2_INPUT: RESOLVE_TYPE_BOUNDS_ERRORS.of(unit),
|
| RESOLVE_UNIT_ERRORS_INPUT: RESOLVE_UNIT_ERRORS.of(unit),
|
| + STATIC_VARIABLE_RESOLUTION_ERRORS_INPUT:
|
| + STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT.of(unit),
|
| STRONG_MODE_ERRORS_INPUT: STRONG_MODE_ERRORS.of(unit),
|
| VARIABLE_REFERENCE_ERRORS_INPUT: VARIABLE_REFERENCE_ERRORS.of(unit),
|
| VERIFY_ERRORS_INPUT: VERIFY_ERRORS.of(unit)
|
| @@ -3182,12 +3963,25 @@ class ParseDartTask extends SourceBasedAnalysisTask {
|
| EXPORTED_LIBRARIES,
|
| IMPORTED_LIBRARIES,
|
| INCLUDED_PARTS,
|
| + LIBRARY_SPECIFIC_UNITS,
|
| PARSE_ERRORS,
|
| PARSED_UNIT,
|
| + REFERENCED_NAMES,
|
| + REFERENCED_SOURCES,
|
| SOURCE_KIND,
|
| - UNITS
|
| + UNITS,
|
| ]);
|
|
|
| + /**
|
| + * The source that is being parsed.
|
| + */
|
| + Source _source;
|
| +
|
| + /**
|
| + * The [ErrorReporter] to report errors to.
|
| + */
|
| + ErrorReporter _errorReporter;
|
| +
|
| /**
|
| * Initialize a newly created task to parse the content of the Dart file
|
| * associated with the given [target] in the given [context].
|
| @@ -3200,16 +3994,21 @@ class ParseDartTask extends SourceBasedAnalysisTask {
|
|
|
| @override
|
| void internalPerform() {
|
| - Source source = getRequiredSource();
|
| + _source = getRequiredSource();
|
| LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT_NAME);
|
| int modificationTime = getRequiredInput(MODIFICATION_TIME_INPUT_NAME);
|
| Token tokenStream = getRequiredInput(TOKEN_STREAM_INPUT_NAME);
|
|
|
| RecordingErrorListener errorListener = new RecordingErrorListener();
|
| - Parser parser = new Parser(source, errorListener);
|
| + _errorReporter = new ErrorReporter(errorListener, _source);
|
| +
|
| + Parser parser = new Parser(_source, errorListener);
|
| AnalysisOptions options = context.analysisOptions;
|
| - parser.parseFunctionBodies = options.analyzeFunctionBodiesPredicate(source);
|
| + parser.enableAssertInitializer = options.enableAssertInitializer;
|
| + parser.parseFunctionBodies =
|
| + options.analyzeFunctionBodiesPredicate(_source);
|
| parser.parseGenericMethods = options.enableGenericMethods;
|
| + parser.parseGenericMethodComments = options.strongMode;
|
| CompilationUnit unit = parser.parseCompilationUnit(tokenStream);
|
| unit.lineInfo = lineInfo;
|
|
|
| @@ -3218,14 +4017,16 @@ class ParseDartTask extends SourceBasedAnalysisTask {
|
| HashSet<Source> explicitlyImportedSourceSet = new HashSet<Source>();
|
| HashSet<Source> exportedSourceSet = new HashSet<Source>();
|
| HashSet<Source> includedSourceSet = new HashSet<Source>();
|
| - for (Directive directive in unit.directives) {
|
| + NodeList<Directive> directives = unit.directives;
|
| + int length = directives.length;
|
| + for (int i = 0; i < length; i++) {
|
| + Directive directive = directives[i];
|
| if (directive is PartOfDirective) {
|
| hasPartOfDirective = true;
|
| } else {
|
| hasNonPartOfDirective = true;
|
| if (directive is UriBasedDirective) {
|
| - Source referencedSource =
|
| - resolveDirective(context, source, directive, errorListener);
|
| + Source referencedSource = _resolveDirective(directive);
|
| if (referencedSource != null) {
|
| if (directive is ExportDirective) {
|
| exportedSourceSet.add(referencedSource);
|
| @@ -3247,6 +4048,16 @@ class ParseDartTask extends SourceBasedAnalysisTask {
|
| HashSet<Source> importedSourceSet =
|
| new HashSet.from(explicitlyImportedSourceSet);
|
| Source coreLibrarySource = context.sourceFactory.forUri(DartSdk.DART_CORE);
|
| + if (coreLibrarySource == null) {
|
| + String message;
|
| + DartSdk sdk = context.sourceFactory.dartSdk;
|
| + if (sdk == null) {
|
| + message = 'Could not resolve "dart:core": SDK not defined';
|
| + } else {
|
| + message = 'Could not resolve "dart:core": SDK incorrectly configured';
|
| + }
|
| + throw new AnalysisException(message);
|
| + }
|
| importedSourceSet.add(coreLibrarySource);
|
| //
|
| // Compute kind.
|
| @@ -3258,36 +4069,137 @@ class ParseDartTask extends SourceBasedAnalysisTask {
|
| sourceKind = SourceKind.PART;
|
| }
|
| //
|
| - // Record outputs.
|
| + // Compute referenced names.
|
| + //
|
| + ReferencedNames referencedNames = new ReferencedNames(_source);
|
| + new ReferencedNamesBuilder(referencedNames).build(unit);
|
| + //
|
| + // Compute source lists.
|
| //
|
| List<Source> explicitlyImportedSources =
|
| explicitlyImportedSourceSet.toList();
|
| List<Source> exportedSources = exportedSourceSet.toList();
|
| List<Source> importedSources = importedSourceSet.toList();
|
| List<Source> includedSources = includedSourceSet.toList();
|
| - List<AnalysisError> parseErrors =
|
| - removeDuplicateErrors(errorListener.errors);
|
| - List<Source> unitSources = <Source>[source]..addAll(includedSourceSet);
|
| + List<Source> unitSources = <Source>[_source]..addAll(includedSourceSet);
|
| + List<LibrarySpecificUnit> librarySpecificUnits =
|
| + unitSources.map((s) => new LibrarySpecificUnit(_source, s)).toList();
|
| + //
|
| + // Compute referenced sources.
|
| + //
|
| + Set<Source> referencedSources = new Set<Source>();
|
| + referencedSources.add(coreLibrarySource);
|
| + referencedSources.addAll(unitSources);
|
| + for (Directive directive in unit.directives) {
|
| + if (directive is NamespaceDirective) {
|
| + referencedSources.add(directive.uriSource);
|
| + for (Configuration configuration in directive.configurations) {
|
| + referencedSources.add(configuration.uriSource);
|
| + }
|
| + }
|
| + }
|
| + referencedSources.removeWhere((source) => source == null);
|
| + //
|
| + // Record outputs.
|
| + //
|
| + List<AnalysisError> parseErrors = getUniqueErrors(errorListener.errors);
|
| outputs[EXPLICITLY_IMPORTED_LIBRARIES] = explicitlyImportedSources;
|
| outputs[EXPORTED_LIBRARIES] = exportedSources;
|
| outputs[IMPORTED_LIBRARIES] = importedSources;
|
| outputs[INCLUDED_PARTS] = includedSources;
|
| + outputs[LIBRARY_SPECIFIC_UNITS] = librarySpecificUnits;
|
| outputs[PARSE_ERRORS] = parseErrors;
|
| outputs[PARSED_UNIT] = unit;
|
| + outputs[REFERENCED_NAMES] = referencedNames;
|
| + outputs[REFERENCED_SOURCES] = referencedSources.toList();
|
| outputs[SOURCE_KIND] = sourceKind;
|
| outputs[UNITS] = unitSources;
|
| }
|
|
|
| + /**
|
| + * Return the result of resolving the URI of the given URI-based [directive]
|
| + * against the URI of the given library, or `null` if the URI is not valid.
|
| + */
|
| + Source _resolveDirective(UriBasedDirective directive) {
|
| + bool isImport = directive is ImportDirective;
|
| +
|
| + // Resolve the default URI.
|
| + Source defaultSource;
|
| + {
|
| + StringLiteral uriLiteral = directive.uri;
|
| + String uriContent = uriLiteral.stringValue;
|
| + if (uriContent != null) {
|
| + uriContent = uriContent.trim();
|
| + directive.uriContent = uriContent;
|
| + }
|
| + defaultSource = _resolveUri(isImport, uriLiteral, uriContent);
|
| + directive.uriSource = defaultSource;
|
| + }
|
| +
|
| + // Resolve all configurations and try to choose one.
|
| + if (directive is NamespaceDirectiveImpl) {
|
| + String configuredUriContent;
|
| + Source configuredSource;
|
| + for (Configuration configuration in directive.configurations) {
|
| + String uriContent = configuration.uri.stringValue;
|
| + Source source = _resolveUri(isImport, configuration.uri, uriContent);
|
| + configuration.uriSource = source;
|
| + if (configuredSource == null) {
|
| + String variableName =
|
| + configuration.name.components.map((i) => i.name).join('.');
|
| + String variableValue = context.declaredVariables.get(variableName);
|
| + if (configuration.value != null &&
|
| + variableValue == configuration.value.stringValue ||
|
| + variableValue == 'true') {
|
| + configuredUriContent = configuration.uri.stringValue;
|
| + configuredSource = source;
|
| + }
|
| + }
|
| + }
|
| + String selectedContentUri = configuredUriContent ?? directive.uriContent;
|
| + Source selectedSource = configuredSource ?? defaultSource;
|
| + directive.selectedUriContent = selectedContentUri;
|
| + directive.selectedSource = selectedSource;
|
| + return selectedSource;
|
| + }
|
| + return defaultSource;
|
| + }
|
| +
|
| + /**
|
| + * Return the result of resolve the given [uriContent], reporting errors
|
| + * against the [uriLiteral].
|
| + */
|
| + Source _resolveUri(
|
| + bool isImport, StringLiteral uriLiteral, String uriContent) {
|
| + UriValidationCode code =
|
| + UriBasedDirectiveImpl.validateUri(isImport, uriLiteral, uriContent);
|
| + if (code == null) {
|
| + String encodedUriContent = Uri.encodeFull(uriContent);
|
| + return context.sourceFactory.resolveUri(_source, encodedUriContent);
|
| + } else if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
|
| + return null;
|
| + } else if (code == UriValidationCode.URI_WITH_INTERPOLATION) {
|
| + _errorReporter.reportErrorForNode(
|
| + CompileTimeErrorCode.URI_WITH_INTERPOLATION, uriLiteral);
|
| + return null;
|
| + } else if (code == UriValidationCode.INVALID_URI) {
|
| + _errorReporter.reportErrorForNode(
|
| + CompileTimeErrorCode.INVALID_URI, uriLiteral, [uriContent]);
|
| + return null;
|
| + }
|
| + throw new AnalysisException('Failed to handle validation code: $code');
|
| + }
|
| +
|
| /**
|
| * 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
|
| - * [source].
|
| + * [target].
|
| */
|
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| return <String, TaskInput>{
|
| LINE_INFO_INPUT_NAME: LINE_INFO.of(target),
|
| MODIFICATION_TIME_INPUT_NAME: MODIFICATION_TIME.of(target),
|
| - TOKEN_STREAM_INPUT_NAME: TOKEN_STREAM.of(target)
|
| + TOKEN_STREAM_INPUT_NAME: TOKEN_STREAM.of(target, flushOnAccess: true)
|
| };
|
| }
|
|
|
| @@ -3299,58 +4211,19 @@ class ParseDartTask extends SourceBasedAnalysisTask {
|
| AnalysisContext context, AnalysisTarget target) {
|
| return new ParseDartTask(context, target);
|
| }
|
| -
|
| - /**
|
| - * Return the result of resolving the URI of the given URI-based [directive]
|
| - * against the URI of the given library, or `null` if the URI is not valid.
|
| - *
|
| - * Resolution is to be performed in the given [context]. Errors should be
|
| - * reported to the [errorListener].
|
| - */
|
| - static Source resolveDirective(AnalysisContext context, Source librarySource,
|
| - UriBasedDirective directive, AnalysisErrorListener errorListener) {
|
| - StringLiteral uriLiteral = directive.uri;
|
| - String uriContent = uriLiteral.stringValue;
|
| - if (uriContent != null) {
|
| - uriContent = uriContent.trim();
|
| - directive.uriContent = uriContent;
|
| - }
|
| - UriValidationCode code = directive.validate();
|
| - if (code == null) {
|
| - String encodedUriContent = Uri.encodeFull(uriContent);
|
| - Source source =
|
| - context.sourceFactory.resolveUri(librarySource, encodedUriContent);
|
| - directive.source = source;
|
| - return source;
|
| - }
|
| - if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
|
| - return null;
|
| - }
|
| - if (code == UriValidationCode.URI_WITH_INTERPOLATION) {
|
| - errorListener.onError(new AnalysisError(librarySource, uriLiteral.offset,
|
| - uriLiteral.length, CompileTimeErrorCode.URI_WITH_INTERPOLATION));
|
| - return null;
|
| - }
|
| - if (code == UriValidationCode.INVALID_URI) {
|
| - errorListener.onError(new AnalysisError(librarySource, uriLiteral.offset,
|
| - uriLiteral.length, CompileTimeErrorCode.INVALID_URI, [uriContent]));
|
| - return null;
|
| - }
|
| - throw new AnalysisException('Failed to handle validation code: $code');
|
| - }
|
| }
|
|
|
| /**
|
| - * A task that builds [RESOLVED_UNIT5] for a unit.
|
| + * A task that builds [RESOLVED_UNIT7] for a unit.
|
| */
|
| class PartiallyResolveUnitReferencesTask extends SourceBasedAnalysisTask {
|
| /**
|
| - * The name of the [LIBRARY_ELEMENT5] input.
|
| + * The name of the [LIBRARY_ELEMENT6] input.
|
| */
|
| static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
|
|
|
| /**
|
| - * The name of the [RESOLVED_UNIT4] input.
|
| + * The name of the [RESOLVED_UNIT6] input.
|
| */
|
| static const String UNIT_INPUT = 'UNIT_INPUT';
|
|
|
| @@ -3365,8 +4238,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,
|
| + CREATED_RESOLVED_UNIT7,
|
| + RESOLVED_UNIT7
|
| + ]);
|
|
|
| PartiallyResolveUnitReferencesTask(
|
| InternalAnalysisContext context, AnalysisTarget target)
|
| @@ -3387,22 +4263,19 @@ class PartiallyResolveUnitReferencesTask extends SourceBasedAnalysisTask {
|
| //
|
| // Resolve references and record outputs.
|
| //
|
| + PartialResolverVisitor visitor = new PartialResolverVisitor(libraryElement,
|
| + unitElement.source, typeProvider, AnalysisErrorListener.NULL_LISTENER);
|
| + 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[RESOLVED_UNIT5] = unit;
|
| + outputs[RESOLVED_UNIT7] = unit;
|
| + outputs[CREATED_RESOLVED_UNIT7] = true;
|
| }
|
|
|
| /**
|
| @@ -3413,20 +4286,18 @@ class PartiallyResolveUnitReferencesTask extends SourceBasedAnalysisTask {
|
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| LibrarySpecificUnit unit = target;
|
| return <String, TaskInput>{
|
| - 'fullyBuiltLibraryElements': IMPORT_EXPORT_SOURCE_CLOSURE
|
| - .of(unit.library)
|
| - .toListOf(LIBRARY_ELEMENT5),
|
| - LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library),
|
| - UNIT_INPUT: RESOLVED_UNIT4.of(unit),
|
| + 'fullyBuiltLibraryElements': READY_LIBRARY_ELEMENT6.of(unit.library),
|
| + LIBRARY_INPUT: LIBRARY_ELEMENT6.of(unit.library),
|
| + UNIT_INPUT: RESOLVED_UNIT6.of(unit),
|
| TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
|
| // 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
|
| - .of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
|
| + 'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES
|
| + .of(unit.library)
|
| + .toListOf(CREATED_RESOLVED_UNIT10)
|
| };
|
| }
|
|
|
| @@ -3441,93 +4312,238 @@ class PartiallyResolveUnitReferencesTask extends SourceBasedAnalysisTask {
|
| }
|
|
|
| /**
|
| - * The helper for building the public [Namespace] of a [LibraryElement].
|
| + * A task that ensures that [LIBRARY_ELEMENT2] is ready for the target library
|
| + * source and its import/export closure.
|
| */
|
| -class PublicNamespaceBuilder {
|
| - final HashMap<String, Element> definedNames = new HashMap<String, Element>();
|
| +class ReadyLibraryElement2Task extends SourceBasedAnalysisTask {
|
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| + 'ReadyLibraryElement2Task',
|
| + createTask,
|
| + buildInputs,
|
| + <ResultDescriptor>[READY_LIBRARY_ELEMENT2]);
|
|
|
| - /**
|
| - * Build a public [Namespace] of the given [library].
|
| - */
|
| - Namespace build(LibraryElement library) {
|
| - definedNames.clear();
|
| - _addPublicNames(library.definingCompilationUnit);
|
| - library.parts.forEach(_addPublicNames);
|
| - return new Namespace(definedNames);
|
| + ReadyLibraryElement2Task(
|
| + InternalAnalysisContext context, AnalysisTarget target)
|
| + : super(context, target);
|
| +
|
| + @override
|
| + TaskDescriptor get descriptor => DESCRIPTOR;
|
| +
|
| + @override
|
| + bool get handlesDependencyCycles => true;
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + outputs[READY_LIBRARY_ELEMENT2] = true;
|
| }
|
|
|
| - /**
|
| - * Add the given [element] if it has a publicly visible name.
|
| - */
|
| - void _addIfPublic(Element element) {
|
| - String name = element.name;
|
| - if (name != null && !Scope.isPrivateName(name)) {
|
| - definedNames[name] = element;
|
| - }
|
| + static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| + Source source = target;
|
| + return <String, TaskInput>{
|
| + 'thisLibraryElementReady': LIBRARY_ELEMENT2.of(source),
|
| + 'directlyImportedLibrariesReady':
|
| + IMPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT2),
|
| + 'directlyExportedLibrariesReady':
|
| + EXPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT2),
|
| + };
|
| }
|
|
|
| - /**
|
| - * Add all of the public top-level names that are defined in the given
|
| - * [compilationUnit].
|
| - */
|
| - void _addPublicNames(CompilationUnitElement compilationUnit) {
|
| - compilationUnit.accessors.forEach(_addIfPublic);
|
| - compilationUnit.enums.forEach(_addIfPublic);
|
| - compilationUnit.functions.forEach(_addIfPublic);
|
| - compilationUnit.functionTypeAliases.forEach(_addIfPublic);
|
| - compilationUnit.types.forEach(_addIfPublic);
|
| + static ReadyLibraryElement2Task createTask(
|
| + AnalysisContext context, AnalysisTarget target) {
|
| + return new ReadyLibraryElement2Task(context, target);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A task that ensures that [LIBRARY_ELEMENT6] is ready for the target library
|
| + * source and its import/export closure.
|
| + */
|
| +class ReadyLibraryElement5Task extends SourceBasedAnalysisTask {
|
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| + 'ReadyLibraryElement5Task',
|
| + createTask,
|
| + buildInputs,
|
| + <ResultDescriptor>[READY_LIBRARY_ELEMENT6]);
|
| +
|
| + ReadyLibraryElement5Task(
|
| + InternalAnalysisContext context, AnalysisTarget target)
|
| + : super(context, target);
|
| +
|
| + @override
|
| + TaskDescriptor get descriptor => DESCRIPTOR;
|
| +
|
| + @override
|
| + bool get handlesDependencyCycles => true;
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + outputs[READY_LIBRARY_ELEMENT6] = true;
|
| + }
|
| +
|
| + static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| + Source source = target;
|
| + return <String, TaskInput>{
|
| + 'thisLibraryElementReady': LIBRARY_ELEMENT6.of(source),
|
| + 'directlyImportedLibrariesReady':
|
| + IMPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT6),
|
| + 'directlyExportedLibrariesReady':
|
| + EXPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT6),
|
| + };
|
| + }
|
| +
|
| + static ReadyLibraryElement5Task createTask(
|
| + AnalysisContext context, AnalysisTarget target) {
|
| + return new ReadyLibraryElement5Task(context, target);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A task that ensures that [LIBRARY_ELEMENT7] is ready for the target library
|
| + * source and its import/export closure.
|
| + */
|
| +class ReadyLibraryElement7Task extends SourceBasedAnalysisTask {
|
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| + 'ReadyLibraryElement7Task',
|
| + createTask,
|
| + buildInputs,
|
| + <ResultDescriptor>[READY_LIBRARY_ELEMENT7]);
|
| +
|
| + ReadyLibraryElement7Task(
|
| + InternalAnalysisContext context, AnalysisTarget target)
|
| + : super(context, target);
|
| +
|
| + @override
|
| + TaskDescriptor get descriptor => DESCRIPTOR;
|
| +
|
| + @override
|
| + bool get handlesDependencyCycles => true;
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + outputs[READY_LIBRARY_ELEMENT7] = true;
|
| + }
|
| +
|
| + static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| + Source source = target;
|
| + return <String, TaskInput>{
|
| + 'thisLibraryElementReady': LIBRARY_ELEMENT7.of(source),
|
| + 'directlyImportedLibrariesReady':
|
| + IMPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT7),
|
| + 'directlyExportedLibrariesReady':
|
| + EXPORTED_LIBRARIES.of(source).toListOf(READY_LIBRARY_ELEMENT7),
|
| + };
|
| + }
|
| +
|
| + static ReadyLibraryElement7Task createTask(
|
| + AnalysisContext context, AnalysisTarget target) {
|
| + return new ReadyLibraryElement7Task(context, target);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A task that ensures that [RESOLVED_UNIT] is ready for every unit of the
|
| + * target library source and its import/export closure.
|
| + */
|
| +class ReadyResolvedUnitTask extends SourceBasedAnalysisTask {
|
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| + 'ReadyResolvedUnitTask',
|
| + createTask,
|
| + buildInputs,
|
| + <ResultDescriptor>[READY_RESOLVED_UNIT]);
|
| +
|
| + ReadyResolvedUnitTask(InternalAnalysisContext context, AnalysisTarget target)
|
| + : super(context, target);
|
| +
|
| + @override
|
| + TaskDescriptor get descriptor => DESCRIPTOR;
|
| +
|
| + @override
|
| + bool get handlesDependencyCycles => true;
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + outputs[READY_RESOLVED_UNIT] = true;
|
| + }
|
| +
|
| + static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| + Source source = target;
|
| + return <String, TaskInput>{
|
| + 'thisLibraryUnitsReady':
|
| + LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT),
|
| + };
|
| + }
|
| +
|
| + static ReadyResolvedUnitTask createTask(
|
| + AnalysisContext context, AnalysisTarget target) {
|
| + return new ReadyResolvedUnitTask(context, target);
|
| }
|
| }
|
|
|
| /**
|
| - * Information about a library - which names it uses, which names it defines
|
| - * with their externally visible dependencies.
|
| + * Information about a Dart [source] - which names it uses, which names it
|
| + * defines with their externally visible dependencies.
|
| */
|
| class ReferencedNames {
|
| - final Set<String> names = new Set<String>();
|
| - final Map<String, Set<String>> userToDependsOn = <String, Set<String>>{};
|
| + final Source source;
|
|
|
| /**
|
| - * Updates [delta] by adding names that are changed in this library.
|
| + * The mapping from the name of a class to the set of names of other classes
|
| + * that extend, mix-in, or implement it.
|
| + *
|
| + * If the set of member of a class is changed, these changes might change
|
| + * the list of unimplemented inherited members in the class and classes that
|
| + * extend, mix-in, or implement it. So, we might need to report (or stop
|
| + * reporting) the corresponding warning.
|
| */
|
| - void addChangedElements(DartDelta delta) {
|
| - bool hasProgress = true;
|
| - while (hasProgress) {
|
| - hasProgress = false;
|
| - userToDependsOn.forEach((user, dependencies) {
|
| - for (String dependency in dependencies) {
|
| - if (delta.isNameAffected(dependency)) {
|
| - if (delta.nameChanged(user)) {
|
| - hasProgress = true;
|
| - }
|
| - }
|
| - }
|
| - });
|
| - }
|
| - }
|
| + final Map<String, Set<String>> superToSubs = <String, Set<String>>{};
|
|
|
| /**
|
| - * Returns `true` if the library described by this object is affected by
|
| - * the given [delta].
|
| + * The names of extended classes for which the unnamed constructor is
|
| + * invoked. Because we cannot use the name of the constructor to identify
|
| + * whether the unit is affected, we need to use the class name.
|
| */
|
| - bool isAffectedBy(DartDelta delta) {
|
| - for (String name in names) {
|
| - if (delta.isNameAffected(name)) {
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| + final Set<String> extendedUsedUnnamedConstructorNames = new Set<String>();
|
| +
|
| + /**
|
| + * The names of instantiated classes.
|
| + *
|
| + * If one of these classes changes its set of members, it might change
|
| + * its list of unimplemented inherited members. So, we might need to report
|
| + * (or stop reporting) the corresponding warning.
|
| + */
|
| + final Set<String> instantiatedNames = new Set<String>();
|
| +
|
| + /**
|
| + * The set of names that are referenced by the library, both inside and
|
| + * outside of method bodies.
|
| + */
|
| + final Set<String> names = new Set<String>();
|
| +
|
| + /**
|
| + * The mapping from the name of a top-level element to the set of names that
|
| + * the element uses in a way that is visible outside of the element, e.g.
|
| + * the return type, or a parameter type.
|
| + */
|
| + final Map<String, Set<String>> userToDependsOn = <String, Set<String>>{};
|
| +
|
| + ReferencedNames(this.source);
|
| +
|
| + void addSubclass(String subName, String superName) {
|
| + superToSubs.putIfAbsent(superName, () => new Set<String>()).add(subName);
|
| }
|
| }
|
|
|
| /**
|
| * A builder for creating [ReferencedNames].
|
| - *
|
| - * TODO(scheglov) Record dependencies for all other top-level declarations.
|
| */
|
| -class ReferencedNamesBuilder extends RecursiveAstVisitor {
|
| +class ReferencedNamesBuilder extends GeneralizingAstVisitor {
|
| + final Set<String> importPrefixNames = new Set<String>();
|
| final ReferencedNames names;
|
| - int bodyLevel = 0;
|
| +
|
| + String enclosingSuperClassName;
|
| + ReferencedNamesScope scope = new ReferencedNamesScope(null);
|
| +
|
| + int localLevel = 0;
|
| Set<String> dependsOn;
|
|
|
| ReferencedNamesBuilder(this.names);
|
| @@ -3538,62 +4554,594 @@ class ReferencedNamesBuilder extends RecursiveAstVisitor {
|
| }
|
|
|
| @override
|
| - visitBlockFunctionBody(BlockFunctionBody node) {
|
| + visitBlock(Block node) {
|
| + ReferencedNamesScope outerScope = scope;
|
| try {
|
| - bodyLevel++;
|
| - super.visitBlockFunctionBody(node);
|
| + scope = new ReferencedNamesScope.forBlock(scope, node);
|
| + super.visitBlock(node);
|
| } finally {
|
| - bodyLevel--;
|
| + scope = outerScope;
|
| }
|
| }
|
|
|
| @override
|
| visitClassDeclaration(ClassDeclaration node) {
|
| - dependsOn = new Set<String>();
|
| - super.visitClassDeclaration(node);
|
| - names.userToDependsOn[node.name.name] = dependsOn;
|
| - dependsOn = null;
|
| + ReferencedNamesScope outerScope = scope;
|
| + try {
|
| + scope = new ReferencedNamesScope.forClass(scope, node);
|
| + dependsOn = new Set<String>();
|
| + enclosingSuperClassName =
|
| + _getSimpleName(node.extendsClause?.superclass?.name);
|
| + super.visitClassDeclaration(node);
|
| + String className = node.name.name;
|
| + names.userToDependsOn[className] = dependsOn;
|
| + _addSuperName(className, node.extendsClause?.superclass);
|
| + _addSuperNames(className, node.withClause?.mixinTypes);
|
| + _addSuperNames(className, node.implementsClause?.interfaces);
|
| + } finally {
|
| + enclosingSuperClassName = null;
|
| + dependsOn = null;
|
| + scope = outerScope;
|
| + }
|
| }
|
|
|
| @override
|
| - visitExpressionFunctionBody(ExpressionFunctionBody node) {
|
| + visitClassTypeAlias(ClassTypeAlias node) {
|
| + ReferencedNamesScope outerScope = scope;
|
| try {
|
| - bodyLevel++;
|
| - super.visitExpressionFunctionBody(node);
|
| + scope = new ReferencedNamesScope.forClassTypeAlias(scope, node);
|
| + dependsOn = new Set<String>();
|
| + super.visitClassTypeAlias(node);
|
| + String className = node.name.name;
|
| + names.userToDependsOn[className] = dependsOn;
|
| + _addSuperName(className, node.superclass);
|
| + _addSuperNames(className, node.withClause?.mixinTypes);
|
| + _addSuperNames(className, node.implementsClause?.interfaces);
|
| } finally {
|
| - bodyLevel--;
|
| + dependsOn = null;
|
| + scope = outerScope;
|
| }
|
| }
|
|
|
| @override
|
| - visitSimpleIdentifier(SimpleIdentifier node) {
|
| - if (!node.inDeclarationContext()) {
|
| - String name = node.name;
|
| - names.names.add(name);
|
| - if (dependsOn != null && bodyLevel == 0) {
|
| - dependsOn.add(name);
|
| - }
|
| + visitComment(Comment node) {
|
| + try {
|
| + localLevel++;
|
| + super.visitComment(node);
|
| + } finally {
|
| + localLevel--;
|
| }
|
| }
|
| -}
|
| -
|
| -/**
|
| - * A task that ensures that all of the inferrable instance members in a
|
| - * compilation unit have had their right hand sides re-resolved
|
| - */
|
| -class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask {
|
| - /**
|
| - * The name of the [LIBRARY_ELEMENT5] input.
|
| - */
|
| - static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
|
|
|
| - /**
|
| + @override
|
| + visitConstructorName(ConstructorName node) {
|
| + if (node.parent is! ConstructorDeclaration) {
|
| + super.visitConstructorName(node);
|
| + }
|
| + }
|
| +
|
| + @override
|
| + visitFunctionBody(FunctionBody node) {
|
| + try {
|
| + localLevel++;
|
| + super.visitFunctionBody(node);
|
| + } finally {
|
| + localLevel--;
|
| + }
|
| + }
|
| +
|
| + @override
|
| + visitFunctionDeclaration(FunctionDeclaration node) {
|
| + if (localLevel == 0) {
|
| + ReferencedNamesScope outerScope = scope;
|
| + try {
|
| + scope = new ReferencedNamesScope.forFunction(scope, node);
|
| + dependsOn = new Set<String>();
|
| + super.visitFunctionDeclaration(node);
|
| + names.userToDependsOn[node.name.name] = dependsOn;
|
| + } finally {
|
| + dependsOn = null;
|
| + scope = outerScope;
|
| + }
|
| + } else {
|
| + super.visitFunctionDeclaration(node);
|
| + }
|
| + }
|
| +
|
| + @override
|
| + visitFunctionTypeAlias(FunctionTypeAlias node) {
|
| + if (localLevel == 0) {
|
| + ReferencedNamesScope outerScope = scope;
|
| + try {
|
| + scope = new ReferencedNamesScope.forFunctionTypeAlias(scope, node);
|
| + dependsOn = new Set<String>();
|
| + super.visitFunctionTypeAlias(node);
|
| + names.userToDependsOn[node.name.name] = dependsOn;
|
| + } finally {
|
| + dependsOn = null;
|
| + scope = outerScope;
|
| + }
|
| + } else {
|
| + super.visitFunctionTypeAlias(node);
|
| + }
|
| + }
|
| +
|
| + @override
|
| + visitImportDirective(ImportDirective node) {
|
| + if (node.prefix != null) {
|
| + importPrefixNames.add(node.prefix.name);
|
| + }
|
| + super.visitImportDirective(node);
|
| + }
|
| +
|
| + @override
|
| + visitInstanceCreationExpression(InstanceCreationExpression node) {
|
| + ConstructorName constructorName = node.constructorName;
|
| + Identifier typeName = constructorName.type.name;
|
| + if (typeName is SimpleIdentifier) {
|
| + names.instantiatedNames.add(typeName.name);
|
| + }
|
| + if (typeName is PrefixedIdentifier) {
|
| + String prefixName = typeName.prefix.name;
|
| + if (importPrefixNames.contains(prefixName)) {
|
| + names.instantiatedNames.add(typeName.identifier.name);
|
| + } else {
|
| + names.instantiatedNames.add(prefixName);
|
| + }
|
| + }
|
| + super.visitInstanceCreationExpression(node);
|
| + }
|
| +
|
| + @override
|
| + visitMethodDeclaration(MethodDeclaration node) {
|
| + ReferencedNamesScope outerScope = scope;
|
| + try {
|
| + scope = new ReferencedNamesScope.forMethod(scope, node);
|
| + super.visitMethodDeclaration(node);
|
| + } finally {
|
| + scope = outerScope;
|
| + }
|
| + }
|
| +
|
| + @override
|
| + visitSimpleIdentifier(SimpleIdentifier node) {
|
| + // Ignore all declarations.
|
| + if (node.inDeclarationContext()) {
|
| + return;
|
| + }
|
| + // Ignore class names references from constructors.
|
| + AstNode parent = node.parent;
|
| + if (parent is ConstructorDeclaration && parent.returnType == node) {
|
| + return;
|
| + }
|
| + // Prepare name.
|
| + String name = node.name;
|
| + // Ignore unqualified names shadowed by local elements.
|
| + if (!node.isQualified) {
|
| + if (scope.contains(name)) {
|
| + return;
|
| + }
|
| + if (importPrefixNames.contains(name)) {
|
| + return;
|
| + }
|
| + }
|
| + // Do add the dependency.
|
| + names.names.add(name);
|
| + if (dependsOn != null && localLevel == 0) {
|
| + dependsOn.add(name);
|
| + }
|
| + }
|
| +
|
| + @override
|
| + visitSuperConstructorInvocation(SuperConstructorInvocation node) {
|
| + if (node.constructorName == null && enclosingSuperClassName != null) {
|
| + names.extendedUsedUnnamedConstructorNames.add(enclosingSuperClassName);
|
| + }
|
| + super.visitSuperConstructorInvocation(node);
|
| + }
|
| +
|
| + @override
|
| + visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
|
| + VariableDeclarationList variableList = node.variables;
|
| + // Prepare type dependencies.
|
| + Set<String> typeDependencies = new Set<String>();
|
| + dependsOn = typeDependencies;
|
| + variableList.type?.accept(this);
|
| + // Combine individual variable dependencies with the type dependencies.
|
| + for (VariableDeclaration variable in variableList.variables) {
|
| + dependsOn = new Set<String>();
|
| + variable.accept(this);
|
| + dependsOn.addAll(typeDependencies);
|
| + names.userToDependsOn[variable.name.name] = dependsOn;
|
| + }
|
| + dependsOn = null;
|
| + }
|
| +
|
| + void _addSuperName(String className, TypeName type) {
|
| + if (type != null) {
|
| + Identifier typeName = type.name;
|
| + if (typeName is SimpleIdentifier) {
|
| + names.addSubclass(className, typeName.name);
|
| + }
|
| + if (typeName is PrefixedIdentifier) {
|
| + names.addSubclass(className, typeName.identifier.name);
|
| + }
|
| + }
|
| + }
|
| +
|
| + void _addSuperNames(String className, List<TypeName> types) {
|
| + types?.forEach((type) => _addSuperName(className, type));
|
| + }
|
| +
|
| + static String _getSimpleName(Identifier identifier) {
|
| + if (identifier is SimpleIdentifier) {
|
| + return identifier.name;
|
| + }
|
| + if (identifier is PrefixedIdentifier) {
|
| + return identifier.identifier.name;
|
| + }
|
| + return null;
|
| + }
|
| +}
|
| +
|
| +class ReferencedNamesScope {
|
| + final ReferencedNamesScope enclosing;
|
| + Set<String> names;
|
| +
|
| + ReferencedNamesScope(this.enclosing);
|
| +
|
| + factory ReferencedNamesScope.forBlock(
|
| + ReferencedNamesScope enclosing, Block node) {
|
| + ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
|
| + for (Statement statement in node.statements) {
|
| + if (statement is FunctionDeclarationStatement) {
|
| + scope.add(statement.functionDeclaration.name.name);
|
| + } else if (statement is VariableDeclarationStatement) {
|
| + for (VariableDeclaration variable in statement.variables.variables) {
|
| + scope.add(variable.name.name);
|
| + }
|
| + }
|
| + }
|
| + return scope;
|
| + }
|
| +
|
| + factory ReferencedNamesScope.forClass(
|
| + ReferencedNamesScope enclosing, ClassDeclaration node) {
|
| + ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
|
| + scope._addTypeParameters(node.typeParameters);
|
| + for (ClassMember member in node.members) {
|
| + if (member is FieldDeclaration) {
|
| + for (VariableDeclaration variable in member.fields.variables) {
|
| + scope.add(variable.name.name);
|
| + }
|
| + } else if (member is MethodDeclaration) {
|
| + scope.add(member.name.name);
|
| + }
|
| + }
|
| + return scope;
|
| + }
|
| +
|
| + factory ReferencedNamesScope.forClassTypeAlias(
|
| + ReferencedNamesScope enclosing, ClassTypeAlias node) {
|
| + ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
|
| + scope._addTypeParameters(node.typeParameters);
|
| + return scope;
|
| + }
|
| +
|
| + factory ReferencedNamesScope.forFunction(
|
| + ReferencedNamesScope enclosing, FunctionDeclaration node) {
|
| + ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
|
| + scope._addTypeParameters(node.functionExpression.typeParameters);
|
| + scope._addFormalParameters(node.functionExpression.parameters);
|
| + return scope;
|
| + }
|
| +
|
| + factory ReferencedNamesScope.forFunctionTypeAlias(
|
| + ReferencedNamesScope enclosing, FunctionTypeAlias node) {
|
| + ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
|
| + scope._addTypeParameters(node.typeParameters);
|
| + return scope;
|
| + }
|
| +
|
| + factory ReferencedNamesScope.forMethod(
|
| + ReferencedNamesScope enclosing, MethodDeclaration node) {
|
| + ReferencedNamesScope scope = new ReferencedNamesScope(enclosing);
|
| + scope._addTypeParameters(node.typeParameters);
|
| + scope._addFormalParameters(node.parameters);
|
| + return scope;
|
| + }
|
| +
|
| + void add(String name) {
|
| + names ??= new Set<String>();
|
| + names.add(name);
|
| + }
|
| +
|
| + bool contains(String name) {
|
| + if (names != null && names.contains(name)) {
|
| + return true;
|
| + }
|
| + if (enclosing != null) {
|
| + return enclosing.contains(name);
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + void _addFormalParameters(FormalParameterList parameterList) {
|
| + if (parameterList != null) {
|
| + parameterList.parameters
|
| + .map((p) => p is NormalFormalParameter ? p.identifier.name : '')
|
| + .forEach(add);
|
| + }
|
| + }
|
| +
|
| + void _addTypeParameters(TypeParameterList typeParameterList) {
|
| + if (typeParameterList != null) {
|
| + typeParameterList.typeParameters.map((p) => p.name.name).forEach(add);
|
| + }
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A task that ensures that the expression AST for a constant is resolved and
|
| + * sets the [CONSTANT_EXPRESSION_RESOLVED] result.
|
| + */
|
| +class ResolveConstantExpressionTask extends ConstantEvaluationAnalysisTask {
|
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| + 'ResolveConstantExpressionTask',
|
| + createTask,
|
| + buildInputs,
|
| + <ResultDescriptor>[CONSTANT_EXPRESSION_RESOLVED]);
|
| +
|
| + ResolveConstantExpressionTask(
|
| + InternalAnalysisContext context, ConstantEvaluationTarget constant)
|
| + : super(context, constant);
|
| +
|
| + @override
|
| + TaskDescriptor get descriptor => DESCRIPTOR;
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + //
|
| + // Record outputs.
|
| + //
|
| + outputs[CONSTANT_EXPRESSION_RESOLVED] = true;
|
| + }
|
| +
|
| + /**
|
| + * 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) {
|
| + Source librarySource;
|
| + if (target is Element) {
|
| + CompilationUnitElementImpl unit = target
|
| + .getAncestor((Element element) => element is CompilationUnitElement);
|
| + librarySource = unit.librarySource;
|
| + } else if (target is ElementAnnotationImpl) {
|
| + librarySource = target.librarySource;
|
| + } else {
|
| + throw new AnalysisException(
|
| + 'Cannot build inputs for a ${target.runtimeType}');
|
| + }
|
| + return <String, TaskInput>{
|
| + 'createdResolvedUnit': CREATED_RESOLVED_UNIT11
|
| + .of(new LibrarySpecificUnit(librarySource, target.source))
|
| + };
|
| + }
|
| +
|
| + /**
|
| + * Create a [ResolveConstantExpressionTask] based on the given [target] in
|
| + * the given [context].
|
| + */
|
| + static ResolveConstantExpressionTask createTask(
|
| + AnalysisContext context, AnalysisTarget target) {
|
| + return new ResolveConstantExpressionTask(context, target);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A task that resolves imports and export directives to already built elements.
|
| + */
|
| +class ResolveDirectiveElementsTask extends SourceBasedAnalysisTask {
|
| + /**
|
| + * The name of the input whose value is the defining [LIBRARY_ELEMENT2].
|
| + */
|
| + static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
|
| +
|
| + /**
|
| + * The name of the input for [RESOLVED_UNIT1] of a unit.
|
| + */
|
| + static const String UNIT_INPUT = 'UNIT_INPUT';
|
| +
|
| + /**
|
| + * The task descriptor describing this kind of task.
|
| + */
|
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| + 'ResolveDirectiveElementsTask',
|
| + createTask,
|
| + buildInputs,
|
| + <ResultDescriptor>[CREATED_RESOLVED_UNIT2, RESOLVED_UNIT2]);
|
| +
|
| + ResolveDirectiveElementsTask(
|
| + InternalAnalysisContext context, AnalysisTarget target)
|
| + : super(context, target);
|
| +
|
| + @override
|
| + TaskDescriptor get descriptor => DESCRIPTOR;
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + LibrarySpecificUnit targetUnit = target;
|
| + //
|
| + // Prepare inputs.
|
| + //
|
| + CompilationUnit unit = getRequiredInput(UNIT_INPUT);
|
| + //
|
| + // Resolve directive AST nodes to elements.
|
| + //
|
| + if (targetUnit.unit == targetUnit.library) {
|
| + DirectiveResolver resolver = new DirectiveResolver();
|
| + unit.accept(resolver);
|
| + }
|
| + //
|
| + // Record outputs.
|
| + //
|
| + outputs[CREATED_RESOLVED_UNIT2] = true;
|
| + outputs[RESOLVED_UNIT2] = 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>{
|
| + LIBRARY_INPUT: LIBRARY_ELEMENT2.of(unit.library),
|
| + UNIT_INPUT: RESOLVED_UNIT1.of(unit)
|
| + };
|
| + }
|
| +
|
| + /**
|
| + * Create a [ResolveDirectiveElementsTask] based on the given [target] in
|
| + * the given [context].
|
| + */
|
| + static ResolveDirectiveElementsTask createTask(
|
| + AnalysisContext context, AnalysisTarget target) {
|
| + return new ResolveDirectiveElementsTask(context, target);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * An artificial task that does nothing except to force [LIBRARY_ELEMENT7] for
|
| + * the target library and its import/export closure.
|
| + */
|
| +class ResolvedUnit7InLibraryClosureTask extends SourceBasedAnalysisTask {
|
| + /**
|
| + * The name of the [LIBRARY_ELEMENT7] input.
|
| + */
|
| + static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
|
| +
|
| + /**
|
| + * The task descriptor describing this kind of task.
|
| + */
|
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| + 'ResolvedUnit7InLibraryClosureTask',
|
| + createTask,
|
| + buildInputs,
|
| + <ResultDescriptor>[LIBRARY_ELEMENT8]);
|
| +
|
| + ResolvedUnit7InLibraryClosureTask(
|
| + InternalAnalysisContext context, AnalysisTarget target)
|
| + : super(context, target);
|
| +
|
| + @override
|
| + TaskDescriptor get descriptor => DESCRIPTOR;
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + LibraryElement library = getRequiredInput(LIBRARY_INPUT);
|
| + outputs[LIBRARY_ELEMENT8] = library;
|
| + }
|
| +
|
| + /**
|
| + * 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) {
|
| + Source source = target;
|
| + return <String, TaskInput>{
|
| + 'readyForClosure': READY_LIBRARY_ELEMENT7.of(source),
|
| + LIBRARY_INPUT: LIBRARY_ELEMENT7.of(source),
|
| + };
|
| + }
|
| +
|
| + /**
|
| + * Create a [ResolvedUnit7InLibraryClosureTask] based on the given
|
| + * [target] in the given [context].
|
| + */
|
| + static ResolvedUnit7InLibraryClosureTask createTask(
|
| + AnalysisContext context, AnalysisTarget target) {
|
| + return new ResolvedUnit7InLibraryClosureTask(context, target);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * An artificial task that does nothing except to force [LIBRARY_ELEMENT6] and
|
| + * [RESOLVED_UNIT7] in the defining and part units of a library.
|
| + */
|
| +class ResolvedUnit7InLibraryTask extends SourceBasedAnalysisTask {
|
| + /**
|
| + * The name of the [LIBRARY_ELEMENT6] input.
|
| + */
|
| + static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
|
| +
|
| + /**
|
| + * The task descriptor describing this kind of task.
|
| + */
|
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| + 'ResolvedUnit7InLibraryTask',
|
| + createTask,
|
| + buildInputs,
|
| + <ResultDescriptor>[LIBRARY_ELEMENT7]);
|
| +
|
| + ResolvedUnit7InLibraryTask(
|
| + InternalAnalysisContext context, AnalysisTarget target)
|
| + : super(context, target);
|
| +
|
| + @override
|
| + TaskDescriptor get descriptor => DESCRIPTOR;
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + LibraryElement library = getRequiredInput(LIBRARY_INPUT);
|
| + outputs[LIBRARY_ELEMENT7] = library;
|
| + }
|
| +
|
| + /**
|
| + * 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) {
|
| + Source source = target;
|
| + return <String, TaskInput>{
|
| + 'resolvedUnits':
|
| + LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT7),
|
| + LIBRARY_INPUT: LIBRARY_ELEMENT6.of(source),
|
| + };
|
| + }
|
| +
|
| + /**
|
| + * Create a [ResolvedUnit7InLibraryTask] based on the given [target]
|
| + * in the given [context].
|
| + */
|
| + static ResolvedUnit7InLibraryTask createTask(
|
| + AnalysisContext context, AnalysisTarget target) {
|
| + return new ResolvedUnit7InLibraryTask(context, target);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A task that ensures that all of the inferable instance members in a
|
| + * compilation unit have had their right hand sides re-resolved
|
| + */
|
| +class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask {
|
| + /**
|
| + * The name of the [LIBRARY_ELEMENT6] input.
|
| + */
|
| + static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
|
| +
|
| + /**
|
| * The name of the [TYPE_PROVIDER] input.
|
| */
|
| 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_UNIT8] for the
|
| * compilation unit.
|
| */
|
| static const String UNIT_INPUT = 'UNIT_INPUT';
|
| @@ -3605,7 +5153,7 @@ class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask {
|
| 'ResolveInstanceFieldsInUnitTask',
|
| createTask,
|
| buildInputs,
|
| - <ResultDescriptor>[RESOLVED_UNIT7]);
|
| + <ResultDescriptor>[CREATED_RESOLVED_UNIT9, RESOLVED_UNIT9]);
|
|
|
| /**
|
| * Initialize a newly created task to build a library element for the given
|
| @@ -3623,124 +5171,292 @@ class ResolveInstanceFieldsInUnitTask extends SourceBasedAnalysisTask {
|
| //
|
| // Prepare inputs.
|
| //
|
| - LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
|
| - CompilationUnit unit = getRequiredInput(UNIT_INPUT);
|
| + LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
|
| + CompilationUnit unit = getRequiredInput(UNIT_INPUT);
|
| + TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
|
| +
|
| + CompilationUnitElement unitElement = unit.element;
|
| + if (context.analysisOptions.strongMode) {
|
| + //
|
| + // Resolve references.
|
| + //
|
| + InstanceFieldResolverVisitor visitor = new InstanceFieldResolverVisitor(
|
| + libraryElement,
|
| + unitElement.source,
|
| + typeProvider,
|
| + AnalysisErrorListener.NULL_LISTENER);
|
| + visitor.resolveCompilationUnit(unit);
|
| + }
|
| + //
|
| + // Record outputs.
|
| + //
|
| + outputs[RESOLVED_UNIT9] = unit;
|
| + outputs[CREATED_RESOLVED_UNIT9] = true;
|
| + }
|
| +
|
| + /**
|
| + * 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
|
| + * [libSource].
|
| + */
|
| + static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| + LibrarySpecificUnit unit = target;
|
| + return <String, TaskInput>{
|
| + UNIT_INPUT: RESOLVED_UNIT8.of(unit),
|
| + LIBRARY_INPUT: LIBRARY_ELEMENT6.of(unit.library),
|
| + TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
|
| + // In strong mode, add additional dependencies to enforce inference
|
| + // ordering.
|
| +
|
| + // Require that static variable inference be complete for all units in
|
| + // the current library cycle.
|
| + 'orderLibraryCycleTasks':
|
| + LIBRARY_CYCLE_UNITS.of(unit.library).toListOf(CREATED_RESOLVED_UNIT8),
|
| + // Require that full inference be complete for all dependencies of the
|
| + // current library cycle.
|
| + 'orderLibraryCycles': LIBRARY_CYCLE_DEPENDENCIES
|
| + .of(unit.library)
|
| + .toListOf(CREATED_RESOLVED_UNIT10)
|
| + };
|
| + }
|
| +
|
| + /**
|
| + * Create a [ResolveInstanceFieldsInUnitTask] based on the given [target] in
|
| + * the given [context].
|
| + */
|
| + static ResolveInstanceFieldsInUnitTask createTask(
|
| + AnalysisContext context, AnalysisTarget target) {
|
| + return new ResolveInstanceFieldsInUnitTask(context, target);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A task that finishes resolution by requesting [RESOLVED_UNIT11] for every
|
| + * unit in the libraries closure and produces [LIBRARY_ELEMENT9].
|
| + */
|
| +class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask {
|
| + /**
|
| + * The name of the [LIBRARY_ELEMENT8] input.
|
| + */
|
| + static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
|
| +
|
| + /**
|
| + * The task descriptor describing this kind of task.
|
| + */
|
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| + 'ResolveLibraryReferencesTask',
|
| + createTask,
|
| + buildInputs,
|
| + <ResultDescriptor>[LIBRARY_ELEMENT9]);
|
| +
|
| + ResolveLibraryReferencesTask(
|
| + InternalAnalysisContext context, AnalysisTarget target)
|
| + : super(context, target);
|
| +
|
| + @override
|
| + TaskDescriptor get descriptor => DESCRIPTOR;
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + LibraryElement library = getRequiredInput(LIBRARY_INPUT);
|
| + outputs[LIBRARY_ELEMENT9] = library;
|
| + }
|
| +
|
| + /**
|
| + * 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) {
|
| + Source source = target;
|
| + return <String, TaskInput>{
|
| + LIBRARY_INPUT: LIBRARY_ELEMENT8.of(source),
|
| + 'resolvedUnits':
|
| + LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT11),
|
| + };
|
| + }
|
| +
|
| + /**
|
| + * Create a [ResolveLibraryReferencesTask] based on the given [target] in
|
| + * the given [context].
|
| + */
|
| + static ResolveLibraryReferencesTask createTask(
|
| + AnalysisContext context, AnalysisTarget target) {
|
| + return new ResolveLibraryReferencesTask(context, target);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A task that finishes resolution by requesting [RESOLVED_UNIT12] for every
|
| + * unit in the libraries closure and produces [LIBRARY_ELEMENT].
|
| + */
|
| +class ResolveLibraryTask extends SourceBasedAnalysisTask {
|
| + /**
|
| + * The name of the [LIBRARY_ELEMENT9] input.
|
| + */
|
| + static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
|
| +
|
| + /**
|
| + * The name of the list of [RESOLVED_UNIT12] input.
|
| + */
|
| + static const String UNITS_INPUT = 'UNITS_INPUT';
|
| +
|
| + /**
|
| + * The task descriptor describing this kind of task.
|
| + */
|
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| + 'ResolveLibraryTask',
|
| + createTask,
|
| + buildInputs,
|
| + <ResultDescriptor>[LIBRARY_ELEMENT]);
|
| +
|
| + ResolveLibraryTask(InternalAnalysisContext context, AnalysisTarget target)
|
| + : super(context, target);
|
| +
|
| + @override
|
| + TaskDescriptor get descriptor => DESCRIPTOR;
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + //
|
| + // Prepare inputs.
|
| + //
|
| + LibraryElement library = getRequiredInput(LIBRARY_INPUT);
|
| + //
|
| + // Record outputs.
|
| + //
|
| + outputs[LIBRARY_ELEMENT] = library;
|
| + }
|
| +
|
| +/**
|
| + * 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) {
|
| + Source source = target;
|
| + return <String, TaskInput>{
|
| + LIBRARY_INPUT: LIBRARY_ELEMENT9.of(source),
|
| + 'thisLibraryClosureIsReady': READY_RESOLVED_UNIT.of(source),
|
| + };
|
| + }
|
| +
|
| +/**
|
| + * Create a [ResolveLibraryTask] based on the given [target] in the given
|
| + * [context].
|
| + */
|
| + static ResolveLibraryTask createTask(
|
| + AnalysisContext context, AnalysisTarget target) {
|
| + return new ResolveLibraryTask(context, target);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * An artificial task that does nothing except to force type names resolution
|
| + * for the defining and part units of a library.
|
| + */
|
| +class ResolveLibraryTypeNamesTask extends SourceBasedAnalysisTask {
|
| + /**
|
| + * The name of the [LIBRARY_ELEMENT5] input.
|
| + */
|
| + static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
|
| +
|
| + /**
|
| + * The name of the [TYPE_PROVIDER] input.
|
| + */
|
| + static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
|
| +
|
| + /**
|
| + * The task descriptor describing this kind of task.
|
| + */
|
| + static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| + 'ResolveLibraryTypeNamesTask',
|
| + createTask,
|
| + buildInputs,
|
| + <ResultDescriptor>[LIBRARY_ELEMENT6]);
|
| +
|
| + ResolveLibraryTypeNamesTask(
|
| + InternalAnalysisContext context, AnalysisTarget target)
|
| + : super(context, target);
|
| +
|
| + @override
|
| + TaskDescriptor get descriptor => DESCRIPTOR;
|
| +
|
| + @override
|
| + void internalPerform() {
|
| + //
|
| + // Prepare inputs.
|
| + //
|
| + LibraryElement library = getRequiredInput(LIBRARY_INPUT);
|
| TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
|
| -
|
| - CompilationUnitElement unitElement = unit.element;
|
| - if (context.analysisOptions.strongMode) {
|
| - //
|
| - // Resolve references.
|
| - //
|
| - // TODO(leafp): This code only needs to re-resolve the right hand sides of
|
| - // instance fields. We could do incremental resolution on each field
|
| - // only using the incremental resolver. However, this caused a massive
|
| - // performance degredation on the large_class_declaration_test.dart test.
|
| - // I would hypothesize that incremental resolution of field is linear in
|
| - // the size of the enclosing class, and hence incrementally resolving each
|
| - // field was quadratic. We may wish to revisit this if we can resolve
|
| - // this performance issue.
|
| - InheritanceManager inheritanceManager =
|
| - new InheritanceManager(libraryElement);
|
| - PartialResolverVisitor visitor = new PartialResolverVisitor(
|
| - libraryElement,
|
| - unitElement.source,
|
| - typeProvider,
|
| - AnalysisErrorListener.NULL_LISTENER,
|
| - inheritanceManager: inheritanceManager);
|
| - unit.accept(visitor);
|
| - }
|
| + //
|
| + // Create the synthetic element for `loadLibrary`.
|
| + //
|
| + (library as LibraryElementImpl).createLoadLibraryFunction(typeProvider);
|
| //
|
| // Record outputs.
|
| //
|
| - outputs[RESOLVED_UNIT7] = unit;
|
| + outputs[LIBRARY_ELEMENT6] = library;
|
| }
|
|
|
| /**
|
| * 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
|
| - * [libSource].
|
| + * input descriptors describing those inputs for a task with the
|
| + * given [target].
|
| */
|
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| - LibrarySpecificUnit unit = target;
|
| + Source source = target;
|
| return <String, TaskInput>{
|
| - UNIT_INPUT: RESOLVED_UNIT6.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
|
| - // ordering.
|
| -
|
| - // 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
|
| - .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
|
| - .of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
|
| + 'resolvedUnit':
|
| + LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT5),
|
| + LIBRARY_INPUT: LIBRARY_ELEMENT5.of(source),
|
| + TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
|
| };
|
| }
|
|
|
| /**
|
| - * Create a [ResolveInstanceFieldsInUnitTask] based on the given [target] in
|
| + * Create a [ResolveLibraryTypeNamesTask] based on the given [target] in
|
| * the given [context].
|
| */
|
| - static ResolveInstanceFieldsInUnitTask createTask(
|
| + static ResolveLibraryTypeNamesTask createTask(
|
| AnalysisContext context, AnalysisTarget target) {
|
| - return new ResolveInstanceFieldsInUnitTask(context, target);
|
| + return new ResolveLibraryTypeNamesTask(context, target);
|
| }
|
| }
|
|
|
| /**
|
| - * A task that finishes resolution by requesting [RESOLVED_UNIT_NO_CONSTANTS] for every
|
| - * unit in the libraries closure and produces [LIBRARY_ELEMENT].
|
| + * An artificial task that does nothing except to force type parameter bounds
|
| + * type names resolution for the defining and part units of a library.
|
| */
|
| -class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask {
|
| +class ResolveTopLevelLibraryTypeBoundsTask extends SourceBasedAnalysisTask {
|
| /**
|
| - * The name of the [LIBRARY_ELEMENT5] input.
|
| + * The name of the [LIBRARY_ELEMENT4] input.
|
| */
|
| static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
|
|
|
| - /**
|
| - * The name of the list of [RESOLVED_UNIT9] input.
|
| - */
|
| - static const String UNITS_INPUT = 'UNITS_INPUT';
|
| -
|
| /**
|
| * The task descriptor describing this kind of task.
|
| */
|
| static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| - 'ResolveLibraryReferencesTask',
|
| + 'ResolveTopLevelLibraryTypeBoundsTask',
|
| createTask,
|
| buildInputs,
|
| - <ResultDescriptor>[LIBRARY_ELEMENT, REFERENCED_NAMES]);
|
| + <ResultDescriptor>[LIBRARY_ELEMENT5]);
|
|
|
| - ResolveLibraryReferencesTask(
|
| + ResolveTopLevelLibraryTypeBoundsTask(
|
| InternalAnalysisContext context, AnalysisTarget target)
|
| : super(context, target);
|
|
|
| @override
|
| TaskDescriptor get descriptor => DESCRIPTOR;
|
|
|
| + @override
|
| + bool get handlesDependencyCycles => true;
|
| +
|
| @override
|
| void internalPerform() {
|
| - //
|
| - // Prepare inputs.
|
| - //
|
| LibraryElement library = getRequiredInput(LIBRARY_INPUT);
|
| - List<CompilationUnit> units = getRequiredInput(UNITS_INPUT);
|
| - // Compute referenced names.
|
| - ReferencedNames referencedNames = new ReferencedNames();
|
| - for (CompilationUnit unit in units) {
|
| - new ReferencedNamesBuilder(referencedNames).build(unit);
|
| - }
|
| - //
|
| - // Record outputs.
|
| - //
|
| - outputs[LIBRARY_ELEMENT] = library;
|
| - outputs[REFERENCED_NAMES] = referencedNames;
|
| + outputs[LIBRARY_ELEMENT5] = library;
|
| }
|
|
|
| /**
|
| @@ -3751,47 +5467,58 @@ class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask {
|
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| Source source = target;
|
| return <String, TaskInput>{
|
| - LIBRARY_INPUT: LIBRARY_ELEMENT5.of(source),
|
| - UNITS_INPUT: UNITS.of(source).toList((Source unit) =>
|
| - RESOLVED_UNIT9.of(new LibrarySpecificUnit(source, unit))),
|
| - 'resolvedUnits': IMPORT_EXPORT_SOURCE_CLOSURE
|
| - .of(source)
|
| - .toMapOf(UNITS)
|
| - .toFlattenList((Source library, Source unit) =>
|
| - RESOLVED_UNIT9.of(new LibrarySpecificUnit(library, unit))),
|
| + LIBRARY_INPUT: LIBRARY_ELEMENT4.of(source),
|
| + 'thisLibraryUnitsReady':
|
| + LIBRARY_SPECIFIC_UNITS.of(source).toListOf(RESOLVED_UNIT4),
|
| + 'directlyImportedLibrariesReady':
|
| + IMPORTED_LIBRARIES.of(source).toListOf(LIBRARY_ELEMENT5),
|
| + 'directlyExportedLibrariesReady':
|
| + EXPORTED_LIBRARIES.of(source).toListOf(LIBRARY_ELEMENT5),
|
| };
|
| }
|
|
|
| /**
|
| - * Create a [ResolveLibraryReferencesTask] based on the given [target] in
|
| - * the given [context].
|
| + * Create a [ResolveTopLevelLibraryTypeBoundsTask] based on the given [target]
|
| + * in the given [context].
|
| */
|
| - static ResolveLibraryReferencesTask createTask(
|
| + static ResolveTopLevelLibraryTypeBoundsTask createTask(
|
| AnalysisContext context, AnalysisTarget target) {
|
| - return new ResolveLibraryReferencesTask(context, target);
|
| + return new ResolveTopLevelLibraryTypeBoundsTask(context, target);
|
| }
|
| }
|
|
|
| /**
|
| - * An artifitial task that does nothing except to force type names resolution
|
| - * for the defining and part units of a library.
|
| + * A task that builds [RESOLVED_UNIT4] for a unit.
|
| */
|
| -class ResolveLibraryTypeNamesTask extends SourceBasedAnalysisTask {
|
| +class ResolveTopLevelUnitTypeBoundsTask extends SourceBasedAnalysisTask {
|
| /**
|
| - * The name of the [LIBRARY_ELEMENT4] input.
|
| + * The name of the input whose value is the defining [LIBRARY_ELEMENT4].
|
| */
|
| static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
|
|
|
| + /**
|
| + * The name of the [RESOLVED_UNIT3] input.
|
| + */
|
| + static const String UNIT_INPUT = 'UNIT_INPUT';
|
| +
|
| + /**
|
| + * The name of the [TYPE_PROVIDER] input.
|
| + */
|
| + static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
|
| +
|
| /**
|
| * The task descriptor describing this kind of task.
|
| */
|
| static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| - 'ResolveLibraryTypeNamesTask',
|
| + 'ResolveTopLevelUnitTypeBoundsTask',
|
| createTask,
|
| - buildInputs,
|
| - <ResultDescriptor>[LIBRARY_ELEMENT5]);
|
| + buildInputs, <ResultDescriptor>[
|
| + RESOLVE_TYPE_BOUNDS_ERRORS,
|
| + CREATED_RESOLVED_UNIT4,
|
| + RESOLVED_UNIT4
|
| + ]);
|
|
|
| - ResolveLibraryTypeNamesTask(
|
| + ResolveTopLevelUnitTypeBoundsTask(
|
| InternalAnalysisContext context, AnalysisTarget target)
|
| : super(context, target);
|
|
|
| @@ -3800,8 +5527,27 @@ class ResolveLibraryTypeNamesTask extends SourceBasedAnalysisTask {
|
|
|
| @override
|
| void internalPerform() {
|
| + //
|
| + // Prepare inputs.
|
| + //
|
| LibraryElement library = getRequiredInput(LIBRARY_INPUT);
|
| - outputs[LIBRARY_ELEMENT5] = library;
|
| + CompilationUnit unit = getRequiredInput(UNIT_INPUT);
|
| + CompilationUnitElement unitElement = unit.element;
|
| + TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
|
| + //
|
| + // Resolve TypeName nodes.
|
| + //
|
| + RecordingErrorListener errorListener = new RecordingErrorListener();
|
| + new TypeParameterBoundsResolver(
|
| + typeProvider, library, unitElement.source, errorListener)
|
| + .resolveTypeBounds(unit);
|
| + //
|
| + // Record outputs.
|
| + //
|
| + outputs[RESOLVE_TYPE_BOUNDS_ERRORS] =
|
| + getTargetSourceErrors(errorListener, target);
|
| + outputs[RESOLVED_UNIT4] = unit;
|
| + outputs[CREATED_RESOLVED_UNIT4] = true;
|
| }
|
|
|
| /**
|
| @@ -3810,21 +5556,28 @@ class ResolveLibraryTypeNamesTask extends SourceBasedAnalysisTask {
|
| * given [target].
|
| */
|
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| - Source source = target;
|
| + // TODO(brianwilkerson) This task updates the element model to have type
|
| + // information and updates the class hierarchy. It should produce a new
|
| + // version of the element model in order to record those changes.
|
| + LibrarySpecificUnit unit = target;
|
| return <String, TaskInput>{
|
| - 'resolvedUnit': UNITS.of(source).toList((Source unit) =>
|
| - RESOLVED_UNIT3.of(new LibrarySpecificUnit(source, unit))),
|
| - LIBRARY_INPUT: LIBRARY_ELEMENT4.of(source)
|
| + 'importsExportNamespace':
|
| + IMPORTED_LIBRARIES.of(unit.library).toMapOf(LIBRARY_ELEMENT4),
|
| + 'dependOnAllExportedSources':
|
| + IMPORTED_LIBRARIES.of(unit.library).toMapOf(EXPORT_SOURCE_CLOSURE),
|
| + LIBRARY_INPUT: LIBRARY_ELEMENT4.of(unit.library),
|
| + UNIT_INPUT: RESOLVED_UNIT3.of(unit),
|
| + TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
|
| };
|
| }
|
|
|
| /**
|
| - * Create a [ResolveLibraryTypeNamesTask] based on the given [target] in
|
| + * Create a [ResolveTopLevelUnitTypeBoundsTask] based on the given [target] in
|
| * the given [context].
|
| */
|
| - static ResolveLibraryTypeNamesTask createTask(
|
| + static ResolveTopLevelUnitTypeBoundsTask createTask(
|
| AnalysisContext context, AnalysisTarget target) {
|
| - return new ResolveLibraryTypeNamesTask(context, target);
|
| + return new ResolveTopLevelUnitTypeBoundsTask(context, target);
|
| }
|
| }
|
|
|
| @@ -3834,7 +5587,7 @@ class ResolveLibraryTypeNamesTask extends SourceBasedAnalysisTask {
|
| */
|
| class ResolveUnitTask extends SourceBasedAnalysisTask {
|
| /**
|
| - * The name of the input whose value is the defining [LIBRARY_ELEMENT5].
|
| + * The name of the input whose value is the defining [LIBRARY_ELEMENT8].
|
| */
|
| static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
|
|
|
| @@ -3844,15 +5597,17 @@ 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_UNIT10] input.
|
| */
|
| static const String UNIT_INPUT = 'UNIT_INPUT';
|
|
|
| static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| - 'ResolveUnitTask',
|
| - createTask,
|
| - buildInputs,
|
| - <ResultDescriptor>[RESOLVE_UNIT_ERRORS, RESOLVED_UNIT9]);
|
| + 'ResolveUnitTask', createTask, buildInputs, <ResultDescriptor>[
|
| + CONSTANT_EXPRESSIONS_DEPENDENCIES,
|
| + RESOLVE_UNIT_ERRORS,
|
| + CREATED_RESOLVED_UNIT11,
|
| + RESOLVED_UNIT11
|
| + ]);
|
|
|
| ResolveUnitTask(
|
| InternalAnalysisContext context, LibrarySpecificUnit compilationUnit)
|
| @@ -3866,6 +5621,7 @@ class ResolveUnitTask extends SourceBasedAnalysisTask {
|
| //
|
| // Prepare inputs.
|
| //
|
| + LibrarySpecificUnit target = this.target;
|
| LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT);
|
| CompilationUnit unit = getRequiredInput(UNIT_INPUT);
|
| TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
|
| @@ -3878,10 +5634,26 @@ class ResolveUnitTask extends SourceBasedAnalysisTask {
|
| libraryElement, unitElement.source, typeProvider, errorListener);
|
| unit.accept(visitor);
|
| //
|
| + // Compute constant expressions' dependencies.
|
| + //
|
| + List<ConstantEvaluationTarget> constExprDependencies;
|
| + {
|
| + ConstantExpressionsDependenciesFinder finder =
|
| + new ConstantExpressionsDependenciesFinder();
|
| + unit.accept(finder);
|
| + constExprDependencies = finder.dependencies.toList();
|
| + }
|
| + //
|
| // Record outputs.
|
| //
|
| - outputs[RESOLVE_UNIT_ERRORS] = errorListener.errors;
|
| - outputs[RESOLVED_UNIT9] = unit;
|
| + // TODO(brianwilkerson) This task modifies the element model (by copying the
|
| + // AST's for constructor initializers into it) but does not produce an
|
| + // updated version of the element model.
|
| + //
|
| + outputs[CONSTANT_EXPRESSIONS_DEPENDENCIES] = constExprDependencies;
|
| + outputs[RESOLVE_UNIT_ERRORS] = getTargetSourceErrors(errorListener, target);
|
| + outputs[RESOLVED_UNIT11] = unit;
|
| + outputs[CREATED_RESOLVED_UNIT11] = true;
|
| }
|
|
|
| /**
|
| @@ -3892,17 +5664,16 @@ class ResolveUnitTask extends SourceBasedAnalysisTask {
|
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| LibrarySpecificUnit unit = target;
|
| return <String, TaskInput>{
|
| - LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library),
|
| + LIBRARY_INPUT: LIBRARY_ELEMENT8.of(unit.library),
|
| TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
|
| - UNIT_INPUT: RESOLVED_UNIT8.of(unit),
|
| + UNIT_INPUT: RESOLVED_UNIT10.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
|
| - .of(new LibrarySpecificUnit(unit.librarySource, unit.source)))
|
| + 'orderLibraryCycleTasks':
|
| + LIBRARY_CYCLE_UNITS.of(unit.library).toListOf(CREATED_RESOLVED_UNIT10)
|
| };
|
| }
|
|
|
| @@ -3917,16 +5688,16 @@ class ResolveUnitTask extends SourceBasedAnalysisTask {
|
| }
|
|
|
| /**
|
| - * A task that builds [RESOLVED_UNIT3] for a unit.
|
| + * A task that builds [RESOLVED_UNIT5] for a unit.
|
| */
|
| class ResolveUnitTypeNamesTask extends SourceBasedAnalysisTask {
|
| /**
|
| - * The name of the input whose value is the defining [LIBRARY_ELEMENT4].
|
| + * The name of the input whose value is the defining [LIBRARY_ELEMENT5].
|
| */
|
| static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
|
|
|
| /**
|
| - * The name of the [RESOLVED_UNIT2] input.
|
| + * The name of the [RESOLVED_UNIT4] input.
|
| */
|
| static const String UNIT_INPUT = 'UNIT_INPUT';
|
|
|
| @@ -3939,10 +5710,11 @@ class ResolveUnitTypeNamesTask extends SourceBasedAnalysisTask {
|
| * The task descriptor describing this kind of task.
|
| */
|
| static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| - 'ResolveUnitTypeNamesTask',
|
| - createTask,
|
| - buildInputs,
|
| - <ResultDescriptor>[RESOLVE_TYPE_NAMES_ERRORS, RESOLVED_UNIT3]);
|
| + 'ResolveUnitTypeNamesTask', createTask, buildInputs, <ResultDescriptor>[
|
| + RESOLVE_TYPE_NAMES_ERRORS,
|
| + CREATED_RESOLVED_UNIT5,
|
| + RESOLVED_UNIT5
|
| + ]);
|
|
|
| ResolveUnitTypeNamesTask(
|
| InternalAnalysisContext context, AnalysisTarget target)
|
| @@ -3971,8 +5743,9 @@ class ResolveUnitTypeNamesTask extends SourceBasedAnalysisTask {
|
| // Record outputs.
|
| //
|
| outputs[RESOLVE_TYPE_NAMES_ERRORS] =
|
| - removeDuplicateErrors(errorListener.errors);
|
| - outputs[RESOLVED_UNIT3] = unit;
|
| + getTargetSourceErrors(errorListener, target);
|
| + outputs[RESOLVED_UNIT5] = unit;
|
| + outputs[CREATED_RESOLVED_UNIT5] = true;
|
| }
|
|
|
| /**
|
| @@ -3986,10 +5759,8 @@ class ResolveUnitTypeNamesTask extends SourceBasedAnalysisTask {
|
| // version of the element model in order to record those changes.
|
| LibrarySpecificUnit unit = target;
|
| return <String, TaskInput>{
|
| - 'importsExportNamespace':
|
| - IMPORTED_LIBRARIES.of(unit.library).toMapOf(LIBRARY_ELEMENT4),
|
| - LIBRARY_INPUT: LIBRARY_ELEMENT4.of(unit.library),
|
| - UNIT_INPUT: RESOLVED_UNIT2.of(unit),
|
| + LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library),
|
| + UNIT_INPUT: RESOLVED_UNIT4.of(unit),
|
| TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
|
| };
|
| }
|
| @@ -4005,7 +5776,7 @@ class ResolveUnitTypeNamesTask extends SourceBasedAnalysisTask {
|
| }
|
|
|
| /**
|
| - * A task that builds [RESOLVED_UNIT4] for a unit.
|
| + * A task that builds [RESOLVED_UNIT6] for a unit.
|
| */
|
| class ResolveVariableReferencesTask extends SourceBasedAnalysisTask {
|
| /**
|
| @@ -4014,7 +5785,7 @@ class ResolveVariableReferencesTask extends SourceBasedAnalysisTask {
|
| static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
|
|
|
| /**
|
| - * The name of the [RESOLVED_UNIT3] input.
|
| + * The name of the [RESOLVED_UNIT5] input.
|
| */
|
| static const String UNIT_INPUT = 'UNIT_INPUT';
|
|
|
| @@ -4029,8 +5800,11 @@ class ResolveVariableReferencesTask extends SourceBasedAnalysisTask {
|
| static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| 'ResolveVariableReferencesTask',
|
| createTask,
|
| - buildInputs,
|
| - <ResultDescriptor>[RESOLVED_UNIT4, VARIABLE_REFERENCE_ERRORS]);
|
| + buildInputs, <ResultDescriptor>[
|
| + CREATED_RESOLVED_UNIT6,
|
| + RESOLVED_UNIT6,
|
| + VARIABLE_REFERENCE_ERRORS
|
| + ]);
|
|
|
| ResolveVariableReferencesTask(
|
| InternalAnalysisContext context, AnalysisTarget target)
|
| @@ -4052,7 +5826,7 @@ class ResolveVariableReferencesTask extends SourceBasedAnalysisTask {
|
| // Resolve local variables.
|
| //
|
| RecordingErrorListener errorListener = new RecordingErrorListener();
|
| - Scope nameScope = new LibraryScope(libraryElement, errorListener);
|
| + Scope nameScope = new LibraryScope(libraryElement);
|
| VariableResolverVisitor visitor = new VariableResolverVisitor(
|
| libraryElement, unitElement.source, typeProvider, errorListener,
|
| nameScope: nameScope);
|
| @@ -4060,9 +5834,10 @@ class ResolveVariableReferencesTask extends SourceBasedAnalysisTask {
|
| //
|
| // Record outputs.
|
| //
|
| - outputs[RESOLVED_UNIT4] = unit;
|
| + outputs[RESOLVED_UNIT6] = unit;
|
| + outputs[CREATED_RESOLVED_UNIT6] = true;
|
| outputs[VARIABLE_REFERENCE_ERRORS] =
|
| - removeDuplicateErrors(errorListener.errors);
|
| + getTargetSourceErrors(errorListener, target);
|
| }
|
|
|
| /**
|
| @@ -4074,7 +5849,7 @@ class ResolveVariableReferencesTask extends SourceBasedAnalysisTask {
|
| LibrarySpecificUnit unit = target;
|
| return <String, TaskInput>{
|
| LIBRARY_INPUT: LIBRARY_ELEMENT1.of(unit.library),
|
| - UNIT_INPUT: RESOLVED_UNIT3.of(unit),
|
| + UNIT_INPUT: RESOLVED_UNIT5.of(unit),
|
| TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
|
| };
|
| }
|
| @@ -4099,6 +5874,11 @@ class ScanDartTask extends SourceBasedAnalysisTask {
|
| */
|
| static const String CONTENT_INPUT_NAME = 'CONTENT_INPUT_NAME';
|
|
|
| + /**
|
| + * The name of the input whose value is the modification time of the file.
|
| + */
|
| + static const String MODIFICATION_TIME_INPUT = 'MODIFICATION_TIME_INPUT';
|
| +
|
| /**
|
| * The task descriptor describing this kind of task.
|
| */
|
| @@ -4106,7 +5886,8 @@ class ScanDartTask extends SourceBasedAnalysisTask {
|
| 'ScanDartTask',
|
| createTask,
|
| buildInputs,
|
| - <ResultDescriptor>[LINE_INFO, SCAN_ERRORS, TOKEN_STREAM]);
|
| + <ResultDescriptor>[IGNORE_INFO, LINE_INFO, SCAN_ERRORS, TOKEN_STREAM],
|
| + suitabilityFor: suitabilityFor);
|
|
|
| /**
|
| * Initialize a newly created task to access the content of the source
|
| @@ -4121,9 +5902,10 @@ class ScanDartTask extends SourceBasedAnalysisTask {
|
| @override
|
| void internalPerform() {
|
| Source source = getRequiredSource();
|
| -
|
| RecordingErrorListener errorListener = new RecordingErrorListener();
|
| - if (context.getModificationStamp(target.source) < 0) {
|
| +
|
| + int modificationTime = getRequiredInput(MODIFICATION_TIME_INPUT);
|
| + if (modificationTime < 0) {
|
| String message = 'Content could not be read';
|
| if (context is InternalAnalysisContext) {
|
| CacheEntry entry =
|
| @@ -4155,20 +5937,33 @@ class ScanDartTask extends SourceBasedAnalysisTask {
|
| errorListener);
|
| scanner.setSourceStart(fragment.line, fragment.column);
|
| scanner.preserveComments = context.analysisOptions.preserveComments;
|
| + scanner.scanGenericMethodComments = context.analysisOptions.strongMode;
|
| + scanner.scanLazyAssignmentOperators =
|
| + context.analysisOptions.enableLazyAssignmentOperators;
|
| +
|
| + LineInfo lineInfo = new LineInfo(scanner.lineStarts);
|
|
|
| outputs[TOKEN_STREAM] = scanner.tokenize();
|
| - outputs[LINE_INFO] = new LineInfo(scanner.lineStarts);
|
| - outputs[SCAN_ERRORS] = removeDuplicateErrors(errorListener.errors);
|
| + outputs[LINE_INFO] = lineInfo;
|
| + outputs[IGNORE_INFO] =
|
| + IgnoreInfo.calculateIgnores(fragment.content, lineInfo);
|
| + outputs[SCAN_ERRORS] = getUniqueErrors(errorListener.errors);
|
| } else if (target is Source) {
|
| String content = getRequiredInput(CONTENT_INPUT_NAME);
|
|
|
| Scanner scanner =
|
| new Scanner(source, new CharSequenceReader(content), errorListener);
|
| scanner.preserveComments = context.analysisOptions.preserveComments;
|
| + scanner.scanGenericMethodComments = context.analysisOptions.strongMode;
|
| + scanner.scanLazyAssignmentOperators =
|
| + context.analysisOptions.enableLazyAssignmentOperators;
|
| +
|
| + LineInfo lineInfo = new LineInfo(scanner.lineStarts);
|
|
|
| outputs[TOKEN_STREAM] = scanner.tokenize();
|
| - outputs[LINE_INFO] = new LineInfo(scanner.lineStarts);
|
| - outputs[SCAN_ERRORS] = removeDuplicateErrors(errorListener.errors);
|
| + outputs[LINE_INFO] = lineInfo;
|
| + outputs[IGNORE_INFO] = IgnoreInfo.calculateIgnores(content, lineInfo);
|
| + outputs[SCAN_ERRORS] = getUniqueErrors(errorListener.errors);
|
| } else {
|
| throw new AnalysisException(
|
| 'Cannot scan Dart code from a ${target.runtimeType}');
|
| @@ -4178,16 +5973,23 @@ class ScanDartTask extends SourceBasedAnalysisTask {
|
| /**
|
| * 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
|
| - * [source].
|
| + * [target].
|
| */
|
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| if (target is Source) {
|
| - return <String, TaskInput>{CONTENT_INPUT_NAME: CONTENT.of(target)};
|
| + return <String, TaskInput>{
|
| + CONTENT_INPUT_NAME: CONTENT.of(target, flushOnAccess: true),
|
| + MODIFICATION_TIME_INPUT: MODIFICATION_TIME.of(target)
|
| + };
|
| } else if (target is DartScript) {
|
| // This task does not use the following input; it is included only to add
|
| // a dependency between this value and the containing source so that when
|
| // the containing source is modified these results will be invalidated.
|
| - return <String, TaskInput>{'-': DART_SCRIPTS.of(target.source)};
|
| + Source source = target.source;
|
| + return <String, TaskInput>{
|
| + '-': DART_SCRIPTS.of(source),
|
| + MODIFICATION_TIME_INPUT: MODIFICATION_TIME.of(source)
|
| + };
|
| }
|
| throw new AnalysisException(
|
| 'Cannot build inputs for a ${target.runtimeType}');
|
| @@ -4200,6 +6002,21 @@ class ScanDartTask extends SourceBasedAnalysisTask {
|
| AnalysisContext context, AnalysisTarget target) {
|
| return new ScanDartTask(context, target);
|
| }
|
| +
|
| + /**
|
| + * Return an indication of how suitable this task is for the given [target].
|
| + */
|
| + static TaskSuitability suitabilityFor(AnalysisTarget target) {
|
| + if (target is Source) {
|
| + if (target.shortName.endsWith(AnalysisEngine.SUFFIX_DART)) {
|
| + return TaskSuitability.HIGHEST;
|
| + }
|
| + return TaskSuitability.LOWEST;
|
| + } else if (target is DartScript) {
|
| + return TaskSuitability.HIGHEST;
|
| + }
|
| + return TaskSuitability.NONE;
|
| + }
|
| }
|
|
|
| /**
|
| @@ -4208,7 +6025,7 @@ class ScanDartTask extends SourceBasedAnalysisTask {
|
| */
|
| class StrongModeVerifyUnitTask extends SourceBasedAnalysisTask {
|
| /**
|
| - * The name of the [RESOLVED_UNIT10] input.
|
| + * The name of the [RESOLVED_UNIT12] input.
|
| */
|
| static const String UNIT_INPUT = 'UNIT_INPUT';
|
|
|
| @@ -4221,10 +6038,11 @@ class StrongModeVerifyUnitTask extends SourceBasedAnalysisTask {
|
| * The task descriptor describing this kind of task.
|
| */
|
| static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
|
| - 'StrongModeVerifyUnitTask',
|
| - createTask,
|
| - buildInputs,
|
| - <ResultDescriptor>[STRONG_MODE_ERRORS, RESOLVED_UNIT]);
|
| + 'StrongModeVerifyUnitTask', createTask, buildInputs, <ResultDescriptor>[
|
| + STRONG_MODE_ERRORS,
|
| + CREATED_RESOLVED_UNIT,
|
| + RESOLVED_UNIT
|
| + ]);
|
|
|
| StrongModeVerifyUnitTask(
|
| InternalAnalysisContext context, AnalysisTarget target)
|
| @@ -4241,14 +6059,22 @@ class StrongModeVerifyUnitTask extends SourceBasedAnalysisTask {
|
| //
|
| TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
|
| CompilationUnit unit = getRequiredInput(UNIT_INPUT);
|
| - if (context.analysisOptions.strongMode) {
|
| - unit.accept(new CodeChecker(new TypeRules(typeProvider), errorListener));
|
| + AnalysisOptionsImpl options = context.analysisOptions;
|
| + if (options.strongMode) {
|
| + CodeChecker checker = new CodeChecker(
|
| + typeProvider,
|
| + new StrongTypeSystemImpl(
|
| + implicitCasts: options.implicitCasts,
|
| + nonnullableTypes: options.nonnullableTypes),
|
| + errorListener,
|
| + options);
|
| + checker.visitCompilationUnit(unit);
|
| }
|
| -
|
| //
|
| // Record outputs.
|
| //
|
| - outputs[STRONG_MODE_ERRORS] = removeDuplicateErrors(errorListener.errors);
|
| + outputs[STRONG_MODE_ERRORS] = getUniqueErrors(errorListener.errors);
|
| + outputs[CREATED_RESOLVED_UNIT] = true;
|
| outputs[RESOLVED_UNIT] = unit;
|
| }
|
|
|
| @@ -4260,13 +6086,8 @@ class StrongModeVerifyUnitTask extends SourceBasedAnalysisTask {
|
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| LibrarySpecificUnit unit = target;
|
| return <String, TaskInput>{
|
| - 'resolvedUnits': IMPORT_EXPORT_SOURCE_CLOSURE
|
| - .of(unit.library)
|
| - .toMapOf(UNITS)
|
| - .toFlattenList((Source library, Source unit) =>
|
| - RESOLVED_UNIT10.of(new LibrarySpecificUnit(library, unit))),
|
| - UNIT_INPUT: RESOLVED_UNIT10.of(unit),
|
| - TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
|
| + UNIT_INPUT: RESOLVED_UNIT12.of(unit),
|
| + TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
|
| };
|
| }
|
|
|
| @@ -4285,15 +6106,27 @@ class StrongModeVerifyUnitTask extends SourceBasedAnalysisTask {
|
| */
|
| class VerifyUnitTask extends SourceBasedAnalysisTask {
|
| /**
|
| - * The name of the [RESOLVED_UNIT] input.
|
| + * The name of the [PENDING_ERRORS] input.
|
| */
|
| - static const String UNIT_INPUT = 'UNIT_INPUT';
|
| + static const String PENDING_ERRORS_INPUT = 'PENDING_ERRORS_INPUT';
|
| +
|
| + /**
|
| + * The name of the input of a mapping from [REFERENCED_SOURCES] to their
|
| + * [MODIFICATION_TIME]s.
|
| + */
|
| + static const String REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT =
|
| + 'REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT';
|
|
|
| /**
|
| * The name of the [TYPE_PROVIDER] input.
|
| */
|
| static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
|
|
|
| + /**
|
| + * The name of the [RESOLVED_UNIT] input.
|
| + */
|
| + static const String UNIT_INPUT = 'UNIT_INPUT';
|
| +
|
| /**
|
| * The task descriptor describing this kind of task.
|
| */
|
| @@ -4305,6 +6138,12 @@ class VerifyUnitTask extends SourceBasedAnalysisTask {
|
| */
|
| ErrorReporter errorReporter;
|
|
|
| + /**
|
| + * The mapping from the current library referenced sources to their
|
| + * modification times.
|
| + */
|
| + Map<Source, int> sourceTimeMap;
|
| +
|
| VerifyUnitTask(InternalAnalysisContext context, AnalysisTarget target)
|
| : super(context, target);
|
|
|
| @@ -4319,10 +6158,18 @@ class VerifyUnitTask extends SourceBasedAnalysisTask {
|
| //
|
| // Prepare inputs.
|
| //
|
| - TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
|
| CompilationUnit unit = getRequiredInput(UNIT_INPUT);
|
| CompilationUnitElement unitElement = unit.element;
|
| LibraryElement libraryElement = unitElement.library;
|
| + if (libraryElement == null) {
|
| + throw new AnalysisException(
|
| + 'VerifyUnitTask verifying a unit with no library: '
|
| + '${unitElement.source.fullName}');
|
| + }
|
| + List<PendingError> pendingErrors = getRequiredInput(PENDING_ERRORS_INPUT);
|
| + sourceTimeMap =
|
| + getRequiredInput(REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT);
|
| + TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
|
| //
|
| // Validate the directives.
|
| //
|
| @@ -4341,13 +6188,19 @@ class VerifyUnitTask extends SourceBasedAnalysisTask {
|
| libraryElement,
|
| typeProvider,
|
| new InheritanceManager(libraryElement),
|
| - context.analysisOptions.enableSuperMixins);
|
| + context.analysisOptions.enableSuperMixins,
|
| + context.analysisOptions.enableAssertMessage);
|
| unit.accept(errorVerifier);
|
| -
|
| + //
|
| + // Convert the pending errors into actual errors.
|
| + //
|
| + for (PendingError pendingError in pendingErrors) {
|
| + errorListener.onError(pendingError.toAnalysisError());
|
| + }
|
| //
|
| // Record outputs.
|
| //
|
| - outputs[VERIFY_ERRORS] = removeDuplicateErrors(errorListener.errors);
|
| + outputs[VERIFY_ERRORS] = getUniqueErrors(errorListener.errors);
|
| }
|
|
|
| /**
|
| @@ -4355,7 +6208,10 @@ class VerifyUnitTask extends SourceBasedAnalysisTask {
|
| * exists and report an error if it does not.
|
| */
|
| void validateDirectives(CompilationUnit unit) {
|
| - for (Directive directive in unit.directives) {
|
| + NodeList<Directive> directives = unit.directives;
|
| + int length = directives.length;
|
| + for (int i = 0; i < length; i++) {
|
| + Directive directive = directives[i];
|
| if (directive is UriBasedDirective) {
|
| validateReferencedSource(directive);
|
| }
|
| @@ -4366,10 +6222,37 @@ class VerifyUnitTask extends SourceBasedAnalysisTask {
|
| * Check the given [directive] to see if the referenced source exists and
|
| * report an error if it does not.
|
| */
|
| - void validateReferencedSource(UriBasedDirective directive) {
|
| - Source source = directive.source;
|
| + void validateReferencedSource(UriBasedDirectiveImpl directive) {
|
| + if (directive is NamespaceDirectiveImpl) {
|
| + for (Configuration configuration in directive.configurations) {
|
| + Source source = configuration.uriSource;
|
| + StringLiteral uriLiteral = configuration.uri;
|
| + String uriContent = uriLiteral?.stringValue?.trim();
|
| + if (source != null) {
|
| + int modificationTime = sourceTimeMap[source] ?? -1;
|
| + if (modificationTime >= 0) {
|
| + continue;
|
| + }
|
| + } else {
|
| + // Don't report errors already reported by ParseDartTask.resolveDirective
|
| + if (UriBasedDirectiveImpl.validateUri(
|
| + directive is ImportDirective, uriLiteral, uriContent) !=
|
| + null) {
|
| + continue;
|
| + }
|
| + }
|
| + CompileTimeErrorCode errorCode =
|
| + CompileTimeErrorCode.URI_DOES_NOT_EXIST;
|
| + if (_isGenerated(source)) {
|
| + errorCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED;
|
| + }
|
| + errorReporter.reportErrorForNode(errorCode, uriLiteral, [uriContent]);
|
| + }
|
| + }
|
| + Source source = directive.uriSource;
|
| if (source != null) {
|
| - if (context.exists(source)) {
|
| + int modificationTime = sourceTimeMap[source] ?? -1;
|
| + if (modificationTime >= 0) {
|
| return;
|
| }
|
| } else {
|
| @@ -4379,8 +6262,38 @@ class VerifyUnitTask extends SourceBasedAnalysisTask {
|
| }
|
| }
|
| StringLiteral uriLiteral = directive.uri;
|
| - errorReporter.reportErrorForNode(CompileTimeErrorCode.URI_DOES_NOT_EXIST,
|
| - uriLiteral, [directive.uriContent]);
|
| + CompileTimeErrorCode errorCode = CompileTimeErrorCode.URI_DOES_NOT_EXIST;
|
| + if (_isGenerated(source)) {
|
| + errorCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED;
|
| + }
|
| + errorReporter
|
| + .reportErrorForNode(errorCode, uriLiteral, [directive.uriContent]);
|
| + }
|
| +
|
| + /**
|
| + * Return `true` if the given [source] refers to a file that is assumed to be
|
| + * generated.
|
| + */
|
| + bool _isGenerated(Source source) {
|
| + if (source == null) {
|
| + return false;
|
| + }
|
| + // TODO(brianwilkerson) Generalize this mechanism.
|
| + const List<String> suffixes = const <String>[
|
| + '.g.dart',
|
| + '.pb.dart',
|
| + '.pbenum.dart',
|
| + '.pbserver.dart',
|
| + '.pbjson.dart',
|
| + '.template.dart'
|
| + ];
|
| + String fullName = source.fullName;
|
| + for (String suffix in suffixes) {
|
| + if (fullName.endsWith(suffix)) {
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| }
|
|
|
| /**
|
| @@ -4391,12 +6304,12 @@ class VerifyUnitTask extends SourceBasedAnalysisTask {
|
| static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
|
| LibrarySpecificUnit unit = target;
|
| return <String, TaskInput>{
|
| - 'resolvedUnits': IMPORT_EXPORT_SOURCE_CLOSURE
|
| - .of(unit.library)
|
| - .toMapOf(UNITS)
|
| - .toFlattenList((Source library, Source unit) =>
|
| - RESOLVED_UNIT.of(new LibrarySpecificUnit(library, unit))),
|
| + 'thisLibraryClosureIsReady': READY_RESOLVED_UNIT.of(unit.library),
|
| UNIT_INPUT: RESOLVED_UNIT.of(unit),
|
| + REFERENCED_SOURCE_MODIFICATION_TIME_MAP_INPUT:
|
| + REFERENCED_SOURCES.of(unit.library).toMapOf(MODIFICATION_TIME),
|
| + PENDING_ERRORS_INPUT: PENDING_ERRORS.of(unit),
|
| + 'requiredConstants': REQUIRED_CONSTANTS.of(unit).toListOf(CONSTANT_VALUE),
|
| TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
|
| };
|
| }
|
| @@ -4430,25 +6343,6 @@ class _ExportSourceClosureTaskInput extends TaskInputImpl<List<Source>> {
|
| target, _SourceClosureKind.EXPORT, resultDescriptor);
|
| }
|
|
|
| -/**
|
| - * A [TaskInput] whose value is a list of library sources imported or exported,
|
| - * directly or indirectly by the target [Source].
|
| - *
|
| - * [resultDescriptor] is the type of result which should be produced for each
|
| - * target [Source].
|
| - */
|
| -class _ImportExportSourceClosureTaskInput extends TaskInputImpl<List<Source>> {
|
| - final Source target;
|
| - final ResultDescriptor resultDescriptor;
|
| -
|
| - _ImportExportSourceClosureTaskInput(this.target, this.resultDescriptor);
|
| -
|
| - @override
|
| - TaskInputBuilder<List<Source>> createBuilder() =>
|
| - new _SourceClosureTaskInputBuilder(
|
| - target, _SourceClosureKind.IMPORT_EXPORT, resultDescriptor);
|
| -}
|
| -
|
| /**
|
| * A [TaskInput] whose value is a list of library sources imported directly
|
| * or indirectly by the target [Source].
|
| @@ -4497,16 +6391,26 @@ class _SourceClosureTaskInputBuilder implements TaskInputBuilder<List<Source>> {
|
| if (_libraries.add(library)) {
|
| if (kind == _SourceClosureKind.IMPORT ||
|
| kind == _SourceClosureKind.IMPORT_EXPORT) {
|
| - for (ImportElement importElement in library.imports) {
|
| - Source importedSource = importElement.importedLibrary.source;
|
| - _newSources.add(importedSource);
|
| + List<ImportElement> imports = library.imports;
|
| + int length = imports.length;
|
| + for (int i = 0; i < length; i++) {
|
| + ImportElement importElement = imports[i];
|
| + Source importedSource = importElement.importedLibrary?.source;
|
| + if (importedSource != null) {
|
| + _newSources.add(importedSource);
|
| + }
|
| }
|
| }
|
| if (kind == _SourceClosureKind.EXPORT ||
|
| kind == _SourceClosureKind.IMPORT_EXPORT) {
|
| - for (ExportElement exportElement in library.exports) {
|
| - Source exportedSource = exportElement.exportedLibrary.source;
|
| - _newSources.add(exportedSource);
|
| + List<ExportElement> exports = library.exports;
|
| + int length = exports.length;
|
| + for (int i = 0; i < length; i++) {
|
| + ExportElement exportElement = exports[i];
|
| + Source exportedSource = exportElement.exportedLibrary?.source;
|
| + if (exportedSource != null) {
|
| + _newSources.add(exportedSource);
|
| + }
|
| }
|
| }
|
| }
|
|
|