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

Unified Diff: pkg/analyzer/lib/src/task/dart.dart

Issue 1008433002: Task: Build Directive Elements. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/analyzer/lib/src/generated/testing/element_factory.dart ('k') | pkg/analyzer/lib/task/dart.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/task/dart.dart
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 134f20c0f079251b2b242aef1a69e4a82073370b..32df68ae844a60325f20f9cc9a6d7e92bebedfac 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -23,6 +23,78 @@ 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<List<AnalysisError>> BUILD_DIRECTIVES_ERRORS =
+ new ResultDescriptor<List<AnalysisError>>(
+ 'BUILD_DIRECTIVES_ERRORS', AnalysisError.NO_ERRORS,
+ contributesTo: ANALYSIS_ERRORS);
+
+/**
+ * The errors produced while builing 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<List<AnalysisError>> BUILD_LIBRARY_ERRORS =
+ new ResultDescriptor<List<AnalysisError>>(
+ 'BUILD_LIBRARY_ERRORS', AnalysisError.NO_ERRORS,
+ contributesTo: ANALYSIS_ERRORS);
+
+/**
+ * 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<LibraryElement> LIBRARY_ELEMENT1 =
+ new ResultDescriptor<LibraryElement>('LIBRARY_ELEMENT1', null);
+
+/**
+ * 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<CompilationUnit> RESOLVED_UNIT1 =
+ new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT1', null);
+
+/**
+ * The partially resolved [CompilationUnit] associated with a unit.
+ *
+ * Directives 'library', 'part' and 'part of' are resolved.
+ *
+ * The result is only available for targets representing a library.
+ */
+final ResultDescriptor<CompilationUnit> RESOLVED_UNIT2 =
+ new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT2', null);
+
+/**
+ * The partially resolved [CompilationUnit] associated with a library.
+ *
+ * All the directives are resolved.
+ *
+ * The result is only available for targets representing a library.
+ */
+final ResultDescriptor<CompilationUnit> RESOLVED_UNIT3 =
+ new ResultDescriptor<CompilationUnit>('RESOLVED_UNIT3', null);
+
+String _input(ResultDescriptor result, [String suffix]) {
Brian Wilkerson 2015/03/12 17:56:26 If this function stays, it needs a comment. But I
scheglov 2015/03/12 18:27:00 Removed.
+ if (suffix == null) {
+ return result.name;
+ }
+ return '${result.name} $suffix';
+}
+
+/**
* A task that builds a compilation unit element for a single compilation unit.
*/
class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask {
@@ -30,19 +102,19 @@ 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 = "lineInfo";
+ static final String LINE_INFO_INPUT_NAME = _input(LINE_INFO);
/**
* The name of the input whose value is the AST for the compilation unit.
*/
- static const String PARSED_UNIT_INPUT_NAME = "parsedUnit";
+ static final String PARSED_UNIT_INPUT_NAME = _input(PARSED_UNIT);
/**
* The task descriptor describing this kind of task.
*/
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'BUILD_COMPILATION_UNIT_ELEMENT', createTask, buildInputs,
- <ResultDescriptor>[COMPILATION_UNIT_ELEMENT, BUILT_UNIT]);
+ <ResultDescriptor>[COMPILATION_UNIT_ELEMENT, RESOLVED_UNIT1]);
/**
* Initialize a newly created task to build a compilation unit element for
@@ -64,7 +136,7 @@ class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask {
CompilationUnitElement element = builder.buildCompilationUnit(source, unit);
outputs[COMPILATION_UNIT_ELEMENT] = element;
- outputs[BUILT_UNIT] = unit;
+ outputs[RESOLVED_UNIT1] = unit;
}
/**
@@ -88,20 +160,278 @@ class BuildCompilationUnitElementTask extends SourceBasedAnalysisTask {
}
/**
+ * A task that builds [RESOLVED_UNIT3] for a library.
+ */
+class BuildDirectiveElementsTask extends SourceBasedAnalysisTask {
+ /**
+ * The name of the input for [RESOLVED_UNIT2] of a library unit.
+ */
+ static final String RESOLVED_UNIT2_INPUT_NAME =
+ _input(RESOLVED_UNIT2, 'defining');
+
+ /**
+ * The input with a list of [LIBRARY_ELEMENT1]s of imported libraries.
+ */
+ static final String IMPORTS_LIBRARY_ELEMENT1_INPUT_NAME =
+ _input(LIBRARY_ELEMENT1, 'imports');
+
+ /**
+ * The input with a list of [LIBRARY_ELEMENT1]s of exported libraries.
+ */
+ static final String EXPORTS_LIBRARY_ELEMENT1_INPUT_NAME =
+ _input(LIBRARY_ELEMENT1, 'exports');
+
+ /**
+ * The input with a list of [SOURCE_KIND]s of imported libraries.
+ */
+ static final String IMPORTS_SOURCE_KIND_INPUT_NAME =
+ _input(SOURCE_KIND, 'imports');
+
+ /**
+ * The input with a list of [SOURCE_KIND]s of exported libraries.
+ */
+ static final String EXPORTS_SOURCE_KIND_INPUT_NAME =
+ _input(SOURCE_KIND, 'exports');
+
+ /**
+ * The task descriptor describing this kind of task.
+ */
+ static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
+ 'BUILD_RESOLVED_UNIT3', createTask, buildInputs, <ResultDescriptor>[
+ RESOLVED_UNIT3,
+ BUILD_DIRECTIVES_ERRORS
+ ]);
+
+ BuildDirectiveElementsTask(
+ InternalAnalysisContext context, AnalysisTarget target)
+ : super(context, target);
+
+ @override
+ TaskDescriptor get descriptor => DESCRIPTOR;
+
+ @override
+ void internalPerform() {
+ List<AnalysisError> errors = <AnalysisError>[];
+ //
+ // Prepare inputs.
+ //
+ CompilationUnit libraryUnit = getRequiredInput(RESOLVED_UNIT2_INPUT_NAME);
+ Map<Source, LibraryElement> importLibraryMap =
+ getRequiredInput(IMPORTS_LIBRARY_ELEMENT1_INPUT_NAME);
+ Map<Source, LibraryElement> exportLibraryMap =
+ getRequiredInput(EXPORTS_LIBRARY_ELEMENT1_INPUT_NAME);
+ Map<Source, SourceKind> importSourceKindMap =
+ getRequiredInput(IMPORTS_SOURCE_KIND_INPUT_NAME);
+ Map<Source, SourceKind> exportSourceKindMap =
+ getRequiredInput(EXPORTS_SOURCE_KIND_INPUT_NAME);
+ //
+ // Process inputs.
+ //
+ LibraryElementImpl libraryElement = libraryUnit.element.library;
+ Source librarySource = libraryElement.source;
+ //
+ // Resolve directives.
+ //
+ HashMap<String, PrefixElementImpl> nameToPrefixMap =
+ new HashMap<String, PrefixElementImpl>();
+ List<ImportElement> imports = <ImportElement>[];
+ List<ExportElement> exports = <ExportElement>[];
+ bool explicitlyImportsCore = false;
+ for (Directive directive in libraryUnit.directives) {
+ if (directive is ImportDirective) {
+ ImportDirective importDirective = directive;
+ String uriContent = importDirective.uriContent;
+ if (DartUriResolver.isDartExtUri(uriContent)) {
+ libraryElement.hasExtUri = true;
+ }
+ Source importedSource = importDirective.source;
+ if (importedSource != null && context.exists(importedSource)) {
+ // The imported source will be null if the URI in the import
+ // directive was invalid.
+ LibraryElement importedLibrary = importLibraryMap[importedSource];
+ if (importedLibrary != null) {
+ 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;
+ // TODO(scheglov) move after EXPORT_NAMESPACE or just this task
+// if (libraryElement.entryPoint == null) {
+// Namespace namespace = new NamespaceBuilder()
+// .createExportNamespaceForLibrary(libraryElement);
+// Element element = namespace.get(FunctionElement.MAIN_FUNCTION_NAME);
+// if (element is FunctionElement) {
+// libraryElement.entryPoint = element;
+// }
+// }
+ //
+ // Record outputs.
+ //
+ outputs[RESOLVED_UNIT3] = libraryUnit;
+ 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 [target].
+ */
+ static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
+ return <String, TaskInput>{
+ RESOLVED_UNIT2_INPUT_NAME: RESOLVED_UNIT2.inputFor(target),
+ IMPORTS_LIBRARY_ELEMENT1_INPUT_NAME:
+ new MapBasedTaskInput<Source, LibraryElement>(
+ new SimpleTaskInput<List<Source>>(target, IMPORTED_LIBRARIES),
Brian Wilkerson 2015/03/12 17:56:26 Personally, I like IMPORTED_LIBRARIES.inputFor
scheglov 2015/03/12 18:27:00 Thank you. My inputs look much better now!
+ (Source includedSource) => new SimpleTaskInput<LibraryElement>(
+ includedSource, LIBRARY_ELEMENT1)),
+ EXPORTS_LIBRARY_ELEMENT1_INPUT_NAME:
+ new MapBasedTaskInput<Source, LibraryElement>(
+ new SimpleTaskInput<List<Source>>(target, EXPORTED_LIBRARIES),
+ (Source includedSource) => new SimpleTaskInput<LibraryElement>(
+ includedSource, LIBRARY_ELEMENT1)),
+ IMPORTS_SOURCE_KIND_INPUT_NAME: new MapBasedTaskInput<Source, SourceKind>(
+ new SimpleTaskInput<List<Source>>(target, IMPORTED_LIBRARIES),
+ (Source includedSource) =>
+ new SimpleTaskInput<SourceKind>(includedSource, SOURCE_KIND)),
+ EXPORTS_SOURCE_KIND_INPUT_NAME: new MapBasedTaskInput<Source, SourceKind>(
+ new SimpleTaskInput<List<Source>>(target, EXPORTED_LIBRARIES),
+ (Source includedSource) =>
+ new SimpleTaskInput<SourceKind>(includedSource, 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<NamespaceCombinator> _buildCombinators(
+ NamespaceDirective directive) {
+ List<NamespaceCombinator> combinators = <NamespaceCombinator>[];
+ for (Combinator combinator in directive.combinators) {
+ if (combinator is ShowCombinator) {
+ ShowElementCombinatorImpl show = new ShowElementCombinatorImpl();
+ show.offset = combinator.offset;
+ show.end = combinator.end;
+ show.shownNames = _getIdentifiers(combinator.shownNames);
+ combinators.add(show);
+ } else if (combinator is HideCombinator) {
+ HideElementCombinatorImpl hide = new HideElementCombinatorImpl();
+ hide.hiddenNames = _getIdentifiers(combinator.hiddenNames);
+ combinators.add(hide);
+ }
+ }
+ return combinators;
+ }
+
+ /**
+ * Return the lexical identifiers associated with the given [identifiers].
+ */
+ static List<String> _getIdentifiers(NodeList<SimpleIdentifier> identifiers) {
+ return identifiers.map((identifier) => identifier.name).toList();
+ }
+}
+
+/**
* A task that builds a library element for a Dart library.
*/
class BuildLibraryElementTask extends SourceBasedAnalysisTask {
/**
- * The name of the input whose value is the built compilation unit of the
- * defining compilation unit of a library.
+ * The name of the input whose value is the defining [RESOLVED_UNIT1].
*/
- static const String DEFINING_BUILT_UNIT_INPUT_NAME = 'definingBuiltUnit';
+ static final String DEFINING_RESOLVER_UNIT1_INPUT_NAME =
+ _input(RESOLVED_UNIT1, 'defining');
/**
- * The name of the input whose value is a list of built compilation units
+ * 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 PART_BUILT_UNITS_INPUT_NAME = 'partBuiltUnits';
+ static final String PARTS_RESOLVED_UNIT1_INPUT_NAME =
+ _input(RESOLVED_UNIT1, 'parts');
/**
* The task descriptor describing this kind of task.
@@ -109,7 +439,8 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask {
static final TaskDescriptor DESCRIPTOR = new TaskDescriptor(
'BUILD_LIBRARY_ELEMENT', createTask, buildInputs, <ResultDescriptor>[
BUILD_LIBRARY_ERRORS,
- BUILT_LIBRARY_ELEMENT,
+ RESOLVED_UNIT2,
+ LIBRARY_ELEMENT1,
IS_LAUNCHABLE,
HAS_HTML_IMPORT
]);
@@ -133,9 +464,9 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask {
//
Source librarySource = getRequiredSource();
CompilationUnit definingCompilationUnit =
- getRequiredInput(DEFINING_BUILT_UNIT_INPUT_NAME);
+ getRequiredInput(DEFINING_RESOLVER_UNIT1_INPUT_NAME);
List<CompilationUnit> partUnits =
- getRequiredInput(PART_BUILT_UNITS_INPUT_NAME);
+ getRequiredInput(PARTS_RESOLVED_UNIT1_INPUT_NAME);
//
// Process inputs.
//
@@ -231,7 +562,8 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask {
// Record outputs.
//
outputs[BUILD_LIBRARY_ERRORS] = errors;
- outputs[BUILT_LIBRARY_ELEMENT] = libraryElement;
+ outputs[RESOLVED_UNIT2] = definingCompilationUnit;
+ outputs[LIBRARY_ELEMENT1] = libraryElement;
outputs[IS_LAUNCHABLE] = entryPoint != null;
outputs[HAS_HTML_IMPORT] = hasHtmlImport;
}
@@ -320,12 +652,13 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask {
*/
static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
return <String, TaskInput>{
- DEFINING_BUILT_UNIT_INPUT_NAME: new SimpleTaskInput(target, BUILT_UNIT),
- PART_BUILT_UNITS_INPUT_NAME:
+ DEFINING_RESOLVER_UNIT1_INPUT_NAME:
+ new SimpleTaskInput(target, RESOLVED_UNIT1),
+ PARTS_RESOLVED_UNIT1_INPUT_NAME:
new ListBasedTaskInput<Source, CompilationUnit>(
new SimpleTaskInput<List<Source>>(target, INCLUDED_PARTS),
(Source includedSource) => new SimpleTaskInput<CompilationUnit>(
- includedSource, BUILT_UNIT))
+ includedSource, RESOLVED_UNIT1))
};
}
@@ -344,9 +677,10 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask {
*/
class BuildPublicNamespaceTask extends SourceBasedAnalysisTask {
/**
- * The name of the [BUILT_LIBRARY_ELEMENT] input.
+ * The name of the input for [LIBRARY_ELEMENT1] of a library.
*/
- static const String BUILT_LIBRARY_ELEMENT_INPUT_NAME = "builtLibraryElement";
+ static final String BUILT_LIBRARY_ELEMENT_INPUT_NAME =
+ _input(LIBRARY_ELEMENT1);
/**
* The task descriptor describing this kind of task.
@@ -380,7 +714,7 @@ class BuildPublicNamespaceTask extends SourceBasedAnalysisTask {
*/
static Map<String, TaskInput> buildInputs(AnalysisTarget target) {
return <String, TaskInput>{
- BUILT_LIBRARY_ELEMENT_INPUT_NAME: BUILT_LIBRARY_ELEMENT.inputFor(target)
+ BUILT_LIBRARY_ELEMENT_INPUT_NAME: LIBRARY_ELEMENT1.inputFor(target)
};
}
@@ -402,12 +736,12 @@ 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 = "lineInfo";
+ static final String LINE_INFO_INPUT_NAME = _input(LINE_INFO);
/**
* The name of the input whose value is the token stream produced for the file.
*/
- static const String TOKEN_STREAM_INPUT_NAME = "tokenStream";
+ static final String TOKEN_STREAM_INPUT_NAME = _input(TOKEN_STREAM);
/**
* The task descriptor describing this kind of task.
@@ -475,11 +809,21 @@ class ParseDartTask extends SourceBasedAnalysisTask {
}
}
}
+ //
+ // 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();
@@ -557,7 +901,7 @@ class ScanDartTask extends SourceBasedAnalysisTask {
/**
* The name of the input whose value is the content of the file.
*/
- static const String CONTENT_INPUT_NAME = "content";
+ static final String CONTENT_INPUT_NAME = _input(CONTENT);
/**
* The task descriptor describing this kind of task.
« no previous file with comments | « pkg/analyzer/lib/src/generated/testing/element_factory.dart ('k') | pkg/analyzer/lib/task/dart.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698