blob: aa309b26b18fd4a47455f840f743f845bc4060eb [file] [log] [blame]
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library analyzer.src.task.dart;
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_resolution_map.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/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/dart/sdk/patch.dart';
import 'package:analyzer/src/dart/sdk/sdk.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/declaration_resolver.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/parser.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.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/inputs.dart';
import 'package:analyzer/src/task/model.dart';
import 'package:analyzer/src/task/strong/checker.dart';
import 'package:analyzer/src/task/strong_mode.dart';
import 'package:analyzer/task/dart.dart';
import 'package:analyzer/task/general.dart';
import 'package:analyzer/task/model.dart';
/**
* The [ResultCachingPolicy] for ASTs.
*/
const ResultCachingPolicy AST_CACHING_POLICY =
const SimpleResultCachingPolicy(1024 * 64, 32);
/**
* The [ResultCachingPolicy] for lists of [ConstantEvaluationTarget]s.
*/
const ResultCachingPolicy CONSTANT_EVALUATION_TARGET_LIST_POLICY =
const SimpleResultCachingPolicy(-1, -1);
/**
* The [ResultCachingPolicy] for [ConstantEvaluationTarget]s.
*/
const ResultCachingPolicy CONSTANT_EVALUATION_TARGET_POLICY =
const SimpleResultCachingPolicy(-1, -1);
/**
* The [ResultCachingPolicy] for [Element]s.
*/
const ResultCachingPolicy ELEMENT_CACHING_POLICY =
const SimpleResultCachingPolicy(-1, -1);
/**
* The [ResultCachingPolicy] for [TOKEN_STREAM].
*/
const ResultCachingPolicy TOKEN_STREAM_CACHING_POLICY =
const SimpleResultCachingPolicy(1, 1);
/**
* The [ResultCachingPolicy] for [UsedImportedElements]s.
*/
const ResultCachingPolicy USED_IMPORTED_ELEMENTS_POLICY =
const SimpleResultCachingPolicy(-1, -1);
/**
* The [ResultCachingPolicy] for [UsedLocalElements]s.
*/
const ResultCachingPolicy USED_LOCAL_ELEMENTS_POLICY =
const SimpleResultCachingPolicy(-1, -1);
/**
* The errors produced while building a library's directives.
*
* The list will be empty if there were no errors, but will not be `null`.
*
* The result is only available for [Source]s representing a library.
*/
final ListResultDescriptor<AnalysisError> BUILD_DIRECTIVES_ERRORS =
new ListResultDescriptor<AnalysisError>(
'BUILD_DIRECTIVES_ERRORS', AnalysisError.NO_ERRORS);
/**
* The errors produced while building a library element.
*
* The list will be empty if there were no errors, but will not be `null`.
*
* The result is only available for [Source]s representing a library.
*/
final ListResultDescriptor<AnalysisError> BUILD_LIBRARY_ERRORS =
new ListResultDescriptor<AnalysisError>(
'BUILD_LIBRARY_ERRORS', AnalysisError.NO_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.
*
* The result is only available for [LibrarySpecificUnit]s.
*/
final ListResultDescriptor<ConstantEvaluationTarget>
COMPILATION_UNIT_CONSTANTS =
new ListResultDescriptor<ConstantEvaluationTarget>(
'COMPILATION_UNIT_CONSTANTS', null,
cachingPolicy: CONSTANT_EVALUATION_TARGET_LIST_POLICY);
/**
* The element model associated with a single compilation unit.
*
* The result is only available for [LibrarySpecificUnit]s.
*/
final ResultDescriptor<CompilationUnitElement> COMPILATION_UNIT_ELEMENT =
new ResultDescriptor<CompilationUnitElement>(
'COMPILATION_UNIT_ELEMENT', null,
cachingPolicy: ELEMENT_CACHING_POLICY);
/**
* The list of [ConstantEvaluationTarget]s on which the target constant element
* depends.
*
* 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 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.
*
* TODO(paulberry): is ELEMENT_CACHING_POLICY the correct caching policy?
*
* The result is only available for [ConstantEvaluationTarget]s.
*
*/
final ResultDescriptor<ConstantEvaluationTarget> CONSTANT_VALUE =
new ResultDescriptor<ConstantEvaluationTarget>('CONSTANT_VALUE', null,
cachingPolicy: CONSTANT_EVALUATION_TARGET_POLICY);
/**
* The sources representing the libraries that include a given source as a part.
*
* The result is only available for [Source]s representing a compilation unit.
*/
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_DIRECTIVES_ERRORS,
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.
*
* The result is only available for [Source]s representing a library.
*/
final ListResultDescriptor<Source> EXPORT_SOURCE_CLOSURE =
new ListResultDescriptor<Source>('EXPORT_SOURCE_CLOSURE', null);
/**
* The errors produced while generating hints a compilation unit.
*
* 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> HINTS =
new ListResultDescriptor<AnalysisError>(
'HINT_ERRORS', AnalysisError.NO_ERRORS);
/**
* The ignore information for a [Source].
*/
final ResultDescriptor<IgnoreInfo> IGNORE_INFO =
new ResultDescriptor<IgnoreInfo>('IGNORE_INFO', null);
/**
* A list of the [VariableElement]s whose type should be inferred that another
* inferable static variable (the target) depends on.
*
* The result is only available for [VariableElement]s, and only when strong
* mode is enabled.
*/
final ListResultDescriptor<VariableElement>
INFERABLE_STATIC_VARIABLE_DEPENDENCIES =
new ListResultDescriptor<VariableElement>(
'INFERABLE_STATIC_VARIABLE_DEPENDENCIES', null);
/**
* A list of the [VariableElement]s defined in a unit whose type should be
* inferred. This includes variables defined at the library level as well as
* static members inside classes.
*
* The result is only available for [LibrarySpecificUnit]s, and only when strong
* mode is enabled.
*/
final ListResultDescriptor<VariableElement> INFERABLE_STATIC_VARIABLES_IN_UNIT =
new ListResultDescriptor<VariableElement>(
'INFERABLE_STATIC_VARIABLES_IN_UNIT', null);
/**
* An inferable static variable ([VariableElement]) whose type has been
* inferred.
*
* The result is only available for [VariableElement]s, and only when strong
* mode is enabled.
*/
final ResultDescriptor<VariableElement> INFERRED_STATIC_VARIABLE =
new ResultDescriptor<VariableElement>('INFERRED_STATIC_VARIABLE', null,
cachingPolicy: ELEMENT_CACHING_POLICY);
/**
* A list of the [LibraryElement]s 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 [Source]s representing a library.
*/
final ListResultDescriptor<LibraryElement> LIBRARY_CYCLE =
new ListResultDescriptor<LibraryElement>('LIBRARY_CYCLE', null);
/**
* 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 [Source]s representing a library.
*/
final ListResultDescriptor<LibrarySpecificUnit> LIBRARY_CYCLE_DEPENDENCIES =
new ListResultDescriptor<LibrarySpecificUnit>(
'LIBRARY_CYCLE_DEPENDENCIES', null);
/**
* 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 [Source]s representing a library.
*/
final ListResultDescriptor<LibrarySpecificUnit> LIBRARY_CYCLE_UNITS =
new ListResultDescriptor<LibrarySpecificUnit>('LIBRARY_CYCLE_UNITS', null);
/**
* The partial [LibraryElement] associated with a library.
*
* The [LibraryElement] and its [CompilationUnitElement]s are attached to each
* other. Directives 'library', 'part' and 'part of' are resolved.
*
* The result is only available for [Source]s representing a library.
*/
final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT1 =
new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT1', null,
cachingPolicy: ELEMENT_CACHING_POLICY);
/**
* The partial [LibraryElement] associated with a library.
*
* In addition to [LIBRARY_ELEMENT1] also [LibraryElement.imports] and
* [LibraryElement.exports] are set.
*
* The result is only available for [Source]s representing a library.
*/
final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT2 =
new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT2', null,
cachingPolicy: ELEMENT_CACHING_POLICY);
/**
* The partial [LibraryElement] associated with a library.
*
* In addition to [LIBRARY_ELEMENT2] the [LibraryElement.publicNamespace] is set.
*
* The result is only available for [Source]s representing a library.
*/
final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT3 =
new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT3', null,
cachingPolicy: ELEMENT_CACHING_POLICY);
/**
* The partial [LibraryElement] associated with a library.
*
* In addition to [LIBRARY_ELEMENT3] the [LibraryElement.entryPoint] is set,
* if the library does not declare one already and one of the exported
* libraries exports one.
*
* Also [LibraryElement.exportNamespace] is set.
*
* The result is only available for [Source]s representing a library.
*/
final ResultDescriptor<LibraryElement> LIBRARY_ELEMENT4 =
new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT4', null,
cachingPolicy: ELEMENT_CACHING_POLICY);
/**
* The partial [LibraryElement] associated with a library.
*
* [LIBRARY_ELEMENT5] plus resolved types type parameter bounds.
*
* The result is only available for [Source]s representing a library.
*/
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.
*
* The result is only available for [Source]s representing a library.
*/
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.
*
* The result is only available for [LibrarySpecificUnit]s.
*/
final ListResultDescriptor<AnalysisError> LIBRARY_UNIT_ERRORS =
new ListResultDescriptor<AnalysisError>(
'LIBRARY_UNIT_ERRORS', AnalysisError.NO_ERRORS);
/**
* The errors produced while generating lints for a compilation unit.
*
* 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> LINTS =
new ListResultDescriptor<AnalysisError>(
'LINT_ERRORS', AnalysisError.NO_ERRORS);
/**
* The errors produced while parsing a compilation unit.
*
* The list will be empty if there were no errors, but will not be `null`.
*
* The result is only available for [Source]s representing a compilation unit.
*/
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 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 a library's directives.
*
* The list will be empty if there were no errors, but will not be `null`.
*
* The result is only available for [Source]s representing a library.
*/
final ListResultDescriptor<AnalysisError> RESOLVE_DIRECTIVES_ERRORS =
new ListResultDescriptor<AnalysisError>(
'RESOLVE_DIRECTIVES_ERRORS', AnalysisError.NO_ERRORS);
/**
* 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.
*
* 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_NAMES_ERRORS =
new ListResultDescriptor<AnalysisError>(
'RESOLVE_TYPE_NAMES_ERRORS', AnalysisError.NO_ERRORS);
/**
* The errors produced while resolving a full compilation unit.
*
* 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_UNIT_ERRORS =
new ListResultDescriptor<AnalysisError>(
'RESOLVE_UNIT_ERRORS', AnalysisError.NO_ERRORS);
/**
* 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, except for the constants defined in an 'enum' declaration.
*
* The result is only available for [LibrarySpecificUnit]s.
*/
final ResultDescriptor<CompilationUnit> RESOLVED_UNIT1 =
new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT1', null,
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_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);
/**
* The resolved [CompilationUnit] associated with a compilation unit, with
* constants resolved.
*
* The result is only available for [LibrarySpecificUnit]s.
*/
final ResultDescriptor<CompilationUnit> RESOLVED_UNIT12 =
new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT12', null,
cachingPolicy: AST_CACHING_POLICY);
/**
* The partially resolved [CompilationUnit] associated with a compilation unit.
*
* 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);
/**
* 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.
*
* The result is only available for [LibrarySpecificUnit]s.
*/
final ResultDescriptor<CompilationUnit> RESOLVED_UNIT3 =
new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT3', null,
cachingPolicy: AST_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 the types associated with type bounds have been
* resolved.
*
* The result is only available for [LibrarySpecificUnit]s.
*/
final ResultDescriptor<CompilationUnit> RESOLVED_UNIT4 =
new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT4', null,
cachingPolicy: AST_CACHING_POLICY);
/**
* 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 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.
*/
final ResultDescriptor<CompilationUnit> RESOLVED_UNIT5 =
new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT5', null,
cachingPolicy: AST_CACHING_POLICY);
/**
* 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 references to local variables and formal
* parameters have been resolved.
*
* The result is only available for [LibrarySpecificUnit]s.
*/
final ResultDescriptor<CompilationUnit> RESOLVED_UNIT6 =
new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT6', null,
cachingPolicy: AST_CACHING_POLICY);
/**
* 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 elements and types associated with expressions
* outside of method bodies (essentially initializers) have been initially
* resolved.
*
* The result is only available for [LibrarySpecificUnit]s.
*/
final ResultDescriptor<CompilationUnit> RESOLVED_UNIT7 =
new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT7', null,
cachingPolicy: AST_CACHING_POLICY);
/**
* 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.
*/
final ResultDescriptor<CompilationUnit> RESOLVED_UNIT8 =
new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT8', null,
cachingPolicy: AST_CACHING_POLICY);
/**
* 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.
*/
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.
*
* The list will be empty if there were no errors, but will not be `null`.
*
* The result is only available for [Source]s representing a compilation unit.
*/
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.
*
* The list will be empty if there were no errors, but will not be `null`.
*
* The result is only available for [LibrarySpecificUnits]s representing a
* compilation unit.
*
*/
final ListResultDescriptor<AnalysisError> STRONG_MODE_ERRORS =
new ListResultDescriptor<AnalysisError>(
'STRONG_MODE_ERRORS', AnalysisError.NO_ERRORS);
/**
* The [TypeProvider] of the [AnalysisContext].
*/
final ResultDescriptor<TypeProvider> TYPE_PROVIDER =
new ResultDescriptor<TypeProvider>('TYPE_PROVIDER', null);
/**
* The [UsedImportedElements] of a [LibrarySpecificUnit].
*/
final ResultDescriptor<UsedImportedElements> USED_IMPORTED_ELEMENTS =
new ResultDescriptor<UsedImportedElements>('USED_IMPORTED_ELEMENTS', null,
cachingPolicy: USED_IMPORTED_ELEMENTS_POLICY);
/**
* The [UsedLocalElements] of a [LibrarySpecificUnit].
*/
final ResultDescriptor<UsedLocalElements> USED_LOCAL_ELEMENTS =
new ResultDescriptor<UsedLocalElements>('USED_LOCAL_ELEMENTS', null,
cachingPolicy: USED_LOCAL_ELEMENTS_POLICY);
/**
* The errors produced while resolving variable references in a compilation unit.
*
* 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> VARIABLE_REFERENCE_ERRORS =
new ListResultDescriptor<AnalysisError>(
'VARIABLE_REFERENCE_ERRORS', AnalysisError.NO_ERRORS);
/**
* The errors produced while verifying a compilation unit.
*
* 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> 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> getUniqueErrors(List<AnalysisError> errors) {
if (errors.isEmpty) {
return errors;
}
return errors.toSet().toList();
}
/**
* A task that builds a compilation unit element for a single compilation unit.
*/
class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask {
/**
* The name of the input whose value is the AST for the compilation unit.
*/
static const String PARSED_UNIT_INPUT_NAME = 'PARSED_UNIT_INPUT_NAME';
/**
* The name of the input whose value is the source line info.
*/
static const String LINE_INFO_INPUT_NAME = 'LINE_INFO_INPUT_NAME';
/**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'BuildCompilationUnitElementTask',
createTask,
buildInputs, <ResultDescriptor>[
COMPILATION_UNIT_CONSTANTS,
COMPILATION_UNIT_ELEMENT,
CREATED_RESOLVED_UNIT1,
RESOLVED_UNIT1
]);
/**
* Initialize a newly created task to build a compilation unit element for
* the given [target] in the given [context].
*/
BuildCompilationUnitElementTask(
InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
//
// Prepare inputs.
//
LibrarySpecificUnit librarySpecificUnit = target;
Source source = getRequiredSource();
CompilationUnit unit = getRequiredInput(PARSED_UNIT_INPUT_NAME);
LineInfo lineInfo = getRequiredInput(LINE_INFO_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.
//
if (element == null) {
CompilationUnitBuilder builder = new CompilationUnitBuilder();
element = builder.buildCompilationUnit(
source, unit, librarySpecificUnit.library);
(element as CompilationUnitElementImpl).lineInfo = lineInfo;
} else {
new DeclarationResolver().resolve(unit, element);
}
//
// Prepare constants.
//
ConstantFinder constantFinder = new ConstantFinder();
unit.accept(constantFinder);
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;
}
/**
* 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>{
PARSED_UNIT_INPUT_NAME: PARSED_UNIT.of(unit.unit, flushOnAccess: true),
LINE_INFO_INPUT_NAME: LINE_INFO.of(unit.unit)
};
}
/**
* Create a [BuildCompilationUnitElementTask] based on the given [target] in
* the given [context].
*/
static BuildCompilationUnitElementTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new BuildCompilationUnitElementTask(context, target);
}
}
/**
* A task that builds imports and export directive elements for a library.
*/
class BuildDirectiveElementsTask extends SourceBasedAnalysisTask {
/**
* The name of the input whose value is the defining [LIBRARY_ELEMENT1].
*/
static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
/**
* The name of the input for [RESOLVED_UNIT1] of a library unit.
*/
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.
*/
static const String IMPORTS_LIBRARY_ELEMENT_INPUT_NAME =
'IMPORTS_LIBRARY_ELEMENT1_INPUT_NAME';
/**
* The input with a list of [LIBRARY_ELEMENT3]s of exported libraries.
*/
static const String EXPORTS_LIBRARY_ELEMENT_INPUT_NAME =
'EXPORTS_LIBRARY_ELEMENT_INPUT_NAME';
/**
* The input with a list of [SOURCE_KIND]s of imported libraries.
*/
static const String IMPORTS_SOURCE_KIND_INPUT_NAME =
'IMPORTS_SOURCE_KIND_INPUT_NAME';
/**
* The input with a list of [SOURCE_KIND]s of exported libraries.
*/
static const String EXPORTS_SOURCE_KIND_INPUT_NAME =
'EXPORTS_SOURCE_KIND_INPUT_NAME';
/**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'BuildDirectiveElementsTask',
createTask,
buildInputs,
<ResultDescriptor>[LIBRARY_ELEMENT2, BUILD_DIRECTIVES_ERRORS]);
BuildDirectiveElementsTask(
InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
//
// 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 =
getRequiredInput(EXPORTS_LIBRARY_ELEMENT_INPUT_NAME);
Map<Source, SourceKind> importSourceKindMap =
getRequiredInput(IMPORTS_SOURCE_KIND_INPUT_NAME);
Map<Source, SourceKind> exportSourceKindMap =
getRequiredInput(EXPORTS_SOURCE_KIND_INPUT_NAME);
//
// Try to get the existing LibraryElement.
//
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);
}
}
//
// Build or reuse the directive elements.
//
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(
sourceModificationTimeMap, importSourceKindMap, exportSourceKindMap);
libraryUnit.accept(resolver);
errors = resolver.errors;
}
//
// Record outputs.
//
outputs[LIBRARY_ELEMENT2] = libraryElement;
outputs[BUILD_DIRECTIVES_ERRORS] = errors;
}
/**
* 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>{
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:
EXPORTED_LIBRARIES.of(source).toMapOf(LIBRARY_ELEMENT1),
IMPORTS_SOURCE_KIND_INPUT_NAME:
IMPORTED_LIBRARIES.of(source).toMapOf(SOURCE_KIND),
EXPORTS_SOURCE_KIND_INPUT_NAME:
EXPORTED_LIBRARIES.of(source).toMapOf(SOURCE_KIND)
};
}
/**
* Create a [BuildDirectiveElementsTask] based on the given [target] in
* the given [context].
*/
static BuildDirectiveElementsTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new BuildDirectiveElementsTask(context, target);
}
}
/**
* A task that builds the elements representing the members of enum
* declarations.
*/
class BuildEnumMemberElementsTask extends SourceBasedAnalysisTask {
/**
* The name of the [TYPE_PROVIDER] input.
*/
static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
/**
* The name of the [RESOLVED_UNIT1] input.
*/
static const String UNIT_INPUT = 'UNIT_INPUT';
/**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'BuildEnumMemberElementsTask',
createTask,
buildInputs,
<ResultDescriptor>[CREATED_RESOLVED_UNIT3, RESOLVED_UNIT3]);
BuildEnumMemberElementsTask(
InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
//
// Prepare inputs.
//
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 &&
resolutionMap
.elementDeclaredByEnumDeclaration(firstEnum)
.accessors
.isEmpty) {
EnumMemberBuilder builder = new EnumMemberBuilder(typeProvider);
unit.accept(builder);
}
//
// Record outputs.
//
outputs[CREATED_RESOLVED_UNIT3] = true;
outputs[RESOLVED_UNIT3] = 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>{
TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request),
UNIT_INPUT: RESOLVED_UNIT2.of(unit)
};
}
/**
* Create a [BuildEnumMemberElementsTask] based on the given [target] in
* the given [context].
*/
static BuildEnumMemberElementsTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new BuildEnumMemberElementsTask(context, target);
}
}
/**
* A task that builds [EXPORT_NAMESPACE] and [LIBRARY_ELEMENT4] for a library.
*/
class BuildExportNamespaceTask extends SourceBasedAnalysisTask {
/**
* The name of the input for [LIBRARY_ELEMENT3] of a library.
*/
static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
/**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'BuildExportNamespaceTask',
createTask,
buildInputs,
<ResultDescriptor>[LIBRARY_ELEMENT4]);
BuildExportNamespaceTask(
InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
LibraryElementImpl library = getRequiredInput(LIBRARY_INPUT);
//
// Compute export namespace.
//
library.exportNamespace = null;
NamespaceBuilder builder = new NamespaceBuilder();
Namespace namespace = builder.createExportNamespaceForLibrary(library);
library.exportNamespace = namespace;
//
// Update entry point.
//
if (library.entryPoint == null) {
Iterable<Element> exportedElements = namespace.definedNames.values;
library.entryPoint = exportedElements.firstWhere(
(element) => element is FunctionElement && element.isEntryPoint,
orElse: () => null);
}
//
// Record outputs.
//
outputs[LIBRARY_ELEMENT4] = 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 library [libSource].
*/
static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
Source source = target;
return <String, TaskInput>{
LIBRARY_INPUT: LIBRARY_ELEMENT3.of(source),
'exportsLibraryPublicNamespace':
EXPORT_SOURCE_CLOSURE.of(source).toMapOf(LIBRARY_ELEMENT3)
};
}
/**
* Create a [BuildExportNamespaceTask] based on the given [target] in
* the given [context].
*/
static BuildExportNamespaceTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new BuildExportNamespaceTask(context, target);
}
}
/**
* A task that builds a library element for a Dart library.
*/
class BuildLibraryElementTask extends SourceBasedAnalysisTask {
/**
* The name of the input whose value is the defining [RESOLVED_UNIT1].
*/
static const String DEFINING_UNIT_INPUT = 'DEFINING_UNIT_INPUT';
/**
* The name of the input whose value is a list of built [RESOLVED_UNIT1]s
* of the parts sourced by a library.
*/
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.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'BuildLibraryElementTask', createTask, buildInputs, <ResultDescriptor>[
BUILD_LIBRARY_ERRORS,
LIBRARY_ELEMENT1,
IS_LAUNCHABLE
]);
/**
* The constant used as an unknown common library name in parts.
*/
static const String _UNKNOWN_LIBRARY_NAME = 'unknown-library-name';
/**
* Initialize a newly created task to build a library element for the given
* [target] in the given [context].
*/
BuildLibraryElementTask(
InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
List<AnalysisError> errors = <AnalysisError>[];
//
// Prepare inputs.
//
Source librarySource = getRequiredSource();
CompilationUnit definingCompilationUnit =
getRequiredInput(DEFINING_UNIT_INPUT);
List<CompilationUnit> partUnits = getRequiredInput(PARTS_UNIT_INPUT);
int modificationTime = getRequiredInput(MODIFICATION_TIME_INPUT);
//
// Process inputs.
//
CompilationUnitElementImpl definingCompilationUnitElement =
definingCompilationUnit.element;
Map<Source, CompilationUnit> partUnitMap =
new HashMap<Source, CompilationUnit>();
int partLength = partUnits.length;
for (int i = 0; i < partLength; i++) {
CompilationUnit partUnit = partUnits[i];
Source partSource =
resolutionMap.elementDeclaredByCompilationUnit(partUnit).source;
partUnitMap[partSource] = partUnit;
}
//
// Update "part" directives.
//
LibraryIdentifier libraryNameNode = null;
String partsLibraryName = _UNKNOWN_LIBRARY_NAME;
bool hasPartDirective = false;
Set<Source> seenPartSources = new Set<Source>();
FunctionElement entryPoint =
_findEntryPoint(definingCompilationUnitElement);
List<Directive> directivesToResolve = <Directive>[];
List<CompilationUnitElementImpl> sourcedCompilationUnits =
<CompilationUnitElementImpl>[];
NodeList<Directive> directives = definingCompilationUnit.directives;
int directiveLength = directives.length;
for (int i = 0; i < directiveLength; i++) {
Directive directive = directives[i];
if (directive is LibraryDirective) {
libraryNameNode = directive.name;
directivesToResolve.add(directive);
} else if (directive is PartDirective) {
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 = directive.uriContent;
//
// Validate that the part source is unique in the library.
//
if (!seenPartSources.add(partSource)) {
errors.add(new AnalysisError(
librarySource,
partUri.offset,
partUri.length,
CompileTimeErrorCode.DUPLICATE_PART,
[partSource.uri]));
}
//
// Validate that the part contains a part-of directive with the same
// name as the library.
//
if (context.exists(partSource)) {
_NameOrSource nameOrSource = _getPartLibraryNameOrUri(
context, partSource, partUnit, directivesToResolve);
if (nameOrSource == null) {
errors.add(new AnalysisError(
librarySource,
partUri.offset,
partUri.length,
CompileTimeErrorCode.PART_OF_NON_PART,
[partUri.toSource()]));
} else {
String name = nameOrSource.name;
if (name != null) {
if (libraryNameNode == null) {
if (partsLibraryName == _UNKNOWN_LIBRARY_NAME) {
partsLibraryName = name;
} else if (partsLibraryName != name) {
partsLibraryName = null;
}
} else if (libraryNameNode.name != name) {
errors.add(new AnalysisError(
librarySource,
partUri.offset,
partUri.length,
StaticWarningCode.PART_OF_DIFFERENT_LIBRARY,
[libraryNameNode.name, name]));
}
} else {
Source source = nameOrSource.source;
if (source != librarySource) {
errors.add(new AnalysisError(
librarySource,
partUri.offset,
partUri.length,
StaticWarningCode.PART_OF_DIFFERENT_LIBRARY,
[librarySource.uri.toString(), source.uri.toString()]));
}
}
}
}
if (entryPoint == null) {
entryPoint = _findEntryPoint(partElement);
}
directive.element = partElement;
sourcedCompilationUnits.add(partElement);
}
}
}
if (hasPartDirective &&
libraryNameNode == null &&
!context.analysisOptions.enableUriInPartOf) {
errors.add(new AnalysisError(librarySource, 0, 0,
ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART));
}
//
// Create and populate the library element.
//
AnalysisContext owningContext = context;
if (context is InternalAnalysisContext) {
InternalAnalysisContext internalContext = context;
owningContext = internalContext.getContextFor(librarySource);
}
//
// 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;
}
}
//
// Create a new LibraryElement.
//
if (libraryElement == null) {
libraryElement =
new LibraryElementImpl.forNode(owningContext, libraryNameNode);
libraryElement.isSynthetic = 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.
//
outputs[BUILD_LIBRARY_ERRORS] = errors;
outputs[LIBRARY_ELEMENT1] = libraryElement;
outputs[IS_LAUNCHABLE] = entryPoint != null;
}
/**
* Return the top-level [FunctionElement] entry point, or `null` if the given
* [element] does not define an entry point.
*/
FunctionElement _findEntryPoint(CompilationUnitElementImpl element) {
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;
}
}
return null;
}
/**
* Return the name of the library that the given part is declared to be a
* part of, or `null` if the part does not contain a part-of directive.
*/
_NameOrSource _getPartLibraryNameOrUri(
AnalysisContext context,
Source partSource,
CompilationUnit partUnit,
List<Directive> directivesToResolve) {
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;
if (libraryName != null) {
return new _NameOrSource(libraryName.name, null);
}
String uri = directive.uri?.stringValue;
if (uri != null) {
Source librarySource =
context.sourceFactory.resolveUri(partSource, uri);
if (librarySource != null) {
return new _NameOrSource(null, librarySource);
}
}
}
}
return null;
}
/**
* Return `true` if the given compilation [unit] contains at least one
* import directive with a `dart-ext:` URI.
*/
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;
}
/**
* 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) {
Source source = target;
return <String, TaskInput>{
DEFINING_UNIT_INPUT:
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)
};
}
/**
* Create a [BuildLibraryElementTask] based on the given [target] in the
* given [context].
*/
static BuildLibraryElementTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new BuildLibraryElementTask(context, target);
}
}
/**
* A task that builds [PUBLIC_NAMESPACE] for a library.
*/
class BuildPublicNamespaceTask extends SourceBasedAnalysisTask {
/**
* The name of the input for [LIBRARY_ELEMENT2] of a library.
*/
static const String LIBRARY_INPUT = 'LIBRARY_INPUT';
/**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'BuildPublicNamespaceTask',
createTask,
buildInputs,
<ResultDescriptor>[LIBRARY_ELEMENT3]);
BuildPublicNamespaceTask(
InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
LibraryElementImpl library = getRequiredInput(LIBRARY_INPUT);
NamespaceBuilder builder = new NamespaceBuilder();
library.publicNamespace = builder.createPublicNamespaceForLibrary(library);
outputs[LIBRARY_ELEMENT3] = 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 library [libSource].
*/
static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
Source source = target;
return <String, TaskInput>{LIBRARY_INPUT: LIBRARY_ELEMENT2.of(source)};
}
/**
* Create a [BuildPublicNamespaceTask] based on the given [target] in
* the given [context].
*/
static BuildPublicNamespaceTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new BuildPublicNamespaceTask(context, target);
}
}
/**
* A task that builds [EXPORT_SOURCE_CLOSURE] of a library.
*/
class BuildSourceExportClosureTask extends SourceBasedAnalysisTask {
/**
* The name of the export closure.
*/
static const String EXPORT_INPUT = 'EXPORT_INPUT';
/**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'BuildSourceExportClosureTask',
createTask,
buildInputs,
<ResultDescriptor>[EXPORT_SOURCE_CLOSURE]);
BuildSourceExportClosureTask(
InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
List<Source> exportClosure = getRequiredInput(EXPORT_INPUT);
//
// Record output.
//
outputs[EXPORT_SOURCE_CLOSURE] = exportClosure;
}
/**
* 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>{
EXPORT_INPUT: new _ExportSourceClosureTaskInput(source, LIBRARY_ELEMENT2)
};
}
/**
* Create a [BuildSourceExportClosureTask] based on the given [target] in
* the given [context].
*/
static BuildSourceExportClosureTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new BuildSourceExportClosureTask(context, target);
}
}
/**
* A task that builds [TYPE_PROVIDER] for a context.
*/
class BuildTypeProviderTask extends SourceBasedAnalysisTask {
/**
* The [PUBLIC_NAMESPACE] input of the `dart:core` library.
*/
static const String CORE_INPUT = 'CORE_INPUT';
/**
* The [PUBLIC_NAMESPACE] input of the `dart:async` library.
*/
static const String ASYNC_INPUT = 'ASYNC_INPUT';
/**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'BuildTypeProviderTask',
createTask,
buildInputs,
<ResultDescriptor>[TYPE_PROVIDER]);
BuildTypeProviderTask(
InternalAnalysisContext context, AnalysisContextTarget target)
: super(context, target);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
LibraryElement coreLibrary = getRequiredInput(CORE_INPUT);
LibraryElement asyncLibrary = getOptionalInput(ASYNC_INPUT);
Namespace coreNamespace = coreLibrary.publicNamespace;
Namespace asyncNamespace = asyncLibrary.publicNamespace;
//
// Record outputs.
//
TypeProvider typeProvider =
new TypeProviderImpl.forNamespaces(coreNamespace, asyncNamespace);
(context as InternalAnalysisContext).typeProvider = typeProvider;
outputs[TYPE_PROVIDER] = typeProvider;
}
static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
AnalysisContextTarget contextTarget = target;
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)
};
}
/**
* Create a [BuildTypeProviderTask] based on the given [context].
*/
static BuildTypeProviderTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new BuildTypeProviderTask(context, target);
}
}
/**
* A task that computes [CONSTANT_DEPENDENCIES] for a constant.
*/
class ComputeConstantDependenciesTask extends ConstantEvaluationAnalysisTask {
/**
* The name of the [TYPE_PROVIDER] input.
*/
static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'ComputeConstantDependenciesTask',
createTask,
buildInputs,
<ResultDescriptor>[CONSTANT_DEPENDENCIES]);
ComputeConstantDependenciesTask(
InternalAnalysisContext context, ConstantEvaluationTarget constant)
: super(context, constant);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
//
// Prepare inputs.
//
ConstantEvaluationTarget constant = target;
TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
//
// Compute dependencies.
//
List<ConstantEvaluationTarget> dependencies = <ConstantEvaluationTarget>[];
new ConstantEvaluationEngine(typeProvider, context.declaredVariables,
typeSystem: context.typeSystem)
.computeDependencies(constant, dependencies.add);
//
// Record outputs.
//
outputs[CONSTANT_DEPENDENCIES] = dependencies;
}
/**
* 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) {
return <String, TaskInput>{
'constantExpressionResolved': CONSTANT_EXPRESSION_RESOLVED.of(target),
TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
};
}
/**
* Create a [ComputeConstantDependenciesTask] based on the given [target] in
* the given [context].
*/
static ComputeConstantDependenciesTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new ComputeConstantDependenciesTask(context, target);
}
}
/**
* A task that computes the value of a constant ([CONSTANT_VALUE]) and
* stores it in the element model.
*/
class ComputeConstantValueTask extends ConstantEvaluationAnalysisTask {
/**
* The name of the input which ensures that dependent constants are evaluated
* before the target.
*/
static const String DEPENDENCIES_INPUT = 'DEPENDENCIES_INPUT';
/**
* The name of the [TYPE_PROVIDER] input.
*/
static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT';
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'ComputeConstantValueTask',
createTask,
buildInputs,
<ResultDescriptor>[CONSTANT_VALUE]);
ComputeConstantValueTask(
InternalAnalysisContext context, ConstantEvaluationTarget constant)
: super(context, constant);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
bool get handlesDependencyCycles => true;
@override
void internalPerform() {
//
// Prepare inputs.
//
// Note: DEPENDENCIES_INPUT is not needed. It is merely a bookkeeping
// dependency to ensure that the constants that this constant depends on
// are computed first.
ConstantEvaluationTarget constant = target;
AnalysisContext context = constant.context;
TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
//
// Compute the value of the constant, or report an error if there was a
// cycle.
//
ConstantEvaluationEngine constantEvaluationEngine =
new ConstantEvaluationEngine(typeProvider, context.declaredVariables,
typeSystem: context.typeSystem);
if (dependencyCycle == null) {
constantEvaluationEngine.computeConstantValue(constant);
} else {
List<ConstantEvaluationTarget> constantsInCycle =
<ConstantEvaluationTarget>[];
int length = dependencyCycle.length;
for (int i = 0; i < length; i++) {
WorkItem workItem = dependencyCycle[i];
if (workItem.descriptor == DESCRIPTOR) {
AnalysisTarget target = workItem.target;
constantsInCycle.add(target);
if (target is ConstructorElementImpl) {
target.isCycleFree = false;
}
}
}
assert(constantsInCycle.isNotEmpty);
constantEvaluationEngine.generateCycleError(constantsInCycle, constant);
}
//
// Record outputs.
//
outputs[CONSTANT_VALUE] = constant;
}
/**
* 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) {
ConstantEvaluationTarget evaluationTarget = target;
return <String, TaskInput>{
DEPENDENCIES_INPUT:
CONSTANT_DEPENDENCIES.of(evaluationTarget).toListOf(CONSTANT_VALUE),
TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request)
};
}
/**
* Create a [ComputeConstantValueTask] based on the given [target] in the
* given [context].
*/
static ComputeConstantValueTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new ComputeConstantValueTask(context, target);
}
}
/**
* A task that computes the [INFERABLE_STATIC_VARIABLE_DEPENDENCIES] for a
* static variable whose type should be inferred.
*/
class ComputeInferableStaticVariableDependenciesTask
extends InferStaticVariableTask {
/**
* The name of the [RESOLVED_UNIT7] input.
*/
static const String UNIT_INPUT = 'UNIT_INPUT';
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'ComputeInferableStaticVariableDependenciesTask',
createTask,
buildInputs,
<ResultDescriptor>[INFERABLE_STATIC_VARIABLE_DEPENDENCIES]);
ComputeInferableStaticVariableDependenciesTask(
InternalAnalysisContext context, VariableElement variable)
: super(context, variable);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
//
// Prepare inputs.
//
CompilationUnit unit = getRequiredInput(UNIT_INPUT);
//
// Compute dependencies.
//
VariableDeclaration declaration = getDeclaration(unit);
VariableGatherer gatherer = new VariableGatherer(_isInferableStatic);
declaration.initializer.accept(gatherer);
//
// Record outputs.
//
outputs[INFERABLE_STATIC_VARIABLE_DEPENDENCIES] = gatherer.results.toList();
}
/**
* Return `true` if the given [variable] is a static variable whose type
* should be inferred.
*/
bool _isInferableStatic(VariableElement variable) =>
variable.isStatic &&
variable.hasImplicitType &&
variable.initializer != null;
/**
* Return a map from the names of the inputs of this kind of task to the task
* input descriptors describing those inputs for a task with the
* given [target].
*/
static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
if (target is VariableElement) {
CompilationUnitElementImpl unit = target
.getAncestor((Element element) => element is CompilationUnitElement);
return <String, TaskInput>{
UNIT_INPUT: RESOLVED_UNIT7
.of(new LibrarySpecificUnit(unit.librarySource, unit.source))
};
}
throw new AnalysisException(
'Cannot build inputs for a ${target.runtimeType}');
}
/**
* Create a [ComputeInferableStaticVariableDependenciesTask] based on the
* given [target] in the given [context].
*/
static ComputeInferableStaticVariableDependenciesTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new ComputeInferableStaticVariableDependenciesTask(context, target);
}
}
/**
* A task that computes the [LIBRARY_CYCLE] for a
* library element. Also computes the [LIBRARY_CYCLE_UNITS] and the
* [LIBRARY_CYCLE_DEPENDENCIES].
*/
class ComputeLibraryCycleTask extends SourceBasedAnalysisTask {
/**
* The name of the [LIBRARY_ELEMENT2] input.
*/
static const String LIBRARY_ELEMENT_INPUT = 'LIBRARY_ELEMENT_INPUT';
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'ComputeLibraryCycleForUnitTask',
createTask,
buildInputs, <ResultDescriptor>[
LIBRARY_CYCLE,
LIBRARY_CYCLE_UNITS,
LIBRARY_CYCLE_DEPENDENCIES
]);
ComputeLibraryCycleTask(
InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@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.
LibraryElement library = getRequiredInput(LIBRARY_ELEMENT_INPUT);
if (context.analysisOptions.strongMode &&
!LibraryElementImpl.hasResolutionCapability(
library, LibraryResolutionCapability.resolvedTypeNames)) {
List<LibraryElement> component = library.libraryCycle;
Set<LibraryElement> filter = component.toSet();
Set<CompilationUnitElement> deps = new Set<CompilationUnitElement>();
void addLibrary(LibraryElement l) {
if (!filter.contains(l)) {
deps.addAll(l.units);
}
}
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).map(unitToLSU).toList();
outputs[LIBRARY_CYCLE_DEPENDENCIES] = deps.map(unitToLSU).toList();
} else {
outputs[LIBRARY_CYCLE] = [];
outputs[LIBRARY_CYCLE_UNITS] = [];
outputs[LIBRARY_CYCLE_DEPENDENCIES] = [];
}
}
/**
* 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 = target;
return <String, TaskInput>{
LIBRARY_ELEMENT_INPUT: LIBRARY_ELEMENT2.of(librarySource),
'resolveReachableLibraries': READY_LIBRARY_ELEMENT2.of(librarySource),
};
}
/**
* Create a [ComputeLibraryCycleTask] based on the
* given [target] in the given [context].
*/
static ComputeLibraryCycleTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new ComputeLibraryCycleTask(context, target);
}
}
/**
* 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].
*/
abstract class ConstantEvaluationAnalysisTask extends AnalysisTask {
/**
* Initialize a newly created task to perform analysis within the given
* [context] in order to produce results for the given [constant].
*/
ConstantEvaluationAnalysisTask(
AnalysisContext context, ConstantEvaluationTarget constant)
: super(context, constant);
@override
String get description {
Source source = target.source;
String sourceName = source == null ? '<unknown source>' : source.fullName;
return '${descriptor.name} for element $target in source $sourceName';
}
}
/**
* Interface for [AnalysisTarget]s for which constant evaluation can be
* performed.
*/
abstract class ConstantEvaluationTarget extends AnalysisTarget {
/**
* Return the [AnalysisContext] which should be used to evaluate this
* constant.
*/
AnalysisContext get context;
}
/**
* A task that computes a list of the libraries containing the target source.
*/
class ContainingLibrariesTask extends SourceBasedAnalysisTask {
/**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'ContainingLibrariesTask',
createTask,
buildInputs,
<ResultDescriptor>[CONTAINING_LIBRARIES]);
ContainingLibrariesTask(
InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
// TODO(brianwilkerson) This value can change as new libraries are analyzed
// so we need some way of making sure that this result is removed from the
// cache appropriately.
Source source = getRequiredSource();
outputs[CONTAINING_LIBRARIES] = context.getLibrariesContaining(source);
}
/**
* 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) {
return <String, TaskInput>{};
}
/**
* Create a [ContainingLibrariesTask] based on the given [target] in the given
* [context].
*/
static ContainingLibrariesTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new ContainingLibrariesTask(context, target);
}
}
/**
* A task that merges all of the errors for a single source into a single list
* of errors.
*/
class DartErrorsTask extends SourceBasedAnalysisTask {
/**
* The task descriptor describing this kind of task.
*/
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);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
List<List<AnalysisError>> errorLists = <List<AnalysisError>>[];
//
// Prepare inputs.
//
EnginePlugin enginePlugin = AnalysisEngine.instance.enginePlugin;
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));
}
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] = 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);
}
/**
* 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;
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
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
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) {
LibrarySpecificUnit unit = new LibrarySpecificUnit(library, source);
return result.of(unit);
});
}
return inputs;
}
/**
* Create a [DartErrorsTask] based on the given [target] in the given
* [context].
*/
static DartErrorsTask createTask(
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();
return ignoreInfo.ignoredAt(errorCode, errorLine);
}
return errors.where((AnalysisError e) => !isIgnored(e)).toList();
}
}
/**
* A task that builds [RESOLVED_UNIT12] for a unit.
*/
class EvaluateUnitConstantsTask extends SourceBasedAnalysisTask {
/**
* The name of the [RESOLVED_UNIT11] input.
*/
static const String UNIT_INPUT = 'UNIT_INPUT';
/**
* The name of the [CONSTANT_VALUE] input.
*/
static const String CONSTANT_VALUES = 'CONSTANT_VALUES';
/**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'EvaluateUnitConstantsTask',
createTask,
buildInputs,
<ResultDescriptor>[CREATED_RESOLVED_UNIT12, RESOLVED_UNIT12]);
EvaluateUnitConstantsTask(AnalysisContext context, LibrarySpecificUnit target)
: super(context, target);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
// 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_UNIT12] = unit;
outputs[CREATED_RESOLVED_UNIT12] = 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) {
LibrarySpecificUnit unit = target;
return <String, TaskInput>{
'libraryElement': LIBRARY_ELEMENT9.of(unit.library),
UNIT_INPUT: RESOLVED_UNIT11.of(unit),
CONSTANT_VALUES:
COMPILATION_UNIT_CONSTANTS.of(unit).toListOf(CONSTANT_VALUE),
'constantExpressionsDependencies':
CONSTANT_EXPRESSIONS_DEPENDENCIES.of(unit).toListOf(CONSTANT_VALUE)
};
}
/**
* Create an [EvaluateUnitConstantsTask] based on the given [target] in
* the given [context].
*/
static EvaluateUnitConstantsTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new EvaluateUnitConstantsTask(context, target);
}
}
/**
* A task that builds [USED_IMPORTED_ELEMENTS] for a unit.
*/
class GatherUsedImportedElementsTask extends SourceBasedAnalysisTask {
/**
* The name of the [RESOLVED_UNIT11] input.
*/
static const String UNIT_INPUT = 'UNIT_INPUT';
/**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'GatherUsedImportedElementsTask',
createTask,
buildInputs,
<ResultDescriptor>[USED_IMPORTED_ELEMENTS]);
GatherUsedImportedElementsTask(
InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
CompilationUnit unit = getRequiredInput(UNIT_INPUT);
CompilationUnitElement unitElement = unit.element;
LibraryElement libraryElement = unitElement.library;
//
// Prepare used imported elements.
//
GatherUsedImportedElementsVisitor visitor =
new GatherUsedImportedElementsVisitor(libraryElement);
unit.accept(visitor);
//
// Record outputs.
//
outputs[USED_IMPORTED_ELEMENTS] = visitor.usedElements;
}
/**
* 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_UNIT11.of(unit)};
}
/**
* Create a [GatherUsedImportedElementsTask] based on the given [target] in
* the given [context].
*/
static GatherUsedImportedElementsTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new GatherUsedImportedElementsTask(context, target);
}
}
/**
* A task that builds [USED_LOCAL_ELEMENTS] for a unit.
*/
class GatherUsedLocalElementsTask extends SourceBasedAnalysisTask {
/**
* The name of the [RESOLVED_UNIT11] input.
*/
static const String UNIT_INPUT = 'UNIT_INPUT';
/**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'GatherUsedLocalElementsTask',
createTask,
buildInputs,
<ResultDescriptor>[USED_LOCAL_ELEMENTS]);
GatherUsedLocalElementsTask(
InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
CompilationUnit unit = getRequiredInput(UNIT_INPUT);
CompilationUnitElement unitElement = unit.element;
LibraryElement libraryElement = unitElement.library;
//
// Prepare used local elements.
//
GatherUsedLocalElementsVisitor visitor =
new GatherUsedLocalElementsVisitor(libraryElement);
unit.accept(visitor);
//
// Record outputs.
//
outputs[USED_LOCAL_ELEMENTS] = visitor.usedElements;
}
/**
* 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_UNIT11.of(unit)};
}
/**
* Create a [GatherUsedLocalElementsTask] based on the given [target] in
* the given [context].
*/
static GatherUsedLocalElementsTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new GatherUsedLocalElementsTask(context, target);
}
}
/**
* A task that generates [HINTS] for a unit.
*/
class GenerateHintsTask extends SourceBasedAnalysisTask {
/**
* The name of the [RESOLVED_UNIT11] input.
*/
static const String RESOLVED_UNIT_INPUT = 'RESOLVED_UNIT';
/**
* The name of a list of [USED_LOCAL_ELEMENTS] for each library unit input.
*/
static const String USED_LOCAL_ELEMENTS_INPUT = 'USED_LOCAL_ELEMENTS';
/**
* The name of a list of [USED_IMPORTED_ELEMENTS] for each library unit input.
*/
static const String USED_IMPORTED_ELEMENTS_INPUT = 'USED_IMPORTED_ELEMENTS';
/**
* 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(
'GenerateHintsTask', createTask, buildInputs, <ResultDescriptor>[HINTS]);
GenerateHintsTask(InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
AnalysisOptions analysisOptions = context.analysisOptions;
if (!analysisOptions.hint) {
outputs[HINTS] = AnalysisError.NO_ERRORS;
return;
}
//
// Prepare collectors.
//
RecordingErrorListener errorListener = new RecordingErrorListener();
Source source = getRequiredSource();
ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
//
// Prepare inputs.
//
CompilationUnit unit = getRequiredInput(RESOLVED_UNIT_INPUT);
List<UsedImportedElements> usedImportedElementsList =
getRequiredInput(USED_IMPORTED_ELEMENTS_INPUT);
List<UsedLocalElements> usedLocalElementsList =
getRequiredInput(USED_LOCAL_ELEMENTS_INPUT);
CompilationUnitElement unitElement = unit.element;
LibraryElement libraryElement = unitElement.library;
TypeSystem typeSystem = context.typeSystem;
//
// Generate errors.
//
unit.accept(new DeadCodeVerifier(errorReporter, typeSystem: typeSystem));
// Verify imports.
{
ImportsVerifier verifier = new ImportsVerifier();
verifier.addImports(unit);
usedImportedElementsList.forEach(verifier.removeUsedElements);
verifier.generateDuplicateImportHints(errorReporter);
verifier.generateUnusedImportHints(errorReporter);
verifier.generateUnusedShownNameHints(errorReporter);
}
// Unused local elements.
{
UsedLocalElements usedElements =
new UsedLocalElements.merge(usedLocalElementsList);
UnusedLocalElementsVerifier visitor =
new UnusedLocalElementsVerifier(errorListener, usedElements);
unit.accept(visitor);
}
// Dart2js analysis.
if (analysisOptions.dart2jsHint) {
unit.accept(new Dart2JSVerifier(errorReporter));
}
// Dart best practices.
InheritanceManager inheritanceManager = new InheritanceManager(
libraryElement,
includeAbstractFromSuperclasses: true);
TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
unit.accept(new BestPracticesVerifier(
errorReporter, typeProvider, libraryElement, inheritanceManager,
typeSystem: typeSystem));
unit.accept(new OverrideVerifier(errorReporter, inheritanceManager));
// Find to-do comments.
new ToDoFinder(errorReporter).findIn(unit);
//
// Record outputs.
//
outputs[HINTS] = errorListener.errors;
}
/**
* 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;
Source libSource = unit.library;
return <String, TaskInput>{
RESOLVED_UNIT_INPUT: RESOLVED_UNIT.of(unit),
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)
};
}
/**
* Create a [GenerateHintsTask] based on the given [target] in
* the given [context].
*/
static GenerateHintsTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new GenerateHintsTask(context, target);
}
}
/**
* A task that generates [LINTS] for a unit.
*/
class GenerateLintsTask extends SourceBasedAnalysisTask {
/**
* The name of the [RESOLVED_UNIT] input.
*/
static const String RESOLVED_UNIT_INPUT = 'RESOLVED_UNIT';
/**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'GenerateLintsTask', createTask, buildInputs, <ResultDescriptor>[LINTS]);
GenerateLintsTask(InternalAnalysisContext context, AnalysisTarget target)
: super(context, target);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
AnalysisOptions analysisOptions = context.analysisOptions;
if (!analysisOptions.lint) {
outputs[LINTS] = AnalysisError.NO_ERRORS;
return;
}
//
// Prepare collectors.
//
RecordingErrorListener errorListener = new RecordingErrorListener();
Source source = getRequiredSource();
ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
//
// Prepare inputs.
//
CompilationUnit unit = getRequiredInput(RESOLVED_UNIT_INPUT);
//
// Generate lints.
//
List<AstVisitor> visitors = <AstVisitor>[];
bool timeVisits = analysisOptions.enableTiming;
List<Linter> linters = getLints(context);
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);
}
}
AstVisitor visitor = new ExceptionHandlingDelegatingAstVisitor(
visitors, ExceptionHandlingDelegatingAstVisitor.logException);
unit.accept(visitor);
//
// Record outputs.
//
outputs[LINTS] = errorListener.errors;
}
/**
* 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) =>
<String, TaskInput>{RESOLVED_UNIT_INPUT: RESOLVED_UNIT.of(target)};
/**
* Create a [GenerateLintsTask] based on the given [target] in
* the given [context].
*/
static GenerateLintsTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new GenerateLintsTask(context, target);
}
}
/**
* Information about analysis `//ignore:` and `//ignore_for_file` 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);
/**
* A regular expression for matching 'ignore_for_file' comments. Produces
* matches containing 2 groups. For example:
*
* * ['//ignore_for_file: error_code', 'error_code']
*
* Resulting codes may be in a list ('error_code_1,error_code2').
*/
static final RegExp _IGNORE_FOR_FILE_MATCHER =
new RegExp(r'//[ ]*ignore_for_file:(.*)$', multiLine: true);
final Map<int, List<String>> _ignoreMap = new HashMap<int, List<String>>();
final Set<String> _ignoreForFileSet = new HashSet<String>();
/**
* Whether this info object defines any ignores.
*/
bool get hasIgnores => ignores.isNotEmpty || _ignoreForFileSet.isNotEmpty;
/**
* Iterable of error codes ignored for the whole file.
*/
Iterable<String> get ignoreForFiles => _ignoreForFileSet;
/**
* 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);
}
/**
* Ignore these [errorCodes] in the whole file.
*/
void addAllForFile(Iterable<String> errorCodes) {
_ignoreForFileSet.addAll(errorCodes);
}
/**
* Test whether this [errorCode] is ignored at the given [line].
*/
bool ignoredAt(String errorCode, int line) =>
_ignoreForFileSet.contains(errorCode) ||
_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);
Iterable<Match> fileMatches = _IGNORE_FOR_FILE_MATCHER.allMatches(content);
if (matches.isEmpty && fileMatches.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());
LineInfo_Location location = info.getLocation(match.start);
int lineNumber = location.lineNumber;
String beforeMatch = content.substring(
info.getOffsetOfLine(lineNumber - 1),
info.getOffsetOfLine(lineNumber - 1) + location.columnNumber - 1);
if (beforeMatch.trim().isEmpty) {
// The comment is on its own line, so it refers to the next line.
ignoreInfo.addAll(lineNumber + 1, codes);
} else {
// The comment sits next to code, so it refers to its own line.
ignoreInfo.addAll(lineNumber, codes);
}
}
for (Match match in fileMatches) {
Iterable<String> codes = match
.group(1)
.split(',')
.map((String code) => code.trim().toLowerCase());
ignoreInfo.addAllForFile(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 {
/**
* 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_UNIT8] for the
* compilation unit.
*/
static const String UNIT_INPUT = 'UNIT_INPUT';
/**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'InferInstanceMembersInUnitTask',
createTask,
buildInputs,
<ResultDescriptor>[CREATED_RESOLVED_UNIT10, RESOLVED_UNIT10]);
/**
* Initialize a newly created task to build a library element for the given
* [unit] in the given [context].
*/
InferInstanceMembersInUnitTask(
InternalAnalysisContext context, LibrarySpecificUnit unit)
: super(context, unit);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
//
// Prepare inputs.
//
CompilationUnit unit = getRequiredInput(UNIT_INPUT);
TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT);
//
// Infer instance members.
//
if (context.analysisOptions.strongMode) {
var inheritanceManager = new InheritanceManager(
resolutionMap.elementDeclaredByCompilationUnit(unit).library);
InstanceMemberInferrer inferrer = new InstanceMemberInferrer(
typeProvider, (_) => inheritanceManager,
typeSystem: context.typeSystem);
inferrer.inferCompilationUnit(unit.element);
}
//
// Record outputs.
//
outputs[RESOLVED_UNIT10] = unit;
outputs[CREATED_RESOLVED_UNIT10] = 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_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.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.library)
.toListOf(CREATED_RESOLVED_UNIT10)
};
}
/**
* Create a [InferInstanceMembersInUnitTask] based on the given [target] in
* the given [context].
*/
static InferInstanceMembersInUnitTask createTask(
AnalysisContext context, AnalysisTarget target) {
return new InferInstanceMembersInUnitTask(context, target);
}
}
/**
* An abstract class that defines utility methods that are useful for tasks
* operating on static variables.
*/
abstract class InferStaticVariableTask extends ConstantEvaluationAnalysisTask {
InferStaticVariableTask(
InternalAnalysisContext context, VariableElement variable)
: super(context, variable);
/**
* Return the declaration of the target within the given compilation [unit].
* Throw an exception if the declaration cannot be found.
*/
VariableDeclaration getDeclaration(CompilationUnit unit) {
VariableElement variable = target;
int offset = variable.nameOffset;
AstNode node = new NodeLocator2(offset).searchWithin(unit);
if (node == null) {
Source variableSource = variable.source;
Source unitSource =
resolutionMap.elementDeclaredByCompilationUnit(unit).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 =
resolutionMap.elementDeclaredByCompilationUnit(unit).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} 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 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_UNIT8] for the
* compilation unit.
*/
static const String UNIT_INPUT = 'UNIT_INPUT';
/**
* The name of the [STATIC_VARIABLE_RESOLUTION_ERRORS] for all static
* variables in the compilation unit.
*/
static const String ERRORS_LIST_INPUT = 'INFERRED_VARIABLES_INPUT';
/**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'InferStaticVariableTypesInUnitTask',
createTask,
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
* [unit] in the given [context].
*/
InferStaticVariableTypesInUnitTask(
InternalAnalysisContext context, LibrarySpecificUnit unit)
: super(context, unit);
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@override
void internalPerform() {
//
// 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_UNIT8] = unit;
outputs[CREATED_RESOLVED_UNIT8] = true;
outputs[STATIC_VARIABLE_RESOLUTION_ERRORS_IN_UNIT] =
AnalysisError.mergeLists(errorLists);
}
/**
* 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>{
'inferredTypes': INFERABLE_STATIC_VARIABLES_IN_UNIT
.of(unit)
.toListOf(INFERRED_STATIC_VARIABLE),
ERRORS_LIST_INPUT: INFERABLE_STATIC_VARIABLES_IN_UNIT<