Linter Demo Errors: 1Warnings: 180File: /home/fstrocco/Dart/dart/benchmark/analyzer/lib/src/task/dart.dart // 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 'dart:math' as math; import 'package:analyzer/src/generated/ast.dart'; import 'package:analyzer/src/generated/element.dart'; import 'package:analyzer/src/generated/engine.dart' hide AnalysisTask; import 'package:analyzer/src/generated/error.dart'; import 'package:analyzer/src/generated/error_verifier.dart'; import 'package:analyzer/src/generated/java_engine.dart'; import 'package:analyzer/src/generated/parser.dart'; import 'package:analyzer/src/generated/resolver.dart'; import 'package:analyzer/src/generated/scanner.dart'; import 'package:analyzer/src/generated/sdk.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/generated/utilities_general.dart'; import 'package:analyzer/src/task/driver.dart'; import 'package:analyzer/src/task/general.dart'; import 'package:analyzer/task/dart.dart'; import 'package:analyzer/task/general.dart'; import 'package:analyzer/task/model.dart'; /** * The errors produced while resolving a library directives. * * The list will be empty if there were no errors, but will not be `null`. * * The result is only available for targets representing a Dart library. */ final ResultDescriptor> BUILD_DIRECTIVES_ERRORS = new ResultDescriptor>( 'BUILD_DIRECTIVES_ERRORS', AnalysisError.NO_ERRORS, contributesTo: DART_ERRORS); /** * The errors produced while building function type aliases. * * The list will be empty if there were no errors, but will not be `null`. * * The result is only available for targets representing a Dart library. */ final ResultDescriptor> BUILD_FUNCTION_TYPE_ALIASES_ERRORS = new ResultDescriptor>( 'BUILD_FUNCTION_TYPE_ALIASES_ERRORS', AnalysisError.NO_ERRORS, contributesTo: DART_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 targets representing a Dart library. */ final ResultDescriptor> BUILD_LIBRARY_ERRORS = new ResultDescriptor>( 'BUILD_LIBRARY_ERRORS', AnalysisError.NO_ERRORS, contributesTo: DART_ERRORS); /** * The [ClassElement]s of a [LibraryUnitTarget]. */ final ListResultDescriptor CLASS_ELEMENTS = new ListResultDescriptor('CLASS_ELEMENTS', null); /** * The element model associated with a single compilation unit. * * The result is only available for targets representing a Dart compilation unit. */ final ResultDescriptor COMPILATION_UNIT_ELEMENT = new ResultDescriptor( 'COMPILATION_UNIT_ELEMENT', null); /** * The [ConstructorElement]s of a [ClassElement]. */ final ResultDescriptor> CONSTRUCTORS = new ResultDescriptor>('CONSTRUCTORS', null); /** * The errors produced while building a [ClassElement] constructors. * * The list will be empty if there were no errors, but will not be `null`. * * The result is only available for targets representing a [ClassElement]. */ final ResultDescriptor> CONSTRUCTORS_ERRORS = new ResultDescriptor>( 'CONSTRUCTORS_ERRORS', AnalysisError.NO_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 targets representing a Dart library. */ final ListResultDescriptor EXPORT_SOURCE_CLOSURE = new ListResultDescriptor('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 targets representing a Dart compilation unit. */ final ResultDescriptor> HINTS = new ResultDescriptor>( 'HINT_ERRORS', AnalysisError.NO_ERRORS, contributesTo: DART_ERRORS); /** * The sources representing the import closure of a library. * The [Source]s include only library sources, not their units. * * The result is only available for targets representing a Dart library. */ final ListResultDescriptor IMPORT_SOURCE_CLOSURE = new ListResultDescriptor('IMPORT_SOURCE_CLOSURE', 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 targets representing a Dart library. */ final ResultDescriptor LIBRARY_ELEMENT1 = new ResultDescriptor('LIBRARY_ELEMENT1', null); /** * The partial [LibraryElement] associated with a library. * * In addition to [LIBRARY_ELEMENT1] [LibraryElement.imports] and * [LibraryElement.exports] are set. * * The result is only available for targets representing a Dart library. */ final ResultDescriptor LIBRARY_ELEMENT2 = new ResultDescriptor('LIBRARY_ELEMENT2', null); /** * The partial [LibraryElement] associated with a library. * * In addition to [LIBRARY_ELEMENT2] the [LibraryElement.publicNamespace] is set. * * The result is only available for targets representing a Dart library. */ final ResultDescriptor LIBRARY_ELEMENT3 = new ResultDescriptor('LIBRARY_ELEMENT3', null); /** * 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 targets representing a Dart library. */ final ResultDescriptor LIBRARY_ELEMENT4 = new ResultDescriptor('LIBRARY_ELEMENT4', null); /** * The partial [LibraryElement] associated with a library. * * [LIBRARY_ELEMENT4] plus [RESOLVED_UNIT4] for every unit. * * The result is only available for targets representing a Dart library. */ final ResultDescriptor LIBRARY_ELEMENT5 = new ResultDescriptor('LIBRARY_ELEMENT5', null); /** * 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 targets representing a Dart compilation unit. */ final ResultDescriptor> PARSE_ERRORS = new ResultDescriptor>( 'PARSE_ERRORS', AnalysisError.NO_ERRORS, contributesTo: DART_ERRORS); /** * The errors produced while resolving references. * * The list will be empty if there were no errors, but will not be `null`. * * The result is only available for targets representing a unit. */ final ResultDescriptor> RESOLVE_REFERENCES_ERRORS = new ResultDescriptor>( 'RESOLVE_REFERENCES_ERRORS', AnalysisError.NO_ERRORS, contributesTo: DART_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 targets representing a Dart library. */ final ResultDescriptor> RESOLVE_TYPE_NAMES_ERRORS = new ResultDescriptor>( 'RESOLVE_TYPE_NAMES_ERRORS', AnalysisError.NO_ERRORS, contributesTo: DART_ERRORS); /** * The partially resolved [CompilationUnit] associated with a unit. * * All declarations bound to the element defined by the declaration. * * The result is only available for targets representing a unit. */ final ResultDescriptor RESOLVED_UNIT1 = new ResultDescriptor('RESOLVED_UNIT1', null); /** * The partially resolved [CompilationUnit] associated with a unit. * * All the enum member elements are built. * * The result is only available for targets representing a unit. */ final ResultDescriptor RESOLVED_UNIT2 = new ResultDescriptor('RESOLVED_UNIT2', null); /** * The partially resolved [CompilationUnit] associated with a unit. * * All the function type aliases are resolved. * * The result is only available for targets representing a unit. */ final ResultDescriptor RESOLVED_UNIT3 = new ResultDescriptor('RESOLVED_UNIT3', null); /** * The partially resolved [CompilationUnit] associated with a unit. * * [RESOLVED_UNIT3] with resolved type names. * * The result is only available for targets representing a unit. */ final ResultDescriptor RESOLVED_UNIT4 = new ResultDescriptor('RESOLVED_UNIT4', null); /** * The partially resolved [CompilationUnit] associated with a unit. * * [RESOLVED_UNIT4] plus resolved local variables and formal parameters. * * The result is only available for targets representing a unit. */ final ResultDescriptor RESOLVED_UNIT5 = new ResultDescriptor('RESOLVED_UNIT5', null); /** * 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 targets representing a Dart compilation unit. */ final ResultDescriptor> SCAN_ERRORS = new ResultDescriptor>( 'SCAN_ERRORS', AnalysisError.NO_ERRORS, contributesTo: DART_ERRORS); /** * The [TypeProvider] of the context. */ final ResultDescriptor TYPE_PROVIDER = new ResultDescriptor('TYPE_PROVIDER', null); /** * The [UsedImportedElements] of a [LibraryUnitTarget]. */ final ResultDescriptor USED_IMPORTED_ELEMENTS = new ResultDescriptor('USED_IMPORTED_ELEMENTS', null); /** * The [UsedLocalElements] of a [LibraryUnitTarget]. */ final ResultDescriptor USED_LOCAL_ELEMENTS = new ResultDescriptor('USED_LOCAL_ELEMENTS', null); /** * 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 targets representing a Dart compilation unit. */ final ResultDescriptor> VERIFY_ERRORS = new ResultDescriptor>( 'VERIFY_ERRORS', AnalysisError.NO_ERRORS, contributesTo: DART_ERRORS); /** * A task that builds implicit constructors for a [ClassElement], or keeps * the existing explicit constructors if the class has them. */ class BuildClassConstructorsTask extends SourceBasedAnalysisTask { /** * The name of the [CONSTRUCTORS] input for the superclass. */ static const String SUPER_CONSTRUCTORS = 'SUPER_CONSTRUCTORS'; /** * The task descriptor describing this kind of task. */ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( 'BuildConstructorsForClassTask', createTask, buildInputs, [CONSTRUCTORS, CONSTRUCTORS_ERRORS]); BuildClassConstructorsTask( InternalAnalysisContext context, AnalysisTarget target) : super(context, target); @override TaskDescriptor get descriptor => DESCRIPTOR; @override void internalPerform() { List errors = []; // // Prepare inputs. // ClassElementImpl classElement = this.target; List superConstructors = inputs[SUPER_CONSTRUCTORS]; DartType superType = classElement.supertype; ClassElement superElement = superType.element; // // Shortcut for ClassElement(s) without implicit constructors. // if (superConstructors == null) { outputs[CONSTRUCTORS] = classElement.constructors; outputs[CONSTRUCTORS_ERRORS] = AnalysisError.NO_ERRORS; return; } // // ClassTypeAlias // if (classElement.isTypedef) { List implicitConstructors = new List(); void callback(ConstructorElement explicitConstructor, List parameterTypes, List argumentTypes) { implicitConstructors.add(_createImplicitContructor(classElement.type, explicitConstructor, parameterTypes, argumentTypes)); } if (_findForwardedConstructors(classElement, superType, callback)) { if (implicitConstructors.isEmpty) { errors.add(new AnalysisError.con2(classElement.source, classElement.nameOffset, classElement.name.length, CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS, [superElement.name])); } else { classElement.constructors = implicitConstructors; } } outputs[CONSTRUCTORS] = classElement.constructors; outputs[CONSTRUCTORS_ERRORS] = errors; } // // ClassDeclaration // if (!classElement.isTypedef) { bool constructorFound = false; void callback(ConstructorElement explicitConstructor, List parameterTypes, List argumentTypes) { constructorFound = true; } if (_findForwardedConstructors(classElement, superType, callback) && !constructorFound) { SourceRange withRange = classElement.withClauseRange; errors.add(new AnalysisError.con2(classElement.source, withRange.offset, withRange.length, CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS, [superElement.name])); classElement.mixinErrorsReported = true; } outputs[CONSTRUCTORS] = classElement.constructors; outputs[CONSTRUCTORS_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 [classElement]. */ static Map buildInputs(ClassElement classElement) { // TODO(scheglov) Here we implicitly depend on LIBRARY_ELEMENT5, i.e. that // "supertype" for the "classElement" is set. // We need to make it an explicit dependency. DartType superType = classElement.supertype; if (superType is InterfaceType) { if (classElement.isTypedef || classElement.mixins.isNotEmpty) { ClassElement superElement = superType.element; return { SUPER_CONSTRUCTORS: CONSTRUCTORS.of(superElement) }; } } // No implicit constructors, no inputs required. return {}; } /** * Create a [BuildClassConstructorsTask] based on the given * [target] in the given [context]. */ static BuildClassConstructorsTask createTask( AnalysisContext context, AnalysisTarget target) { return new BuildClassConstructorsTask(context, target); } /** * Create an implicit constructor that is copied from the given * [explicitConstructor], but that is in the given class. * * [classType] - the class in which the implicit constructor is defined. * [explicitConstructor] - the constructor on which the implicit constructor * is modeled. * [parameterTypes] - the types to be replaced when creating parameters. * [argumentTypes] - the types with which the parameters are to be replaced. */ static ConstructorElement _createImplicitContructor(InterfaceType classType, ConstructorElement explicitConstructor, List parameterTypes, List argumentTypes) { ConstructorElementImpl implicitConstructor = new ConstructorElementImpl(explicitConstructor.name, -1); implicitConstructor.synthetic = true; implicitConstructor.redirectedConstructor = explicitConstructor; implicitConstructor.const2 = explicitConstructor.isConst; implicitConstructor.returnType = classType; List explicitParameters = explicitConstructor.parameters; int count = explicitParameters.length; if (count > 0) { List implicitParameters = new List(count); for (int i = 0; i < count; i++) { ParameterElement explicitParameter = explicitParameters[i]; ParameterElementImpl implicitParameter = new ParameterElementImpl(explicitParameter.name, -1); implicitParameter.const3 = explicitParameter.isConst; implicitParameter.final2 = explicitParameter.isFinal; implicitParameter.parameterKind = explicitParameter.parameterKind; implicitParameter.synthetic = true; implicitParameter.type = explicitParameter.type.substitute2(argumentTypes, parameterTypes); implicitParameters[i] = implicitParameter; } implicitConstructor.parameters = implicitParameters; } FunctionTypeImpl type = new FunctionTypeImpl.con1(implicitConstructor); type.typeArguments = classType.typeArguments; implicitConstructor.type = type; return implicitConstructor; } /** * Find all the constructors that should be forwarded from the given * [superType], to the class or mixin application [classElement], * and pass information about them to [callback]. * * Return true if some constructors were considered. (A false return value * can only happen if the supeclass is a built-in type, in which case it * can't be used as a mixin anyway). */ static bool _findForwardedConstructors(ClassElementImpl classElement, InterfaceType superType, void callback( ConstructorElement explicitConstructor, List parameterTypes, List argumentTypes)) { ClassElement superclassElement = superType.element; List constructors = superclassElement.constructors; int count = constructors.length; if (count == 0) { return false; } List parameterTypes = TypeParameterTypeImpl.getTypes(superType.typeParameters); List argumentTypes = _getArgumentTypes(superType, parameterTypes); for (int i = 0; i < count; i++) { ConstructorElement explicitConstructor = constructors[i]; if (!explicitConstructor.isFactory && classElement.isSuperConstructorAccessible(explicitConstructor)) { callback(explicitConstructor, parameterTypes, argumentTypes); } } return true; } /** * Return a list of argument types that corresponds to the [parameterTypes] * and that are derived from the type arguments of the given [superType]. */ static List _getArgumentTypes( InterfaceType superType, List parameterTypes) { DynamicTypeImpl dynamic = DynamicTypeImpl.instance; int parameterCount = parameterTypes.length; List types = new List(parameterCount); if (superType == null) { types = new List.filled(parameterCount, dynamic); } else { List typeArguments = superType.typeArguments; int argumentCount = math.min(typeArguments.length, parameterCount); for (int i = 0; i < argumentCount; i++) { types[i] = typeArguments[i]; } for (int i = argumentCount; i < parameterCount; i++) { types[i] = dynamic; } } return types; } } /** * 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 line information for the * compilation unit. */ static const String LINE_INFO_INPUT_NAME = 'LINE_INFO_INPUT_NAME'; /** * 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 task descriptor describing this kind of task. */ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( 'BuildCompilationUnitElementTask', createTask, buildInputs, [ CLASS_ELEMENTS, COMPILATION_UNIT_ELEMENT, 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. // Source source = getRequiredSource(); CompilationUnit unit = getRequiredInput(PARSED_UNIT_INPUT_NAME); // // Process inputs. // unit = AstCloner.clone(unit); CompilationUnitBuilder builder = new CompilationUnitBuilder(); CompilationUnitElement element = builder.buildCompilationUnit(source, unit); // // Record outputs. // outputs[CLASS_ELEMENTS] = element.types; outputs[COMPILATION_UNIT_ELEMENT] = element; outputs[RESOLVED_UNIT1] = 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 buildInputs(LibraryUnitTarget target) { return { PARSED_UNIT_INPUT_NAME: PARSED_UNIT.of(target.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 for [RESOLVED_UNIT1] of a library unit. */ static const String UNIT_INPUT_NAME = 'UNIT_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, [ LIBRARY_ELEMENT2, BUILD_DIRECTIVES_ERRORS ]); BuildDirectiveElementsTask( InternalAnalysisContext context, AnalysisTarget target) : super(context, target); @override TaskDescriptor get descriptor => DESCRIPTOR; @override void internalPerform() { List errors = []; // // Prepare inputs. // CompilationUnit libraryUnit = getRequiredInput(UNIT_INPUT_NAME); Map importLibraryMap = getRequiredInput(IMPORTS_LIBRARY_ELEMENT_INPUT_NAME); Map exportLibraryMap = getRequiredInput(EXPORTS_LIBRARY_ELEMENT_INPUT_NAME); Map importSourceKindMap = getRequiredInput(IMPORTS_SOURCE_KIND_INPUT_NAME); Map exportSourceKindMap = getRequiredInput(EXPORTS_SOURCE_KIND_INPUT_NAME); // // Process inputs. // LibraryElementImpl libraryElement = libraryUnit.element.library; Source librarySource = libraryElement.source; // // Resolve directives. // HashMap nameToPrefixMap = new HashMap(); List imports = []; List exports = []; bool explicitlyImportsCore = false; for (Directive directive in libraryUnit.directives) { if (directive is ImportDirective) { ImportDirective importDirective = directive; String uriContent = importDirective.uriContent; if (DartUriResolver.isDartExtUri(uriContent)) { libraryElement.hasExtUri = true; } Source importedSource = importDirective.source; if (importedSource != null && context.exists(importedSource)) { // The imported source will be null if the URI in the import // directive was invalid. LibraryElement importedLibrary = importLibraryMap[importedSource]; if (importedLibrary != null) { ImportElementImpl importElement = new ImportElementImpl(directive.offset); StringLiteral uriLiteral = importDirective.uri; if (uriLiteral != null) { importElement.uriOffset = uriLiteral.offset; importElement.uriEnd = uriLiteral.end; } importElement.uri = uriContent; importElement.deferred = importDirective.deferredKeyword != null; importElement.combinators = _buildCombinators(importDirective); importElement.importedLibrary = importedLibrary; SimpleIdentifier prefixNode = directive.prefix; if (prefixNode != null) { importElement.prefixOffset = prefixNode.offset; String prefixName = prefixNode.name; PrefixElementImpl prefix = nameToPrefixMap[prefixName]; if (prefix == null) { prefix = new PrefixElementImpl.forNode(prefixNode); nameToPrefixMap[prefixName] = prefix; } importElement.prefix = prefix; prefixNode.staticElement = prefix; } directive.element = importElement; imports.add(importElement); if (importSourceKindMap[importedSource] != SourceKind.LIBRARY) { ErrorCode errorCode = (importElement.isDeferred ? StaticWarningCode.IMPORT_OF_NON_LIBRARY : CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY); errors.add(new AnalysisError.con2(importedSource, uriLiteral.offset, uriLiteral.length, errorCode, [uriLiteral.toSource()])); } } } } else if (directive is ExportDirective) { ExportDirective exportDirective = directive; Source exportedSource = exportDirective.source; if (exportedSource != null && context.exists(exportedSource)) { // The exported source will be null if the URI in the export // directive was invalid. LibraryElement exportedLibrary = exportLibraryMap[exportedSource]; if (exportedLibrary != null) { ExportElementImpl exportElement = new ExportElementImpl(directive.offset); StringLiteral uriLiteral = exportDirective.uri; if (uriLiteral != null) { exportElement.uriOffset = uriLiteral.offset; exportElement.uriEnd = uriLiteral.end; } exportElement.uri = exportDirective.uriContent; exportElement.combinators = _buildCombinators(exportDirective); exportElement.exportedLibrary = exportedLibrary; directive.element = exportElement; exports.add(exportElement); if (exportSourceKindMap[exportedSource] != SourceKind.LIBRARY) { errors.add(new AnalysisError.con2(exportedSource, uriLiteral.offset, uriLiteral.length, CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, [uriLiteral.toSource()])); } } } } } // // Ensure "dart:core" import. // Source coreLibrarySource = context.sourceFactory.forUri(DartSdk.DART_CORE); if (!explicitlyImportsCore && coreLibrarySource != librarySource) { ImportElementImpl importElement = new ImportElementImpl(-1); importElement.importedLibrary = importLibraryMap[coreLibrarySource]; importElement.synthetic = true; imports.add(importElement); } // // Populate the library element. // libraryElement.imports = imports; libraryElement.exports = exports; // // 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 buildInputs(Source libSource) { return { 'defining_LIBRARY_ELEMENT1': LIBRARY_ELEMENT1.of(libSource), UNIT_INPUT_NAME: RESOLVED_UNIT1.of(new LibraryUnitTarget(libSource, libSource)), IMPORTS_LIBRARY_ELEMENT_INPUT_NAME: IMPORTED_LIBRARIES.of(libSource).toMapOf(LIBRARY_ELEMENT1), EXPORTS_LIBRARY_ELEMENT_INPUT_NAME: EXPORTED_LIBRARIES.of(libSource).toMapOf(LIBRARY_ELEMENT1), IMPORTS_SOURCE_KIND_INPUT_NAME: IMPORTED_LIBRARIES.of(libSource).toMapOf(SOURCE_KIND), EXPORTS_SOURCE_KIND_INPUT_NAME: EXPORTED_LIBRARIES.of(libSource).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); } /** * Build the element model representing the combinators declared by * the given [directive]. */ static List _buildCombinators( NamespaceDirective directive) { List combinators = []; for (Combinator combinator in directive.combinators) { if (combinator is ShowCombinator) { ShowElementCombinatorImpl show = new ShowElementCombinatorImpl(); show.offset = combinator.offset; show.end = combinator.end; show.shownNames = _getIdentifiers(combinator.shownNames); combinators.add(show); } else if (combinator is HideCombinator) { HideElementCombinatorImpl hide = new HideElementCombinatorImpl(); hide.hiddenNames = _getIdentifiers(combinator.hiddenNames); combinators.add(hide); } } return combinators; } /** * Return the lexical identifiers associated with the given [identifiers]. */ static List _getIdentifiers(NodeList identifiers) { return identifiers.map((identifier) => identifier.name).toList(); } } /** * 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, [RESOLVED_UNIT2]); 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); // // Record outputs. // EnumMemberBuilder builder = new EnumMemberBuilder(typeProvider); unit.accept(builder); outputs[RESOLVED_UNIT2] = unit; } /** * Return a map from the names of the inputs of this kind of task to the task * input descriptors describing those inputs for a task with the * given [target]. */ static Map buildInputs(LibraryUnitTarget target) { return { TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request), UNIT_INPUT: RESOLVED_UNIT1.of(target) }; } /** * 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, [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. // ExportNamespaceBuilder builder = new ExportNamespaceBuilder(); Namespace namespace = builder.build(library); library.exportNamespace = namespace; // // Update entry point. // if (library.entryPoint == null) { Iterable 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 buildInputs(Source libSource) { return { LIBRARY_INPUT: LIBRARY_ELEMENT3.of(libSource), 'exportsLibraryPublicNamespace': EXPORT_SOURCE_CLOSURE.of(libSource).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 [RESOLVED_UNIT3] for a unit. */ class BuildFunctionTypeAliasesTask extends SourceBasedAnalysisTask { /** * The name of the [TYPE_PROVIDER] input. */ static const String TYPE_PROVIDER_INPUT = 'TYPE_PROVIDER_INPUT'; /** * The name of the [LIBRARY_ELEMENT4] input. */ static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; /** * The name of the [RESOLVED_UNIT2] input. */ static const String UNIT_INPUT = 'UNIT_INPUT'; /** * The task descriptor describing this kind of task. */ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( 'BuildFunctionTypeAliasesTask', createTask, buildInputs, [BUILD_FUNCTION_TYPE_ALIASES_ERRORS, RESOLVED_UNIT3]); BuildFunctionTypeAliasesTask( InternalAnalysisContext context, AnalysisTarget target) : super(context, target); @override TaskDescriptor get descriptor => DESCRIPTOR; @override void internalPerform() { RecordingErrorListener errorListener = new RecordingErrorListener(); // // Prepare inputs. // Source source = getRequiredSource(); TypeProvider typeProvider = getRequiredInput(TYPE_PROVIDER_INPUT); CompilationUnit unit = getRequiredInput(UNIT_INPUT); LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT); // // Resolve FunctionTypeAlias declarations. // TypeResolverVisitor visitor = new TypeResolverVisitor.con2( libraryElement, source, typeProvider, errorListener); for (CompilationUnitMember member in unit.declarations) { if (member is FunctionTypeAlias) { member.accept(visitor); } } // // Record outputs. // outputs[BUILD_FUNCTION_TYPE_ALIASES_ERRORS] = errorListener.errors; 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 buildInputs(LibraryUnitTarget target) { return { TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request), 'importsExportNamespace': IMPORTED_LIBRARIES.of(target.library).toMapOf(LIBRARY_ELEMENT4), LIBRARY_INPUT: LIBRARY_ELEMENT4.of(target.library), UNIT_INPUT: RESOLVED_UNIT2.of(target) }; } /** * Create a [BuildFunctionTypeAliasesTask] based on the given [target] in * the given [context]. */ static BuildFunctionTypeAliasesTask createTask( AnalysisContext context, AnalysisTarget target) { return new BuildFunctionTypeAliasesTask(context, target); } } /** * This task finishes building [LIBRARY_ELEMENT] by forcing building * constructors for classes in the defining and part units of a library. */ class BuildLibraryConstructorsTask extends SourceBasedAnalysisTask { /** * The name of the [LIBRARY_ELEMENT5] input. */ static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; /** * The task descriptor describing this kind of task. */ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( 'BuildLibraryConstructorsTask', createTask, buildInputs, [LIBRARY_ELEMENT]); BuildLibraryConstructorsTask( InternalAnalysisContext context, AnalysisTarget target) : super(context, target); @override TaskDescriptor get descriptor => DESCRIPTOR; @override void internalPerform() { LibraryElement library = getRequiredInput(LIBRARY_INPUT); outputs[LIBRARY_ELEMENT] = library; } /** * Return a map from the names of the inputs of this kind of task to the task * input descriptors describing those inputs for a task with the * given [target]. */ static Map buildInputs(Source libSource) { return { LIBRARY_INPUT: LIBRARY_ELEMENT5.of(libSource), 'resolvedConstructors': CLASS_ELEMENTS.of(libSource).toListOf(CONSTRUCTORS), }; } /** * Create a [BuildLibraryConstructorsTask] based on the given [target] in * the given [context]. */ static BuildLibraryConstructorsTask createTask( AnalysisContext context, AnalysisTarget target) { return new BuildLibraryConstructorsTask(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 task descriptor describing this kind of task. */ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( 'BuildLibraryElementTask', createTask, buildInputs, [ BUILD_LIBRARY_ERRORS, CLASS_ELEMENTS, 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 errors = []; // // Prepare inputs. // Source librarySource = getRequiredSource(); CompilationUnit definingCompilationUnit = getRequiredInput(DEFINING_UNIT_INPUT); List partUnits = getRequiredInput(PARTS_UNIT_INPUT); // // Process inputs. // CompilationUnitElementImpl definingCompilationUnitElement = definingCompilationUnit.element; Map partUnitMap = new HashMap(); for (CompilationUnit partUnit in partUnits) { Source partSource = partUnit.element.source; partUnitMap[partSource] = partUnit; } // // Update "part" directives. // LibraryIdentifier libraryNameNode = null; String partsLibraryName = _UNKNOWN_LIBRARY_NAME; bool hasPartDirective = false; FunctionElement entryPoint = _findEntryPoint(definingCompilationUnitElement); List directivesToResolve = []; List sourcedCompilationUnits = []; for (Directive directive in definingCompilationUnit.directives) { if (directive is LibraryDirective) { if (libraryNameNode == null) { libraryNameNode = directive.name; directivesToResolve.add(directive); } } else if (directive is PartDirective) { PartDirective partDirective = directive; StringLiteral partUri = partDirective.uri; Source partSource = partDirective.source; if (context.exists(partSource)) { hasPartDirective = true; CompilationUnit partUnit = partUnitMap[partSource]; CompilationUnitElementImpl partElement = partUnit.element; partElement.uriOffset = partUri.offset; partElement.uriEnd = partUri.end; partElement.uri = partDirective.uriContent; // // Validate that the part contains a part-of directive with the same // name as the library. // String partLibraryName = _getPartLibraryName(partSource, partUnit, directivesToResolve); if (partLibraryName == null) { errors.add(new AnalysisError.con2(librarySource, partUri.offset, partUri.length, CompileTimeErrorCode.PART_OF_NON_PART, [partUri.toSource()])); } else if (libraryNameNode == null) { if (partsLibraryName == _UNKNOWN_LIBRARY_NAME) { partsLibraryName = partLibraryName; } else if (partsLibraryName != partLibraryName) { partsLibraryName = null; } } else if (libraryNameNode.name != partLibraryName) { errors.add(new AnalysisError.con2(librarySource, partUri.offset, partUri.length, StaticWarningCode.PART_OF_DIFFERENT_LIBRARY, [ libraryNameNode.name, partLibraryName ])); } if (entryPoint == null) { entryPoint = _findEntryPoint(partElement); } directive.element = partElement; sourcedCompilationUnits.add(partElement); } } } if (hasPartDirective && libraryNameNode == null) { AnalysisError error; if (partsLibraryName != _UNKNOWN_LIBRARY_NAME && partsLibraryName != null) { error = new AnalysisErrorWithProperties.con1(librarySource, ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART) ..setProperty(ErrorProperty.PARTS_LIBRARY_NAME, partsLibraryName); } else { error = new AnalysisError.con1(librarySource, ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART); } errors.add(error); } // // Create and populate the library element. // LibraryElementImpl libraryElement = new LibraryElementImpl.forNode(context, libraryNameNode); libraryElement.definingCompilationUnit = definingCompilationUnitElement; libraryElement.entryPoint = entryPoint; libraryElement.parts = sourcedCompilationUnits; for (Directive directive in directivesToResolve) { directive.element = libraryElement; } if (sourcedCompilationUnits.isNotEmpty) { _patchTopLevelAccessors(libraryElement); } // // Prepare all class elements. // List classElements = libraryElement.units .map((CompilationUnitElement unitElement) => unitElement.types) .expand((List unitClassElements) => unitClassElements) .toList(); // // Record outputs. // outputs[BUILD_LIBRARY_ERRORS] = errors; outputs[CLASS_ELEMENTS] = classElements; outputs[LIBRARY_ELEMENT1] = libraryElement; outputs[IS_LAUNCHABLE] = entryPoint != null; } /** * Add all of the non-synthetic [getters] and [setters] defined in the given * [unit] that have no corresponding accessor to one of the given collections. */ void _collectAccessors(Map getters, List setters, CompilationUnitElement unit) { for (PropertyAccessorElement accessor in unit.accessors) { if (accessor.isGetter) { if (!accessor.isSynthetic && accessor.correspondingSetter == null) { getters[accessor.displayName] = accessor; } } else { if (!accessor.isSynthetic && accessor.correspondingGetter == null) { setters.add(accessor); } } } } /** * Return the top-level [FunctionElement] entry point, or `null` if the given * [element] does not define an entry point. */ FunctionElement _findEntryPoint(CompilationUnitElementImpl element) { for (FunctionElement function in element.functions) { 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. */ String _getPartLibraryName(Source partSource, CompilationUnit partUnit, List directivesToResolve) { for (Directive directive in partUnit.directives) { if (directive is PartOfDirective) { directivesToResolve.add(directive); LibraryIdentifier libraryName = directive.libraryName; if (libraryName != null) { return libraryName.name; } } } return null; } /** * Look through all of the compilation units defined for the given [library], * looking for getters and setters that are defined in different compilation * units but that have the same names. If any are found, make sure that they * have the same variable element. */ void _patchTopLevelAccessors(LibraryElementImpl library) { HashMap getters = new HashMap(); List setters = []; _collectAccessors(getters, setters, library.definingCompilationUnit); for (CompilationUnitElement unit in library.parts) { _collectAccessors(getters, setters, unit); } for (PropertyAccessorElementImpl setter in setters) { PropertyAccessorElement getter = getters[setter.displayName]; if (getter != null) { TopLevelVariableElementImpl variable = getter.variable; TopLevelVariableElementImpl setterVariable = setter.variable; CompilationUnitElementImpl setterUnit = setterVariable.enclosingElement; setterUnit.replaceTopLevelVariable(setterVariable, variable); variable.setter = setter; setter.variable = variable; } } } /** * Return a map from the names of the inputs of this kind of task to the task * input descriptors describing those inputs for a task with the given * [libSource]. */ static Map buildInputs(Source libSource) { return { DEFINING_UNIT_INPUT: RESOLVED_UNIT1.of(new LibraryUnitTarget(libSource, libSource)), PARTS_UNIT_INPUT: INCLUDED_PARTS.of(libSource).toList((Source unit) { LibraryUnitTarget lut = new LibraryUnitTarget(libSource, unit); return RESOLVED_UNIT1.of(lut); }) }; } /** * 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, [LIBRARY_ELEMENT3]); BuildPublicNamespaceTask( InternalAnalysisContext context, AnalysisTarget target) : super(context, target); @override TaskDescriptor get descriptor => DESCRIPTOR; @override void internalPerform() { LibraryElementImpl library = getRequiredInput(LIBRARY_INPUT); library.publicNamespace = new PublicNamespaceBuilder().build(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 buildInputs(Source libSource) { return {LIBRARY_INPUT: LIBRARY_ELEMENT2.of(libSource)}; } /** * 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 [IMPORT_SOURCE_CLOSURE] and [EXPORT_SOURCE_CLOSURE] of * a library. */ class BuildSourceClosuresTask extends SourceBasedAnalysisTask { /** * The name of the import closure. */ static const String IMPORT_CLOSURE_INPUT = 'IMPORT_CLOSURE_INPUT'; /** * The name of the export closure. */ static const String EXPORT_CLOSURE_INPUT = 'EXPORT_CLOSURE_INPUT'; /** * The task descriptor describing this kind of task. */ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( 'BuildExportSourceClosureTask', createTask, buildInputs, [ IMPORT_SOURCE_CLOSURE, EXPORT_SOURCE_CLOSURE, IS_CLIENT ]); BuildSourceClosuresTask( InternalAnalysisContext context, AnalysisTarget target) : super(context, target); @override TaskDescriptor get descriptor => DESCRIPTOR; @override void internalPerform() { List importClosure = getRequiredInput(IMPORT_CLOSURE_INPUT); List exportClosure = getRequiredInput(EXPORT_CLOSURE_INPUT); Source htmlSource = context.sourceFactory.forUri(DartSdk.DART_HTML); // // Record outputs. // outputs[IMPORT_SOURCE_CLOSURE] = importClosure; outputs[EXPORT_SOURCE_CLOSURE] = exportClosure; outputs[IS_CLIENT] = importClosure.contains(htmlSource); } /** * Return a map from the names of the inputs of this kind of task to the task * input descriptors describing those inputs for a task with the * given library [libSource]. */ static Map buildInputs(Source libSource) { return { IMPORT_CLOSURE_INPUT: new _ImportSourceClosureTaskInput(libSource), EXPORT_CLOSURE_INPUT: new _ExportSourceClosureTaskInput(libSource) }; } /** * Create a [BuildSourceClosuresTask] based on the given [target] in * the given [context]. */ static BuildSourceClosuresTask createTask( AnalysisContext context, AnalysisTarget target) { return new BuildSourceClosuresTask(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, [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 = getRequiredInput(ASYNC_INPUT); Namespace coreNamespace = coreLibrary.publicNamespace; Namespace asyncNamespace = asyncLibrary.publicNamespace; // // Record outputs. // TypeProvider typeProvider = new TypeProviderImpl.forNamespaces(coreNamespace, asyncNamespace); (context as ExtendedAnalysisContext).typeProvider = typeProvider; outputs[TYPE_PROVIDER] = typeProvider; } static Map buildInputs(AnalysisContextTarget target) { SourceFactory sourceFactory = target.context.sourceFactory; Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE); Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC); return { 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, AnalysisContextTarget target) { return new BuildTypeProviderTask(context, target); } } /** * The helper for building the export [Namespace] of a [LibraryElement]. */ class ExportNamespaceBuilder { /** * Build the export [Namespace] of the given [LibraryElement]. */ Namespace build(LibraryElement library) { return new Namespace( _createExportMapping(library, new HashSet())); } /** * Create a mapping table representing the export namespace of the given * [library]. * * The given [visitedElements] a set of libraries that do not need to be * visited when processing the export directives of the given library because * all of the names defined by them will be added by another library. */ HashMap _createExportMapping( LibraryElement library, HashSet visitedElements) { visitedElements.add(library); try { HashMap definedNames = new HashMap(); // Add names of the export directives. for (ExportElement element in library.exports) { LibraryElement exportedLibrary = element.exportedLibrary; if (exportedLibrary != null && !visitedElements.contains(exportedLibrary)) { // // The exported library will be null if the URI does not reference a // valid library. // HashMap exportedNames = _createExportMapping(exportedLibrary, visitedElements); exportedNames = _applyCombinators(exportedNames, element.combinators); definedNames.addAll(exportedNames); } } // Add names of the public namespace. { Namespace publicNamespace = library.publicNamespace; if (publicNamespace != null) { definedNames.addAll(publicNamespace.definedNames); } } return definedNames; } finally { visitedElements.remove(library); } } /** * Apply the given [combinators] to all of the names in [definedNames]. */ static HashMap _applyCombinators( HashMap definedNames, List combinators) { for (NamespaceCombinator combinator in combinators) { if (combinator is HideElementCombinator) { _hide(definedNames, combinator.hiddenNames); } else if (combinator is ShowElementCombinator) { definedNames = _show(definedNames, combinator.shownNames); } } return definedNames; } /** * Hide all of the [hiddenNames] by removing them from the given * [definedNames]. */ static void _hide( HashMap definedNames, List hiddenNames) { for (String name in hiddenNames) { definedNames.remove(name); definedNames.remove('$name='); } } /** * Show only the given [shownNames] by removing all other names from the given * [definedNames]. */ static HashMap _show( HashMap definedNames, List shownNames) { HashMap newNames = new HashMap(); for (String name in shownNames) { Element element = definedNames[name]; if (element != null) { newNames[name] = element; } String setterName = '$name='; element = definedNames[setterName]; if (element != null) { newNames[setterName] = element; } } return newNames; } } /** * A task that builds [USED_IMPORTED_ELEMENTS] for a unit. */ class GatherUsedImportedElementsTask extends SourceBasedAnalysisTask { /** * The name of the [RESOLVED_UNIT] 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, [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 buildInputs(LibraryUnitTarget target) { return {UNIT_INPUT: RESOLVED_UNIT.of(target)}; } /** * Create a [GatherUsedImportedElementsTask] based on the given [target] in * the given [context]. */ static GatherUsedImportedElementsTask createTask( AnalysisContext context, LibraryUnitTarget 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_UNIT] 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, [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 buildInputs(LibraryUnitTarget target) { return {UNIT_INPUT: RESOLVED_UNIT.of(target)}; } /** * Create a [GatherUsedLocalElementsTask] based on the given [target] in * the given [context]. */ static GatherUsedLocalElementsTask createTask( AnalysisContext context, LibraryUnitTarget target) { return new GatherUsedLocalElementsTask(context, target); } } /** * A task that generates [HINTS] for a unit. */ class GenerateHintsTask extends SourceBasedAnalysisTask { /** * The name of the [RESOLVED_UNIT] input. */ static const String UNIT_INPUT = 'UNIT_INPUT'; /** * 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 task descriptor describing this kind of task. */ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( 'GenerateHintsTask', createTask, buildInputs, [HINTS]); GenerateHintsTask(InternalAnalysisContext context, AnalysisTarget target) : super(context, target); @override TaskDescriptor get descriptor => DESCRIPTOR; @override void internalPerform() { RecordingErrorListener errorListener = new RecordingErrorListener(); Source source = getRequiredSource(); ErrorReporter errorReporter = new ErrorReporter(errorListener, source); // // Prepare inputs. // CompilationUnit unit = getRequiredInput(UNIT_INPUT); List usedImportedElementsList = getRequiredInput(USED_IMPORTED_ELEMENTS_INPUT); List usedLocalElementsList = getRequiredInput(USED_LOCAL_ELEMENTS_INPUT); CompilationUnitElement unitElement = unit.element; LibraryElement libraryElement = unitElement.library; // // Generate errors. // unit.accept(new DeadCodeVerifier(errorReporter)); // Verify imports. { ImportsVerifier verifier = new ImportsVerifier(); verifier.addImports(unit); usedImportedElementsList.forEach(verifier.removeUsedElements); verifier.generateDuplicateImportHints(errorReporter); verifier.generateUnusedImportHints(errorReporter); } // Unused local elements. { UsedLocalElements usedElements = new UsedLocalElements.merge(usedLocalElementsList); UnusedLocalElementsVerifier visitor = new UnusedLocalElementsVerifier(errorListener, usedElements); unitElement.accept(visitor); } // Dart2js analysis. if (context.analysisOptions.dart2jsHint) { unit.accept(new Dart2JSVerifier(errorReporter)); } // Dart best practices. InheritanceManager inheritanceManager = new InheritanceManager(libraryElement); TypeProvider typeProvider = context.typeProvider; unit.accept(new BestPracticesVerifier(errorReporter, typeProvider)); 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 buildInputs(LibraryUnitTarget target) { Source libSource = target.library; return { UNIT_INPUT: RESOLVED_UNIT.of(target), USED_LOCAL_ELEMENTS_INPUT: UNITS.of(libSource).toList((unit) { LibraryUnitTarget target = new LibraryUnitTarget(libSource, unit); return USED_LOCAL_ELEMENTS.of(target); }), USED_IMPORTED_ELEMENTS_INPUT: UNITS.of(libSource).toList((unit) { LibraryUnitTarget target = new LibraryUnitTarget(libSource, unit); return USED_IMPORTED_ELEMENTS.of(target); }) }; } /** * 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 pair of a library [Source] and a unit [Source] in this library. */ class LibraryUnitTarget implements AnalysisTarget { final Source library; final Source unit; LibraryUnitTarget(this.library, this.unit); @override int get hashCode { return JenkinsSmiHash.combine(library.hashCode, unit.hashCode); } @override Source get source => unit; @override bool operator ==(other) { return other is LibraryUnitTarget && other.library == library && other.unit == unit; } } /** * A task that parses the content of a Dart file, producing an AST structure. */ class ParseDartTask extends SourceBasedAnalysisTask { /** * The name of the input whose value is the line information produced for the * file. */ static const String LINE_INFO_INPUT_NAME = 'LINE_INFO_INPUT_NAME'; /** * The name of the input whose value is the token stream produced for the file. */ static const String TOKEN_STREAM_INPUT_NAME = 'TOKEN_STREAM_INPUT_NAME'; /** * The task descriptor describing this kind of task. */ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('ParseDartTask', createTask, buildInputs, [ EXPORTED_LIBRARIES, IMPORTED_LIBRARIES, INCLUDED_PARTS, PARSE_ERRORS, PARSED_UNIT, SOURCE_KIND, UNITS ]); /** * Initialize a newly created task to parse the content of the Dart file * associated with the given [target] in the given [context]. */ ParseDartTask(InternalAnalysisContext context, AnalysisTarget target) : super(context, target); @override TaskDescriptor get descriptor => DESCRIPTOR; @override void internalPerform() { Source source = getRequiredSource(); LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT_NAME); Token tokenStream = getRequiredInput(TOKEN_STREAM_INPUT_NAME); RecordingErrorListener errorListener = new RecordingErrorListener(); Parser parser = new Parser(source, errorListener); AnalysisOptions options = context.analysisOptions; parser.parseFunctionBodies = options.analyzeFunctionBodiesPredicate(source); CompilationUnit unit = parser.parseCompilationUnit(tokenStream); unit.lineInfo = lineInfo; bool hasNonPartOfDirective = false; bool hasPartOfDirective = false; HashSet exportedSources = new HashSet(); HashSet importedSources = new HashSet(); HashSet includedSources = new HashSet(); for (Directive directive in unit.directives) { if (directive is PartOfDirective) { hasPartOfDirective = true; } else { hasNonPartOfDirective = true; if (directive is UriBasedDirective) { Source referencedSource = resolveDirective(context, source, directive, errorListener); if (referencedSource != null) { if (directive is ExportDirective) { exportedSources.add(referencedSource); } else if (directive is ImportDirective) { importedSources.add(referencedSource); } else if (directive is PartDirective) { if (referencedSource != source) { includedSources.add(referencedSource); } } else { throw new AnalysisException( '$runtimeType failed to handle a ${directive.runtimeType}'); } } } } } // // Always include "dart:core" source. // Source coreLibrarySource = context.sourceFactory.forUri(DartSdk.DART_CORE); importedSources.add(coreLibrarySource); // // Compute kind. // SourceKind sourceKind = SourceKind.LIBRARY; if (!hasNonPartOfDirective && hasPartOfDirective) { sourceKind = SourceKind.PART; } // // Record outputs. // outputs[EXPORTED_LIBRARIES] = exportedSources.toList(); outputs[IMPORTED_LIBRARIES] = importedSources.toList(); outputs[INCLUDED_PARTS] = includedSources.toList(); outputs[PARSE_ERRORS] = errorListener.getErrorsForSource(source); outputs[PARSED_UNIT] = unit; outputs[SOURCE_KIND] = sourceKind; outputs[UNITS] = [source]..addAll(includedSources); } /** * Return a map from the names of the inputs of this kind of task to the task * input descriptors describing those inputs for a task with the given * [source]. */ static Map buildInputs(Source source) { return { LINE_INFO_INPUT_NAME: LINE_INFO.of(source), TOKEN_STREAM_INPUT_NAME: TOKEN_STREAM.of(source) }; } /** * Create a [ParseDartTask] based on the given [target] in the given * [context]. */ static ParseDartTask createTask( AnalysisContext context, AnalysisTarget target) { return new ParseDartTask(context, target); } /** * Return the result of resolving the URI of the given URI-based [directive] * against the URI of the given library, or `null` if the URI is not valid. * * Resolution is to be performed in the given [context]. Errors should be * reported to the [errorListener]. */ static Source resolveDirective(AnalysisContext context, Source librarySource, UriBasedDirective directive, AnalysisErrorListener errorListener) { StringLiteral uriLiteral = directive.uri; String uriContent = uriLiteral.stringValue; if (uriContent != null) { uriContent = uriContent.trim(); directive.uriContent = uriContent; } UriValidationCode code = directive.validate(); if (code == null) { String encodedUriContent = Uri.encodeFull(uriContent); Source source = context.sourceFactory.resolveUri(librarySource, encodedUriContent); directive.source = source; return source; } if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) { return null; } if (code == UriValidationCode.URI_WITH_INTERPOLATION) { errorListener.onError(new AnalysisError.con2(librarySource, uriLiteral.offset, uriLiteral.length, CompileTimeErrorCode.URI_WITH_INTERPOLATION)); return null; } if (code == UriValidationCode.INVALID_URI) { errorListener.onError(new AnalysisError.con2(librarySource, uriLiteral.offset, uriLiteral.length, CompileTimeErrorCode.INVALID_URI, [uriContent])); return null; } throw new AnalysisException('Failed to handle validation code: $code'); } } /** * The helper for building the public [Namespace] of a [LibraryElement]. */ class PublicNamespaceBuilder { final HashMap definedNames = new HashMap(); /** * Build a public [Namespace] of the given [library]. */ Namespace build(LibraryElement library) { definedNames.clear(); _addPublicNames(library.definingCompilationUnit); library.parts.forEach(_addPublicNames); return new Namespace(definedNames); } /** * Add the given [element] if it has a publicly visible name. */ void _addIfPublic(Element element) { String name = element.name; if (name != null && !Scope.isPrivateName(name)) { definedNames[name] = element; } } /** * Add all of the public top-level names that are defined in the given * [compilationUnit]. */ void _addPublicNames(CompilationUnitElement compilationUnit) { compilationUnit.accessors.forEach(_addIfPublic); compilationUnit.enums.forEach(_addIfPublic); compilationUnit.functions.forEach(_addIfPublic); compilationUnit.functionTypeAliases.forEach(_addIfPublic); compilationUnit.types.forEach(_addIfPublic); } } /** * An artifitial task that does nothing except to force type names resolution * for the defining and part units of a library. */ class ResolveLibraryTypeNamesTask extends SourceBasedAnalysisTask { /** * The name of the [LIBRARY_ELEMENT4] input. */ static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; /** * The task descriptor describing this kind of task. */ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( 'ResolveLibraryTypeNamesTask', createTask, buildInputs, [LIBRARY_ELEMENT5]); ResolveLibraryTypeNamesTask( InternalAnalysisContext context, AnalysisTarget target) : super(context, target); @override TaskDescriptor get descriptor => DESCRIPTOR; @override void internalPerform() { LibraryElement library = getRequiredInput(LIBRARY_INPUT); outputs[LIBRARY_ELEMENT5] = library; } /** * Return a map from the names of the inputs of this kind of task to the task * input descriptors describing those inputs for a task with the * given [target]. */ static Map buildInputs(Source libSource) { return { LIBRARY_INPUT: LIBRARY_ELEMENT4.of(libSource), 'resolvedUnits': IMPORT_SOURCE_CLOSURE .of(libSource) .toMapOf(UNITS) .toFlattenList((Source library, Source unit) => RESOLVED_UNIT4.of(new LibraryUnitTarget(library, unit))) }; } /** * Create a [ResolveLibraryTypeNamesTask] based on the given [target] in * the given [context]. */ static ResolveLibraryTypeNamesTask createTask( AnalysisContext context, AnalysisTarget target) { return new ResolveLibraryTypeNamesTask(context, target); } } /** * A task that builds [RESOLVED_UNIT] for a unit. */ class ResolveReferencesTask extends SourceBasedAnalysisTask { /** * The name of the [LIBRARY_ELEMENT] input. */ static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; /** * The name of the [RESOLVED_UNIT5] input. */ static const String UNIT_INPUT = 'UNIT_INPUT'; /** * The task descriptor describing this kind of task. */ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( 'ResolveReferencesTask', createTask, buildInputs, [RESOLVED_UNIT]); ResolveReferencesTask(InternalAnalysisContext context, AnalysisTarget target) : super(context, target); @override TaskDescriptor get descriptor => DESCRIPTOR; @override void internalPerform() { RecordingErrorListener errorListener = new RecordingErrorListener(); // // Prepare inputs. // LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT); CompilationUnit unit = getRequiredInput(UNIT_INPUT); CompilationUnitElement unitElement = unit.element; TypeProvider typeProvider = unitElement.context.typeProvider; // // Resolve references. // InheritanceManager inheritanceManager = new InheritanceManager(libraryElement); AstVisitor visitor = new ResolverVisitor.con2(libraryElement, unitElement.source, typeProvider, inheritanceManager, errorListener); unit.accept(visitor); // // Record outputs. // outputs[RESOLVE_REFERENCES_ERRORS] = errorListener.errors; outputs[RESOLVED_UNIT] = 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 buildInputs(LibraryUnitTarget target) { return { LIBRARY_INPUT: LIBRARY_ELEMENT.of(target.library), UNIT_INPUT: RESOLVED_UNIT5.of(target) }; } /** * Create a [ResolveReferencesTask] based on the given [target] in * the given [context]. */ static ResolveReferencesTask createTask( AnalysisContext context, AnalysisTarget target) { return new ResolveReferencesTask(context, target); } } /** * A task that builds [RESOLVED_UNIT4] for a unit. */ class ResolveUnitTypeNamesTask extends SourceBasedAnalysisTask { /** * The name of the [RESOLVED_UNIT3] input. */ static const String UNIT_INPUT = 'UNIT_INPUT'; /** * The task descriptor describing this kind of task. */ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( 'ResolveUnitTypeNamesTask', createTask, buildInputs, [ RESOLVE_TYPE_NAMES_ERRORS, RESOLVED_UNIT4 ]); ResolveUnitTypeNamesTask( InternalAnalysisContext context, AnalysisTarget target) : super(context, target); @override TaskDescriptor get descriptor => DESCRIPTOR; @override void internalPerform() { RecordingErrorListener errorListener = new RecordingErrorListener(); // // Prepare inputs. // CompilationUnit unit = getRequiredInput(UNIT_INPUT); CompilationUnitElement unitElement = unit.element; // // Resolve TypeName nodes. // TypeResolverVisitor visitor = new TypeResolverVisitor.con2( unitElement.library, unitElement.source, context.typeProvider, errorListener); unit.accept(visitor); // // Record outputs. // outputs[RESOLVE_TYPE_NAMES_ERRORS] = errorListener.errors; outputs[RESOLVED_UNIT4] = 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 buildInputs(LibraryUnitTarget target) { return {UNIT_INPUT: RESOLVED_UNIT3.of(target)}; } /** * Create a [ResolveUnitTypeNamesTask] based on the given [target] in * the given [context]. */ static ResolveUnitTypeNamesTask createTask( AnalysisContext context, AnalysisTarget target) { return new ResolveUnitTypeNamesTask(context, target); } } /** * A task that builds [RESOLVED_UNIT5] for a unit. */ class ResolveVariableReferencesTask extends SourceBasedAnalysisTask { /** * The name of the [LIBRARY_ELEMENT] input. */ static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; /** * The name of the [RESOLVED_UNIT4] input. */ static const String UNIT_INPUT = 'UNIT_INPUT'; /** * The task descriptor describing this kind of task. */ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( 'ResolveVariableReferencesTask', createTask, buildInputs, [RESOLVED_UNIT5]); ResolveVariableReferencesTask( InternalAnalysisContext context, AnalysisTarget target) : super(context, target); @override TaskDescriptor get descriptor => DESCRIPTOR; @override void internalPerform() { RecordingErrorListener errorListener = new RecordingErrorListener(); // // Prepare inputs. // LibraryElement libraryElement = getRequiredInput(LIBRARY_INPUT); CompilationUnit unit = getRequiredInput(UNIT_INPUT); CompilationUnitElement unitElement = unit.element; // // Resolve local variables. // TypeProvider typeProvider = unitElement.context.typeProvider; Scope nameScope = new LibraryScope(libraryElement, errorListener); AstVisitor visitor = new VariableResolverVisitor.con2(libraryElement, unitElement.source, typeProvider, nameScope, errorListener); unit.accept(visitor); // // Record outputs. // outputs[RESOLVED_UNIT5] = 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 buildInputs(LibraryUnitTarget target) { return { LIBRARY_INPUT: LIBRARY_ELEMENT.of(target.library), UNIT_INPUT: RESOLVED_UNIT4.of(target) }; } /** * Create a [ResolveVariableReferencesTask] based on the given [target] in * the given [context]. */ static ResolveVariableReferencesTask createTask( AnalysisContext context, AnalysisTarget target) { return new ResolveVariableReferencesTask(context, target); } } /** * A task that scans the content of a file, producing a set of Dart tokens. */ class ScanDartTask extends SourceBasedAnalysisTask { /** * The name of the input whose value is the content of the file. */ static const String CONTENT_INPUT_NAME = 'CONTENT_INPUT_NAME'; /** * The task descriptor describing this kind of task. */ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor('ScanDartTask', createTask, buildInputs, [ LINE_INFO, SCAN_ERRORS, TOKEN_STREAM ]); /** * Initialize a newly created task to access the content of the source * associated with the given [target] in the given [context]. */ ScanDartTask(InternalAnalysisContext context, AnalysisTarget target) : super(context, target); @override TaskDescriptor get descriptor => DESCRIPTOR; @override void internalPerform() { Source source = getRequiredSource(); String content = getRequiredInput(CONTENT_INPUT_NAME); RecordingErrorListener errorListener = new RecordingErrorListener(); Scanner scanner = new Scanner(source, new CharSequenceReader(content), errorListener); scanner.preserveComments = context.analysisOptions.preserveComments; scanner.enableNullAwareOperators = context.analysisOptions.enableNullAwareOperators; outputs[TOKEN_STREAM] = scanner.tokenize(); outputs[LINE_INFO] = new LineInfo(scanner.lineStarts); outputs[SCAN_ERRORS] = errorListener.getErrorsForSource(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 * [source]. */ static Map buildInputs(Source source) { return {CONTENT_INPUT_NAME: CONTENT.of(source)}; } /** * Create a [ScanDartTask] based on the given [target] in the given [context]. */ static ScanDartTask createTask( AnalysisContext context, AnalysisTarget target) { return new ScanDartTask(context, target); } } /** * A task that builds [VERIFY_ERRORS] for a unit. */ class VerifyUnitTask 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('VerifyUnitTask', createTask, buildInputs, [VERIFY_ERRORS]); /** * The [ErrorReporter] to report errors to. */ ErrorReporter errorReporter; VerifyUnitTask(InternalAnalysisContext context, AnalysisTarget target) : super(context, target); @override TaskDescriptor get descriptor => DESCRIPTOR; @override void internalPerform() { RecordingErrorListener errorListener = new RecordingErrorListener(); Source source = getRequiredSource(); errorReporter = new ErrorReporter(errorListener, source); TypeProvider typeProvider = context.typeProvider; // // Prepare inputs. // CompilationUnit unit = getRequiredInput(UNIT_INPUT); CompilationUnitElement unitElement = unit.element; LibraryElement libraryElement = unitElement.library; // // Use the ErrorVerifier to compute errors. // ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter, libraryElement, typeProvider, new InheritanceManager(libraryElement)); unit.accept(errorVerifier); // // Record outputs. // outputs[VERIFY_ERRORS] = 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 buildInputs(LibraryUnitTarget target) { return {UNIT_INPUT: RESOLVED_UNIT.of(target)}; } /** * Create a [VerifyUnitTask] based on the given [target] in * the given [context]. */ static VerifyUnitTask createTask( AnalysisContext context, AnalysisTarget target) { return new VerifyUnitTask(context, target); } } /** * A [TaskInput] whose value is a list of library sources exported directly * or indirectly by the target [Source]. */ class _ExportSourceClosureTaskInput implements TaskInput> { final Source target; _ExportSourceClosureTaskInput(this.target); @override TaskInputBuilder> createBuilder() => new _SourceClosureTaskInputBuilder(target, _SourceClosureKind.EXPORT); } /** * The kind of the source closure to build. */ enum _SourceClosureKind { IMPORT, EXPORT } /** * A [TaskInput] whose value is a list of library sources imported directly * or indirectly by the target [Source]. */ class _ImportSourceClosureTaskInput implements TaskInput> { final Source target; _ImportSourceClosureTaskInput(this.target); @override TaskInputBuilder> createBuilder() => new _SourceClosureTaskInputBuilder(target, _SourceClosureKind.IMPORT); } /** * A [TaskInputBuilder] to build values for [_ImportSourceClosureTaskInput]. */ class _SourceClosureTaskInputBuilder implements TaskInputBuilder> { final _SourceClosureKind kind; final Set _libraries = new HashSet(); final Set _newSources = new HashSet(); Source currentTarget; _SourceClosureTaskInputBuilder(Source librarySource, this.kind) { _newSources.add(librarySource); } @override ResultDescriptor get currentResult => LIBRARY_ELEMENT2; @override void set currentValue(LibraryElement library) { if (_libraries.add(library)) { if (kind == _SourceClosureKind.IMPORT) { for (ImportElement importElement in library.imports) { Source importedSource = importElement.importedLibrary.source; _newSources.add(importedSource); } } else { for (ExportElement exportElement in library.exports) { Source importedSource = exportElement.exportedLibrary.source; _newSources.add(importedSource); } } } } @override List get inputValue { return _libraries.map((LibraryElement library) => library.source).toList(); } @override bool moveNext() { if (_newSources.isEmpty) { return false; } currentTarget = _newSources.first; _newSources.remove(currentTarget); return true; } }