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 23e32ddf5f4d719d18d2460b408d496c2114589d..18bc4df82cd0e509a488ce50f0d06af68a489555 100644 |
--- a/pkg/analyzer/lib/src/task/dart.dart |
+++ b/pkg/analyzer/lib/src/task/dart.dart |
@@ -16,6 +16,8 @@ import 'package:analyzer/error/listener.dart'; |
import 'package:analyzer/exception/exception.dart'; |
import 'package:analyzer/src/context/cache.dart'; |
import 'package:analyzer/src/context/context.dart'; |
+import 'package:analyzer/src/dart/ast/ast.dart' |
+ show NamespaceDirectiveImpl, UriBasedDirectiveImpl; |
import 'package:analyzer/src/dart/ast/utilities.dart'; |
import 'package:analyzer/src/dart/element/builder.dart'; |
import 'package:analyzer/src/dart/element/element.dart'; |
@@ -1523,7 +1525,7 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask { |
directivesToResolve.add(directive); |
} else if (directive is PartDirective) { |
StringLiteral partUri = directive.uri; |
- Source partSource = directive.source; |
+ Source partSource = directive.uriSource; |
hasPartDirective = true; |
CompilationUnit partUnit = partUnitMap[partSource]; |
if (partUnit != null) { |
@@ -3983,6 +3985,16 @@ class ParseDartTask extends SourceBasedAnalysisTask { |
]); |
/** |
+ * The source that is being parsed. |
+ */ |
+ Source _source; |
+ |
+ /** |
+ * The [ErrorReporter] to report errors to. |
+ */ |
+ ErrorReporter _errorReporter; |
+ |
+ /** |
* Initialize a newly created task to parse the content of the Dart file |
* associated with the given [target] in the given [context]. |
*/ |
@@ -3994,17 +4006,20 @@ class ParseDartTask extends SourceBasedAnalysisTask { |
@override |
void internalPerform() { |
- Source source = getRequiredSource(); |
+ _source = getRequiredSource(); |
LineInfo lineInfo = getRequiredInput(LINE_INFO_INPUT_NAME); |
int modificationTime = getRequiredInput(MODIFICATION_TIME_INPUT_NAME); |
Token tokenStream = getRequiredInput(TOKEN_STREAM_INPUT_NAME); |
RecordingErrorListener errorListener = new RecordingErrorListener(); |
- Parser parser = new Parser(source, errorListener); |
+ _errorReporter = new ErrorReporter(errorListener, _source); |
+ |
+ Parser parser = new Parser(_source, errorListener); |
AnalysisOptions options = context.analysisOptions; |
parser.enableAssertInitializer = options.enableAssertInitializer; |
parser.parseAsync = options.enableAsync; |
- parser.parseFunctionBodies = options.analyzeFunctionBodiesPredicate(source); |
+ parser.parseFunctionBodies = |
+ options.analyzeFunctionBodiesPredicate(_source); |
parser.parseGenericMethods = options.enableGenericMethods; |
parser.parseGenericMethodComments = options.strongMode; |
CompilationUnit unit = parser.parseCompilationUnit(tokenStream); |
@@ -4024,8 +4039,7 @@ class ParseDartTask extends SourceBasedAnalysisTask { |
} else { |
hasNonPartOfDirective = true; |
if (directive is UriBasedDirective) { |
- Source referencedSource = |
- resolveDirective(context, source, directive, errorListener); |
+ Source referencedSource = _resolveDirective(directive); |
if (referencedSource != null) { |
if (directive is ExportDirective) { |
exportedSourceSet.add(referencedSource); |
@@ -4070,7 +4084,7 @@ class ParseDartTask extends SourceBasedAnalysisTask { |
// |
// Compute referenced names. |
// |
- ReferencedNames referencedNames = new ReferencedNames(source); |
+ ReferencedNames referencedNames = new ReferencedNames(_source); |
new ReferencedNamesBuilder(referencedNames).build(unit); |
// |
// Record outputs. |
@@ -4081,14 +4095,14 @@ class ParseDartTask extends SourceBasedAnalysisTask { |
List<Source> importedSources = importedSourceSet.toList(); |
List<Source> includedSources = includedSourceSet.toList(); |
List<AnalysisError> parseErrors = getUniqueErrors(errorListener.errors); |
- List<Source> unitSources = <Source>[source]..addAll(includedSourceSet); |
+ List<Source> unitSources = <Source>[_source]..addAll(includedSourceSet); |
List<Source> referencedSources = (new Set<Source>() |
..addAll(importedSources) |
..addAll(exportedSources) |
..addAll(unitSources)) |
.toList(); |
List<LibrarySpecificUnit> librarySpecificUnits = |
- unitSources.map((s) => new LibrarySpecificUnit(source, s)).toList(); |
+ unitSources.map((s) => new LibrarySpecificUnit(_source, s)).toList(); |
outputs[EXPLICITLY_IMPORTED_LIBRARIES] = explicitlyImportedSources; |
outputs[EXPORTED_LIBRARIES] = exportedSources; |
outputs[IMPORTED_LIBRARIES] = importedSources; |
@@ -4103,6 +4117,76 @@ class ParseDartTask extends SourceBasedAnalysisTask { |
} |
/** |
+ * Return the result of resolving the URI of the given URI-based [directive] |
+ * against the URI of the given library, or `null` if the URI is not valid. |
+ */ |
+ Source _resolveDirective(UriBasedDirective directive) { |
+ bool isImport = directive is ImportDirective; |
+ |
+ // Resolve the default URI. |
+ Source defaultSource; |
+ { |
+ StringLiteral uriLiteral = directive.uri; |
+ String uriContent = uriLiteral.stringValue; |
+ if (uriContent != null) { |
+ uriContent = uriContent.trim(); |
+ directive.uriContent = uriContent; |
+ } |
+ defaultSource = _resolveUri(isImport, uriLiteral, uriContent); |
+ directive.uriSource = defaultSource; |
+ } |
+ |
+ // Resolve all configurations and try to choose one. |
+ if (directive is NamespaceDirectiveImpl) { |
+ Source configurationSource; |
+ for (Configuration configuration in directive.configurations) { |
+ Source source = _resolveUri(isImport, configuration.libraryUri, |
+ configuration.libraryUri.stringValue); |
+ configuration.uriSource = source; |
+ if (configurationSource == null) { |
+ String variableName = |
+ configuration.name.components.map((i) => i.name).join('.'); |
+ String variableValue = context.declaredVariables.get(variableName); |
+ if (configuration.value != null && |
+ variableValue == configuration.value.stringValue || |
+ variableValue == 'true') { |
+ configurationSource = source; |
+ } |
+ } |
+ } |
+ Source referencedSource = configurationSource ?? defaultSource; |
+ directive.selectedSource = referencedSource; |
+ return referencedSource; |
+ } |
+ return defaultSource; |
+ } |
+ |
+ /** |
+ * Return the result of resolve the given [uriContent], reporting errors |
+ * against the [uriLiteral]. |
+ */ |
+ Source _resolveUri( |
+ bool isImport, StringLiteral uriLiteral, String uriContent) { |
+ UriValidationCode code = |
+ UriBasedDirectiveImpl.validateUri(isImport, uriLiteral, uriContent); |
+ if (code == null) { |
+ String encodedUriContent = Uri.encodeFull(uriContent); |
+ return context.sourceFactory.resolveUri(_source, encodedUriContent); |
+ } else if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) { |
+ return null; |
+ } else if (code == UriValidationCode.URI_WITH_INTERPOLATION) { |
+ _errorReporter.reportErrorForNode( |
+ CompileTimeErrorCode.URI_WITH_INTERPOLATION, uriLiteral); |
+ return null; |
+ } else if (code == UriValidationCode.INVALID_URI) { |
+ _errorReporter.reportErrorForNode( |
+ CompileTimeErrorCode.INVALID_URI, uriLiteral, [uriContent]); |
+ return null; |
+ } |
+ throw new AnalysisException('Failed to handle validation code: $code'); |
+ } |
+ |
+ /** |
* Return a map from the names of the inputs of this kind of task to the task |
* input descriptors describing those inputs for a task with the given |
* [target]. |
@@ -4123,45 +4207,6 @@ class ParseDartTask extends SourceBasedAnalysisTask { |
AnalysisContext context, AnalysisTarget target) { |
return new ParseDartTask(context, target); |
} |
- |
- /** |
- * Return the result of resolving the URI of the given URI-based [directive] |
- * against the URI of the given library, or `null` if the URI is not valid. |
- * |
- * Resolution is to be performed in the given [context]. Errors should be |
- * reported to the [errorListener]. |
- */ |
- static Source resolveDirective(AnalysisContext context, Source librarySource, |
- UriBasedDirective directive, AnalysisErrorListener errorListener) { |
- StringLiteral uriLiteral = directive.uri; |
- String uriContent = uriLiteral.stringValue; |
- if (uriContent != null) { |
- uriContent = uriContent.trim(); |
- directive.uriContent = uriContent; |
- } |
- UriValidationCode code = directive.validate(); |
- if (code == null) { |
- String encodedUriContent = Uri.encodeFull(uriContent); |
- Source source = |
- context.sourceFactory.resolveUri(librarySource, encodedUriContent); |
- directive.source = source; |
- return source; |
- } |
- if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) { |
- return null; |
- } |
- if (code == UriValidationCode.URI_WITH_INTERPOLATION) { |
- errorListener.onError(new AnalysisError(librarySource, uriLiteral.offset, |
- uriLiteral.length, CompileTimeErrorCode.URI_WITH_INTERPOLATION)); |
- return null; |
- } |
- if (code == UriValidationCode.INVALID_URI) { |
- errorListener.onError(new AnalysisError(librarySource, uriLiteral.offset, |
- uriLiteral.length, CompileTimeErrorCode.INVALID_URI, [uriContent])); |
- return null; |
- } |
- throw new AnalysisException('Failed to handle validation code: $code'); |
- } |
} |
/** |
@@ -6174,7 +6219,33 @@ class VerifyUnitTask extends SourceBasedAnalysisTask { |
* report an error if it does not. |
*/ |
void validateReferencedSource(UriBasedDirective directive) { |
- Source source = directive.source; |
+ if (directive is NamespaceDirective) { |
+ for (Configuration configuration in directive.configurations) { |
+ Source source = configuration.uriSource; |
+ StringLiteral uriLiteral = configuration.libraryUri; |
+ String uriContent = uriLiteral?.stringValue?.trim(); |
+ if (source != null) { |
+ int modificationTime = sourceTimeMap[source] ?? -1; |
+ if (modificationTime >= 0) { |
+ continue; |
+ } |
+ } else { |
+ // Don't report errors already reported by ParseDartTask.resolveDirective |
+ if (UriBasedDirectiveImpl.validateUri( |
+ directive is ImportDirective, uriLiteral, uriContent) != |
+ null) { |
+ continue; |
+ } |
+ } |
+ CompileTimeErrorCode errorCode = |
+ CompileTimeErrorCode.URI_DOES_NOT_EXIST; |
+ if (_isGenerated(source)) { |
+ errorCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED; |
+ } |
+ errorReporter.reportErrorForNode(errorCode, uriLiteral, [uriContent]); |
+ } |
+ } |
+ Source source = directive.uriSource; |
if (source != null) { |
int modificationTime = sourceTimeMap[source] ?? -1; |
if (modificationTime >= 0) { |