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

Unified Diff: pkg/analyzer/lib/src/generated/resolver.dart

Issue 197213036: New analyzer snapshot. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Update pubspec and recent changes. Created 6 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/engine.dart ('k') | pkg/analyzer/pubspec.yaml » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/generated/resolver.dart
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 9ec01641fe353eb1fe37c65e8874b9cca9a90449..504f25be87a35fac52aa641b49c47c3aeaef2830 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -3863,9 +3863,9 @@ class ImportsVerifier extends RecursiveAstVisitor<Object> {
* @param annotations the list of annotations to visit
*/
void _visitMetadata(NodeList<Annotation> annotations) {
- for (Annotation annotation in annotations) {
- Identifier name = annotation.name;
- _visitIdentifier(name.staticElement, name.name);
+ int count = annotations.length;
+ for (int i = 0; i < count; i++) {
+ annotations[i].accept(this);
}
}
}
@@ -5539,9 +5539,9 @@ class ElementResolver extends SimpleAstVisitor<Object> {
MethodElement propagatedMethod = _lookUpMethod(leftHandSide, propagatedType, methodName);
node.propagatedElement = propagatedMethod;
if (_shouldReportMissingMember(staticType, staticMethod)) {
- _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticTypeWarningCode.UNDEFINED_METHOD, operator, [methodName, staticType.displayName]);
+ _resolver.reportProxyConditionalErrorForToken(staticType.element, StaticTypeWarningCode.UNDEFINED_METHOD, operator, [methodName, staticType.displayName]);
} else if (_enableHints && _shouldReportMissingMember(propagatedType, propagatedMethod) && !_memberFoundInSubclass(propagatedType.element, methodName, true, false)) {
- _resolver.reportErrorProxyConditionalAnalysisError(propagatedType.element, HintCode.UNDEFINED_METHOD, operator, [methodName, propagatedType.displayName]);
+ _resolver.reportProxyConditionalErrorForToken(propagatedType.element, HintCode.UNDEFINED_METHOD, operator, [methodName, propagatedType.displayName]);
}
}
}
@@ -5562,9 +5562,9 @@ class ElementResolver extends SimpleAstVisitor<Object> {
MethodElement propagatedMethod = _lookUpMethod(leftOperand, propagatedType, methodName);
node.propagatedElement = propagatedMethod;
if (_shouldReportMissingMember(staticType, staticMethod)) {
- _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, operator, [methodName, staticType.displayName]);
+ _resolver.reportProxyConditionalErrorForToken(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, operator, [methodName, staticType.displayName]);
} else if (_enableHints && _shouldReportMissingMember(propagatedType, propagatedMethod) && !_memberFoundInSubclass(propagatedType.element, methodName, true, false)) {
- _resolver.reportErrorProxyConditionalAnalysisError(propagatedType.element, HintCode.UNDEFINED_OPERATOR, operator, [methodName, propagatedType.displayName]);
+ _resolver.reportProxyConditionalErrorForToken(propagatedType.element, HintCode.UNDEFINED_OPERATOR, operator, [methodName, propagatedType.displayName]);
}
}
}
@@ -6059,9 +6059,9 @@ class ElementResolver extends SimpleAstVisitor<Object> {
MethodElement propagatedMethod = _lookUpMethod(operand, propagatedType, methodName);
node.propagatedElement = propagatedMethod;
if (_shouldReportMissingMember(staticType, staticMethod)) {
- _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, node.operator, [methodName, staticType.displayName]);
+ _resolver.reportProxyConditionalErrorForToken(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, node.operator, [methodName, staticType.displayName]);
} else if (_enableHints && _shouldReportMissingMember(propagatedType, propagatedMethod) && !_memberFoundInSubclass(propagatedType.element, methodName, true, false)) {
- _resolver.reportErrorProxyConditionalAnalysisError(propagatedType.element, HintCode.UNDEFINED_OPERATOR, node.operator, [methodName, propagatedType.displayName]);
+ _resolver.reportProxyConditionalErrorForToken(propagatedType.element, HintCode.UNDEFINED_OPERATOR, node.operator, [methodName, propagatedType.displayName]);
}
return null;
}
@@ -6138,9 +6138,9 @@ class ElementResolver extends SimpleAstVisitor<Object> {
MethodElement propagatedMethod = _lookUpMethod(operand, propagatedType, methodName);
node.propagatedElement = propagatedMethod;
if (_shouldReportMissingMember(staticType, staticMethod)) {
- _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, operator, [methodName, staticType.displayName]);
+ _resolver.reportProxyConditionalErrorForToken(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, operator, [methodName, staticType.displayName]);
} else if (_enableHints && _shouldReportMissingMember(propagatedType, propagatedMethod) && !_memberFoundInSubclass(propagatedType.element, methodName, true, false)) {
- _resolver.reportErrorProxyConditionalAnalysisError(propagatedType.element, HintCode.UNDEFINED_OPERATOR, operator, [methodName, propagatedType.displayName]);
+ _resolver.reportProxyConditionalErrorForToken(propagatedType.element, HintCode.UNDEFINED_OPERATOR, operator, [methodName, propagatedType.displayName]);
}
}
return null;
@@ -9040,11 +9040,12 @@ class LibraryElementBuilder {
/**
* Initialize a newly created library element builder.
*
- * @param resolver the resolver for which the element model is being built
+ * @param analysisContext the analysis context in which the element model will be built
+ * @param errorListener the listener to which errors will be reported
*/
- LibraryElementBuilder(LibraryResolver resolver) {
- this._analysisContext = resolver.analysisContext;
- this._errorListener = resolver.errorListener;
+ LibraryElementBuilder(InternalAnalysisContext analysisContext, AnalysisErrorListener errorListener) {
+ this._analysisContext = analysisContext;
+ this._errorListener = errorListener;
}
/**
@@ -9083,14 +9084,97 @@ class LibraryElementBuilder {
Source partSource = library.getSource(partDirective);
if (_analysisContext.exists(partSource)) {
hasPartDirective = true;
- CompilationUnitElementImpl part = builder.buildCompilationUnit(partSource, library.getAST(partSource));
+ CompilationUnit partUnit = library.getAST(partSource);
+ CompilationUnitElementImpl part = builder.buildCompilationUnit(partSource, partUnit);
part.uriOffset = partUri.offset;
part.uriEnd = partUri.end;
part.uri = library.getUri(partDirective);
//
// Validate that the part contains a part-of directive with the same name as the library.
//
- String partLibraryName = _getPartLibraryName(library, partSource, directivesToResolve);
+ String partLibraryName = _getPartLibraryName(partSource, partUnit, directivesToResolve);
+ if (partLibraryName == null) {
+ _errorListener.onError(new AnalysisError.con2(librarySource, partUri.offset, partUri.length, CompileTimeErrorCode.PART_OF_NON_PART, [partUri.toSource()]));
+ } else if (libraryNameNode == null) {
+ } else if (libraryNameNode.name != partLibraryName) {
+ _errorListener.onError(new AnalysisError.con2(librarySource, partUri.offset, partUri.length, StaticWarningCode.PART_OF_DIFFERENT_LIBRARY, [libraryNameNode.name, partLibraryName]));
+ }
+ if (entryPoint == null) {
+ entryPoint = _findEntryPoint(part);
+ }
+ directive.element = part;
+ sourcedCompilationUnits.add(part);
+ }
+ }
+ }
+ if (hasPartDirective && libraryNameNode == null) {
+ _errorListener.onError(new AnalysisError.con1(librarySource, ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART, []));
+ }
+ //
+ // Create and populate the library element.
+ //
+ LibraryElementImpl libraryElement = new LibraryElementImpl(_analysisContext, libraryNameNode);
+ libraryElement.definingCompilationUnit = definingCompilationUnitElement;
+ if (entryPoint != null) {
+ libraryElement.entryPoint = entryPoint;
+ }
+ int sourcedUnitCount = sourcedCompilationUnits.length;
+ libraryElement.parts = new List.from(sourcedCompilationUnits);
+ for (Directive directive in directivesToResolve) {
+ directive.element = libraryElement;
+ }
+ library.libraryElement = libraryElement;
+ if (sourcedUnitCount > 0) {
+ _patchTopLevelAccessors(libraryElement);
+ }
+ return libraryElement;
+ }
+
+ /**
+ * Build the library element for the given library.
+ *
+ * @param library the library for which an element model is to be built
+ * @return the library element that was built
+ * @throws AnalysisException if the analysis could not be performed
+ */
+ LibraryElementImpl buildLibrary2(ResolvableLibrary library) {
+ CompilationUnitBuilder builder = new CompilationUnitBuilder();
+ Source librarySource = library.librarySource;
+ CompilationUnit definingCompilationUnit = library.definingCompilationUnit;
+ CompilationUnitElementImpl definingCompilationUnitElement = builder.buildCompilationUnit(librarySource, definingCompilationUnit);
+ NodeList<Directive> directives = definingCompilationUnit.directives;
+ LibraryIdentifier libraryNameNode = null;
+ bool hasPartDirective = false;
+ FunctionElement entryPoint = _findEntryPoint(definingCompilationUnitElement);
+ List<Directive> directivesToResolve = new List<Directive>();
+ List<CompilationUnitElementImpl> sourcedCompilationUnits = new List<CompilationUnitElementImpl>();
+ for (Directive directive in directives) {
+ //
+ // We do not build the elements representing the import and export directives at this point.
+ // That is not done until we get to LibraryResolver.buildDirectiveModels() because we need the
+ // LibraryElements for the referenced libraries, which might not exist at this point (due to
+ // the possibility of circular references).
+ //
+ 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 (_analysisContext.exists(partSource)) {
+ hasPartDirective = true;
+ CompilationUnit partUnit = library.getAST(partSource);
+ CompilationUnitElementImpl part = builder.buildCompilationUnit(partSource, partUnit);
+ part.uriOffset = partUri.offset;
+ part.uriEnd = partUri.end;
+ part.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) {
_errorListener.onError(new AnalysisError.con2(librarySource, partUri.offset, partUri.length, CompileTimeErrorCode.PART_OF_NON_PART, [partUri.toSource()]));
} else if (libraryNameNode == null) {
@@ -9170,25 +9254,21 @@ class LibraryElementBuilder {
* 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.
*
- * @param library the library containing the part
* @param partSource the source representing the part
+ * @param partUnit the AST structure of the part
* @param directivesToResolve a list of directives that should be resolved to the library being
* built
* @return the name of the library that the given part is declared to be a part of
*/
- String _getPartLibraryName(Library library, Source partSource, List<Directive> directivesToResolve) {
- try {
- CompilationUnit partUnit = library.getAST(partSource);
- for (Directive directive in partUnit.directives) {
- if (directive is PartOfDirective) {
- directivesToResolve.add(directive);
- LibraryIdentifier libraryName = directive.libraryName;
- if (libraryName != null) {
- return libraryName.name;
- }
+ String _getPartLibraryName(Source partSource, CompilationUnit partUnit, List<Directive> directivesToResolve) {
+ for (Directive directive in partUnit.directives) {
+ if (directive is PartOfDirective) {
+ directivesToResolve.add(directive);
+ LibraryIdentifier libraryName = directive.libraryName;
+ if (libraryName != null) {
+ return libraryName.name;
}
}
- } on AnalysisException catch (exception) {
}
return null;
}
@@ -9652,7 +9732,7 @@ class LibraryResolver {
*/
void _buildElementModels() {
for (Library library in _librariesInCycles) {
- LibraryElementBuilder builder = new LibraryElementBuilder(this);
+ LibraryElementBuilder builder = new LibraryElementBuilder(analysisContext, errorListener);
LibraryElementImpl libraryElement = builder.buildLibrary(library);
library.libraryElement = libraryElement;
}
@@ -9949,212 +10029,885 @@ class LibraryResolver {
}
/**
- * This class is used to replace uses of `HashMap<String, ExecutableElement>` which are not as
- * performant as this class.
+ * Instances of the class `LibraryResolver` are used to resolve one or more mutually dependent
+ * libraries within a single context.
*/
-class MemberMap {
+class LibraryResolver2 {
/**
- * The current size of this map.
+ * The analysis context in which the libraries are being analyzed.
*/
- int _size = 0;
+ InternalAnalysisContext analysisContext;
/**
- * The array of keys.
+ * The listener to which analysis errors will be reported, this error listener is either
+ * references [recordingErrorListener], or it unions the passed
+ * [AnalysisErrorListener] with the [recordingErrorListener].
*/
- List<String> _keys;
+ RecordingErrorListener _errorListener;
/**
- * The array of ExecutableElement values.
+ * A source object representing the core library (dart:core).
*/
- List<ExecutableElement> _values;
+ Source _coreLibrarySource;
/**
- * Default constructor.
+ * The object representing the core library.
*/
- MemberMap() : this.con1(10);
+ ResolvableLibrary _coreLibrary;
/**
- * This constructor takes an initial capacity of the map.
+ * The object used to access the types from the core library.
+ */
+ TypeProvider _typeProvider;
+
+ /**
+ * A table mapping library sources to the information being maintained for those libraries.
+ */
+ Map<Source, ResolvableLibrary> _libraryMap = new Map<Source, ResolvableLibrary>();
+
+ /**
+ * A collection containing the libraries that are being resolved together.
+ */
+ List<ResolvableLibrary> _librariesInCycle;
+
+ /**
+ * Initialize a newly created library resolver to resolve libraries within the given context.
*
- * @param initialCapacity the initial capacity
+ * @param analysisContext the analysis context in which the library is being analyzed
*/
- MemberMap.con1(int initialCapacity) {
- _initArrays(initialCapacity);
+ LibraryResolver2(InternalAnalysisContext analysisContext) {
+ this.analysisContext = analysisContext;
+ this._errorListener = new RecordingErrorListener();
+ _coreLibrarySource = analysisContext.sourceFactory.forUri(DartSdk.DART_CORE);
}
/**
- * Copy constructor.
+ * Return the listener to which analysis errors will be reported.
+ *
+ * @return the listener to which analysis errors will be reported
*/
- MemberMap.con2(MemberMap memberMap) {
- _initArrays(memberMap._size + 5);
- for (int i = 0; i < memberMap._size; i++) {
- _keys[i] = memberMap._keys[i];
- _values[i] = memberMap._values[i];
+ RecordingErrorListener get errorListener => _errorListener;
+
+ /**
+ * Return an array containing information about all of the libraries that were resolved.
+ *
+ * @return an array containing the libraries that were resolved
+ */
+ List<ResolvableLibrary> get resolvedLibraries => _librariesInCycle;
+
+ /**
+ * Resolve the library specified by the given source in the given context.
+ *
+ * Note that because Dart allows circular imports between libraries, it is possible that more than
+ * one library will need to be resolved. In such cases the error listener can receive errors from
+ * multiple libraries.
+ *
+ * @param librarySource the source specifying the defining compilation unit of the library to be
+ * resolved
+ * @param fullAnalysis `true` if a full analysis should be performed
+ * @return the element representing the resolved library
+ * @throws AnalysisException if the library could not be resolved for some reason
+ */
+ LibraryElement resolveLibrary(Source librarySource, List<ResolvableLibrary> librariesInCycle) {
+ InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engine.LibraryResolver.resolveLibrary");
+ try {
+ instrumentation.data3("fullName", librarySource.fullName);
+ //
+ // Build the map of libraries that are known.
+ //
+ this._librariesInCycle = librariesInCycle;
+ _libraryMap = _buildLibraryMap();
+ ResolvableLibrary targetLibrary = _libraryMap[librarySource];
+ _coreLibrary = _libraryMap[_coreLibrarySource];
+ instrumentation.metric3("buildLibraryMap", "complete");
+ //
+ // Build the element models representing the libraries being resolved. This is done in three
+ // steps:
+ //
+ // 1. Build the basic element models without making any connections between elements other than
+ // the basic parent/child relationships. This includes building the elements representing the
+ // libraries.
+ // 2. Build the elements for the import and export directives. This requires that we have the
+ // elements built for the referenced libraries, but because of the possibility of circular
+ // references needs to happen after all of the library elements have been created.
+ // 3. Build the rest of the type model by connecting superclasses, mixins, and interfaces. This
+ // requires that we be able to compute the names visible in the libraries being resolved,
+ // which in turn requires that we have resolved the import directives.
+ //
+ _buildElementModels();
+ instrumentation.metric3("buildElementModels", "complete");
+ LibraryElement coreElement = _coreLibrary.libraryElement;
+ if (coreElement == null) {
+ throw new AnalysisException.con1("Could not resolve dart:core");
+ }
+ _buildDirectiveModels();
+ instrumentation.metric3("buildDirectiveModels", "complete");
+ _typeProvider = new TypeProviderImpl(coreElement);
+ _buildTypeHierarchies();
+ instrumentation.metric3("buildTypeHierarchies", "complete");
+ //
+ // Perform resolution and type analysis.
+ //
+ // TODO(brianwilkerson) Decide whether we want to resolve all of the libraries or whether we
+ // want to only resolve the target library. The advantage to resolving everything is that we
+ // have already done part of the work so we'll avoid duplicated effort. The disadvantage of
+ // resolving everything is that we might do extra work that we don't really care about. Another
+ // possibility is to add a parameter to this method and punt the decision to the clients.
+ //
+ //if (analyzeAll) {
+ _resolveReferencesAndTypes();
+ instrumentation.metric3("resolveReferencesAndTypes", "complete");
+ //} else {
+ // resolveReferencesAndTypes(targetLibrary);
+ //}
+ _performConstantEvaluation();
+ instrumentation.metric3("performConstantEvaluation", "complete");
+ instrumentation.metric2("librariesInCycles", librariesInCycle.length);
+ for (ResolvableLibrary lib in librariesInCycle) {
+ instrumentation.metric2("librariesInCycles-CompilationUnitSources-Size", lib.compilationUnitSources.length);
+ }
+ return targetLibrary.libraryElement;
+ } finally {
+ instrumentation.log();
}
- _size = memberMap._size;
}
/**
- * Given some key, return the ExecutableElement value from the map, if the key does not exist in
- * the map, `null` is returned.
+ * Build the element model representing the combinators declared by the given directive.
+ *
+ * @param directive the directive that declares the combinators
+ * @return an array containing the import combinators that were built
+ */
+ List<NamespaceCombinator> _buildCombinators(NamespaceDirective directive) {
+ List<NamespaceCombinator> combinators = new List<NamespaceCombinator>();
+ for (Combinator combinator in directive.combinators) {
+ if (combinator is HideCombinator) {
+ HideElementCombinatorImpl hide = new HideElementCombinatorImpl();
+ hide.hiddenNames = _getIdentifiers(combinator.hiddenNames);
+ combinators.add(hide);
+ } else {
+ ShowElementCombinatorImpl show = new ShowElementCombinatorImpl();
+ show.offset = combinator.offset;
+ show.end = combinator.end;
+ show.shownNames = _getIdentifiers((combinator as ShowCombinator).shownNames);
+ combinators.add(show);
+ }
+ }
+ return new List.from(combinators);
+ }
+
+ /**
+ * Every library now has a corresponding [LibraryElement], so it is now possible to resolve
+ * the import and export directives.
+ *
+ * @throws AnalysisException if the defining compilation unit for any of the libraries could not
+ * be accessed
+ */
+ void _buildDirectiveModels() {
+ for (ResolvableLibrary library in _librariesInCycle) {
+ Map<String, PrefixElementImpl> nameToPrefixMap = new Map<String, PrefixElementImpl>();
+ List<ImportElement> imports = new List<ImportElement>();
+ List<ExportElement> exports = new List<ExportElement>();
+ for (Directive directive in library.definingCompilationUnit.directives) {
+ if (directive is ImportDirective) {
+ ImportDirective importDirective = directive;
+ Source importedSource = importDirective.source;
+ if (importedSource != null && analysisContext.exists(importedSource)) {
+ // The imported source will be null if the URI in the import directive was invalid.
+ ResolvableLibrary importedLibrary = _libraryMap[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 = importDirective.uriContent;
+ importElement.combinators = _buildCombinators(importDirective);
+ LibraryElement importedLibraryElement = importedLibrary.libraryElement;
+ if (importedLibraryElement != null) {
+ importElement.importedLibrary = importedLibraryElement;
+ }
+ 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(prefixNode);
+ nameToPrefixMap[prefixName] = prefix;
+ }
+ importElement.prefix = prefix;
+ prefixNode.staticElement = prefix;
+ }
+ directive.element = importElement;
+ imports.add(importElement);
+ if (analysisContext.computeKindOf(importedSource) != SourceKind.LIBRARY) {
+ _errorListener.onError(new AnalysisError.con2(library.librarySource, uriLiteral.offset, uriLiteral.length, CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, [uriLiteral.toSource()]));
+ }
+ }
+ }
+ } else if (directive is ExportDirective) {
+ ExportDirective exportDirective = directive;
+ Source exportedSource = exportDirective.source;
+ if (exportedSource != null && analysisContext.exists(exportedSource)) {
+ // The exported source will be null if the URI in the export directive was invalid.
+ ResolvableLibrary exportedLibrary = _libraryMap[exportedSource];
+ if (exportedLibrary != null) {
+ ExportElementImpl exportElement = new ExportElementImpl();
+ StringLiteral uriLiteral = exportDirective.uri;
+ if (uriLiteral != null) {
+ exportElement.uriOffset = uriLiteral.offset;
+ exportElement.uriEnd = uriLiteral.end;
+ }
+ exportElement.uri = exportDirective.uriContent;
+ exportElement.combinators = _buildCombinators(exportDirective);
+ LibraryElement exportedLibraryElement = exportedLibrary.libraryElement;
+ if (exportedLibraryElement != null) {
+ exportElement.exportedLibrary = exportedLibraryElement;
+ }
+ directive.element = exportElement;
+ exports.add(exportElement);
+ if (analysisContext.computeKindOf(exportedSource) != SourceKind.LIBRARY) {
+ _errorListener.onError(new AnalysisError.con2(library.librarySource, uriLiteral.offset, uriLiteral.length, CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, [uriLiteral.toSource()]));
+ }
+ }
+ }
+ }
+ }
+ Source librarySource = library.librarySource;
+ if (!library.explicitlyImportsCore && _coreLibrarySource != librarySource) {
+ ImportElementImpl importElement = new ImportElementImpl(-1);
+ importElement.importedLibrary = _coreLibrary.libraryElement;
+ importElement.synthetic = true;
+ imports.add(importElement);
+ }
+ LibraryElementImpl libraryElement = library.libraryElement;
+ libraryElement.imports = new List.from(imports);
+ libraryElement.exports = new List.from(exports);
+ if (libraryElement.entryPoint == null) {
+ Namespace namespace = new NamespaceBuilder().createExportNamespaceForLibrary(libraryElement);
+ Element element = namespace.get(LibraryElementBuilder.ENTRY_POINT_NAME);
+ if (element is FunctionElement) {
+ libraryElement.entryPoint = element;
+ }
+ }
+ }
+ }
+
+ /**
+ * Build element models for all of the libraries in the current cycle.
+ *
+ * @throws AnalysisException if any of the element models cannot be built
+ */
+ void _buildElementModels() {
+ for (ResolvableLibrary library in _librariesInCycle) {
+ LibraryElementBuilder builder = new LibraryElementBuilder(analysisContext, errorListener);
+ LibraryElementImpl libraryElement = builder.buildLibrary2(library);
+ library.libraryElement = libraryElement;
+ }
+ }
+
+ Map<Source, ResolvableLibrary> _buildLibraryMap() {
+ Map<Source, ResolvableLibrary> libraryMap = new Map<Source, ResolvableLibrary>();
+ int libraryCount = _librariesInCycle.length;
+ for (int i = 0; i < libraryCount; i++) {
+ ResolvableLibrary library = _librariesInCycle[i];
+ library.errorListener = _errorListener;
+ libraryMap[library.librarySource] = library;
+ List<ResolvableLibrary> dependencies = library.importsAndExports;
+ int dependencyCount = dependencies.length;
+ for (int j = 0; j < dependencyCount; j++) {
+ ResolvableLibrary dependency = dependencies[j];
+ //dependency.setErrorListener(errorListener);
+ libraryMap[dependency.librarySource] = dependency;
+ }
+ }
+ return libraryMap;
+ }
+
+ /**
+ * Resolve the type hierarchy across all of the types declared in the libraries in the current
+ * cycle.
+ *
+ * @throws AnalysisException if any of the type hierarchies could not be resolved
+ */
+ void _buildTypeHierarchies() {
+ TimeCounter_TimeCounterHandle timeCounter = PerformanceStatistics.resolve.start();
+ try {
+ for (ResolvableLibrary library in _librariesInCycle) {
+ for (ResolvableCompilationUnit unit in library.resolvableCompilationUnits) {
+ Source source = unit.source;
+ CompilationUnit ast = unit.compilationUnit;
+ TypeResolverVisitor visitor = new TypeResolverVisitor.con4(library, source, _typeProvider);
+ ast.accept(visitor);
+ }
+ }
+ } finally {
+ timeCounter.stop();
+ }
+ }
+
+ /**
+ * Return an array containing the lexical identifiers associated with the nodes in the given list.
+ *
+ * @param names the AST nodes representing the identifiers
+ * @return the lexical identifiers associated with the nodes in the list
+ */
+ List<String> _getIdentifiers(NodeList<SimpleIdentifier> names) {
+ int count = names.length;
+ List<String> identifiers = new List<String>(count);
+ for (int i = 0; i < count; i++) {
+ identifiers[i] = names[i].name;
+ }
+ return identifiers;
+ }
+
+ /**
+ * Compute a value for all of the constants in the libraries being analyzed.
+ */
+ void _performConstantEvaluation() {
+ TimeCounter_TimeCounterHandle timeCounter = PerformanceStatistics.resolve.start();
+ try {
+ ConstantValueComputer computer = new ConstantValueComputer(_typeProvider);
+ for (ResolvableLibrary library in _librariesInCycle) {
+ for (ResolvableCompilationUnit unit in library.resolvableCompilationUnits) {
+ CompilationUnit ast = unit.compilationUnit;
+ if (ast != null) {
+ computer.add(ast);
+ }
+ }
+ }
+ computer.computeValues();
+ } finally {
+ timeCounter.stop();
+ }
+ }
+
+ /**
+ * Resolve the identifiers and perform type analysis in the libraries in the current cycle.
+ *
+ * @throws AnalysisException if any of the identifiers could not be resolved or if any of the
+ * libraries could not have their types analyzed
+ */
+ void _resolveReferencesAndTypes() {
+ for (ResolvableLibrary library in _librariesInCycle) {
+ _resolveReferencesAndTypesInLibrary(library);
+ }
+ }
+
+ /**
+ * Resolve the identifiers and perform type analysis in the given library.
+ *
+ * @param library the library to be resolved
+ * @throws AnalysisException if any of the identifiers could not be resolved or if the types in
+ * the library cannot be analyzed
+ */
+ void _resolveReferencesAndTypesInLibrary(ResolvableLibrary library) {
+ TimeCounter_TimeCounterHandle timeCounter = PerformanceStatistics.resolve.start();
+ try {
+ for (ResolvableCompilationUnit unit in library.resolvableCompilationUnits) {
+ Source source = unit.source;
+ CompilationUnit ast = unit.compilationUnit;
+ ast.accept(new VariableResolverVisitor.con3(library, source, _typeProvider));
+ ResolverVisitor visitor = new ResolverVisitor.con4(library, source, _typeProvider);
+ ast.accept(visitor);
+ for (ProxyConditionalAnalysisError conditionalCode in visitor.proxyConditionalAnalysisErrors) {
+ if (conditionalCode.shouldIncludeErrorCode()) {
+ visitor.reportError(conditionalCode.analysisError);
+ }
+ }
+ }
+ } finally {
+ timeCounter.stop();
+ }
+ // Angular
+ timeCounter = PerformanceStatistics.angular.start();
+ try {
+ for (ResolvableCompilationUnit unit in library.resolvableCompilationUnits) {
+ Source source = unit.source;
+ CompilationUnit ast = unit.compilationUnit;
+ new AngularCompilationUnitBuilder(_errorListener, source, ast).build();
+ }
+ } finally {
+ timeCounter.stop();
+ }
+ }
+}
+
+/**
+ * This class is used to replace uses of `HashMap<String, ExecutableElement>` which are not as
+ * performant as this class.
+ */
+class MemberMap {
+ /**
+ * The current size of this map.
+ */
+ int _size = 0;
+
+ /**
+ * The array of keys.
+ */
+ List<String> _keys;
+
+ /**
+ * The array of ExecutableElement values.
+ */
+ List<ExecutableElement> _values;
+
+ /**
+ * Default constructor.
+ */
+ MemberMap() : this.con1(10);
+
+ /**
+ * This constructor takes an initial capacity of the map.
+ *
+ * @param initialCapacity the initial capacity
+ */
+ MemberMap.con1(int initialCapacity) {
+ _initArrays(initialCapacity);
+ }
+
+ /**
+ * Copy constructor.
+ */
+ MemberMap.con2(MemberMap memberMap) {
+ _initArrays(memberMap._size + 5);
+ for (int i = 0; i < memberMap._size; i++) {
+ _keys[i] = memberMap._keys[i];
+ _values[i] = memberMap._values[i];
+ }
+ _size = memberMap._size;
+ }
+
+ /**
+ * Given some key, return the ExecutableElement value from the map, if the key does not exist in
+ * the map, `null` is returned.
+ *
+ * @param key some key to look up in the map
+ * @return the associated ExecutableElement value from the map, if the key does not exist in the
+ * map, `null` is returned
+ */
+ ExecutableElement get(String key) {
+ for (int i = 0; i < _size; i++) {
+ if (_keys[i] != null && _keys[i] == key) {
+ return _values[i];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get and return the key at the specified location. If the key/value pair has been removed from
+ * the set, then `null` is returned.
+ *
+ * @param i some non-zero value less than size
+ * @return the key at the passed index
+ * @throw ArrayIndexOutOfBoundsException this exception is thrown if the passed index is less than
+ * zero or greater than or equal to the capacity of the arrays
+ */
+ String getKey(int i) => _keys[i];
+
+ /**
+ * The size of the map.
+ *
+ * @return the size of the map.
+ */
+ int get size => _size;
+
+ /**
+ * Get and return the ExecutableElement at the specified location. If the key/value pair has been
+ * removed from the set, then then `null` is returned.
+ *
+ * @param i some non-zero value less than size
+ * @return the key at the passed index
+ * @throw ArrayIndexOutOfBoundsException this exception is thrown if the passed index is less than
+ * zero or greater than or equal to the capacity of the arrays
+ */
+ ExecutableElement getValue(int i) => _values[i];
+
+ /**
+ * Given some key/value pair, store the pair in the map. If the key exists already, then the new
+ * value overrides the old value.
+ *
+ * @param key the key to store in the map
+ * @param value the ExecutableElement value to store in the map
+ */
+ void put(String key, ExecutableElement value) {
+ // If we already have a value with this key, override the value
+ for (int i = 0; i < _size; i++) {
+ if (_keys[i] != null && _keys[i] == key) {
+ _values[i] = value;
+ return;
+ }
+ }
+ // If needed, double the size of our arrays and copy values over in both arrays
+ if (_size == _keys.length) {
+ int newArrayLength = _size * 2;
+ List<String> keys_new_array = new List<String>(newArrayLength);
+ List<ExecutableElement> values_new_array = new List<ExecutableElement>(newArrayLength);
+ for (int i = 0; i < _size; i++) {
+ keys_new_array[i] = _keys[i];
+ }
+ for (int i = 0; i < _size; i++) {
+ values_new_array[i] = _values[i];
+ }
+ _keys = keys_new_array;
+ _values = values_new_array;
+ }
+ // Put new value at end of array
+ _keys[_size] = key;
+ _values[_size] = value;
+ _size++;
+ }
+
+ /**
+ * Given some [String] key, this method replaces the associated key and value pair with
+ * `null`. The size is not decremented with this call, instead it is expected that the users
+ * check for `null`.
+ *
+ * @param key the key of the key/value pair to remove from the map
+ */
+ void remove(String key) {
+ for (int i = 0; i < _size; i++) {
+ if (_keys[i] == key) {
+ _keys[i] = null;
+ _values[i] = null;
+ return;
+ }
+ }
+ }
+
+ /**
+ * Sets the ExecutableElement at the specified location.
+ *
+ * @param i some non-zero value less than size
+ * @param value the ExecutableElement value to store in the map
+ */
+ void setValue(int i, ExecutableElement value) {
+ _values[i] = value;
+ }
+
+ /**
+ * Initializes [keys] and [values].
+ */
+ void _initArrays(int initialCapacity) {
+ _keys = new List<String>(initialCapacity);
+ _values = new List<ExecutableElement>(initialCapacity);
+ }
+}
+
+/**
+ * This class is a wrapper for an [AnalysisError] which can also be queried after resolution
+ * to find out if the error should actually be reported. In this case, these errors are conditional
+ * on the non-existence of an `@proxy` annotation.
+ *
+ * If we have other conditional error codes in the future, we should have this class implement some
+ * ConditionalErrorCode so that after resolution, a list of ConditionalErrorCode can be visited
+ * instead of multiple lists of *ConditionalErrorCodes.
+ */
+class ProxyConditionalAnalysisError {
+ /**
+ * The enclosing [ClassElement], this is what will determine if the error code should, or
+ * should not, be generated on the source.
+ */
+ Element _enclosingElement;
+
+ /**
+ * The conditional analysis error.
+ */
+ AnalysisError analysisError;
+
+ /**
+ * Instantiate a new [ProxyConditionalAnalysisError] with some enclosing element and the
+ * conditional analysis error.
+ *
+ * @param enclosingElement the enclosing element
+ * @param analysisError the conditional analysis error
+ */
+ ProxyConditionalAnalysisError(Element enclosingElement, AnalysisError analysisError) {
+ this._enclosingElement = enclosingElement;
+ this.analysisError = analysisError;
+ }
+
+ /**
+ * Return `true` iff the enclosing class has the proxy annotation.
+ *
+ * @return `true` iff the enclosing class has the proxy annotation
+ */
+ bool shouldIncludeErrorCode() {
+ if (_enclosingElement is ClassElement) {
+ return !(_enclosingElement as ClassElement).isOrInheritsProxy;
+ }
+ return true;
+ }
+}
+
+/**
+ * Instances of the class `Library` represent the data about a single library during the
+ * resolution of some (possibly different) library. They are not intended to be used except during
+ * the resolution process.
+ */
+class ResolvableLibrary {
+ /**
+ * The source specifying the defining compilation unit of this library.
+ */
+ Source librarySource;
+
+ /**
+ * A list containing all of the libraries that are imported into this library.
+ */
+ List<ResolvableLibrary> _importedLibraries = _EMPTY_ARRAY;
+
+ /**
+ * A flag indicating whether this library explicitly imports core.
+ */
+ bool explicitlyImportsCore = false;
+
+ /**
+ * An array containing all of the libraries that are exported from this library.
+ */
+ List<ResolvableLibrary> _exportedLibraries = _EMPTY_ARRAY;
+
+ /**
+ * An array containing the compilation units that comprise this library. The defining compilation
+ * unit is always first.
+ */
+ List<ResolvableCompilationUnit> _compilationUnits;
+
+ /**
+ * The library element representing this library.
+ */
+ LibraryElementImpl _libraryElement;
+
+ /**
+ * The listener to which analysis errors will be reported.
+ */
+ AnalysisErrorListener _errorListener;
+
+ /**
+ * The inheritance manager which is used for member lookups in this library.
+ */
+ InheritanceManager _inheritanceManager;
+
+ /**
+ * An empty array that can be used to initialize lists of libraries.
+ */
+ static List<ResolvableLibrary> _EMPTY_ARRAY = new List<ResolvableLibrary>(0);
+
+ /**
+ * The library scope used when resolving elements within this library's compilation units.
+ */
+ LibraryScope _libraryScope;
+
+ /**
+ * Initialize a newly created data holder that can maintain the data associated with a library.
+ *
+ * @param librarySource the source specifying the defining compilation unit of this library
+ * @param errorListener the listener to which analysis errors will be reported
+ */
+ ResolvableLibrary(Source librarySource) {
+ this.librarySource = librarySource;
+ }
+
+ /**
+ * Return the AST structure associated with the given source, or `null` if the source does
+ * not represent a compilation unit that is included in this library.
+ *
+ * @param source the source representing the compilation unit whose AST is to be returned
+ * @return the AST structure associated with the given source
+ * @throws AnalysisException if an AST structure could not be created for the compilation unit
+ */
+ CompilationUnit getAST(Source source) {
+ int count = _compilationUnits.length;
+ for (int i = 0; i < count; i++) {
+ if (_compilationUnits[i].source == source) {
+ return _compilationUnits[i].compilationUnit;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return an array of the [CompilationUnit]s that make up the library. The first unit is
+ * always the defining unit.
+ *
+ * @return an array of the [CompilationUnit]s that make up the library. The first unit is
+ * always the defining unit
+ */
+ List<CompilationUnit> get compilationUnits {
+ int count = _compilationUnits.length;
+ List<CompilationUnit> units = new List<CompilationUnit>(count);
+ for (int i = 0; i < count; i++) {
+ units[i] = _compilationUnits[i].compilationUnit;
+ }
+ return units;
+ }
+
+ /**
+ * Return an array containing the sources for the compilation units in this library, including the
+ * defining compilation unit.
+ *
+ * @return the sources for the compilation units in this library
+ */
+ List<Source> get compilationUnitSources {
+ int count = _compilationUnits.length;
+ List<Source> sources = new List<Source>(count);
+ for (int i = 0; i < count; i++) {
+ sources[i] = _compilationUnits[i].source;
+ }
+ return sources;
+ }
+
+ /**
+ * Return the AST structure associated with the defining compilation unit for this library.
+ *
+ * @return the AST structure associated with the defining compilation unit for this library
+ * @throws AnalysisException if an AST structure could not be created for the defining compilation
+ * unit
+ */
+ CompilationUnit get definingCompilationUnit => _compilationUnits[0].compilationUnit;
+
+ /**
+ * Return an array containing the libraries that are exported from this library.
*
- * @param key some key to look up in the map
- * @return the associated ExecutableElement value from the map, if the key does not exist in the
- * map, `null` is returned
+ * @return an array containing the libraries that are exported from this library
*/
- ExecutableElement get(String key) {
- for (int i = 0; i < _size; i++) {
- if (_keys[i] != null && _keys[i] == key) {
- return _values[i];
- }
- }
- return null;
- }
+ List<ResolvableLibrary> get exports => _exportedLibraries;
/**
- * Get and return the key at the specified location. If the key/value pair has been removed from
- * the set, then `null` is returned.
+ * Return an array containing the libraries that are imported into this library.
*
- * @param i some non-zero value less than size
- * @return the key at the passed index
- * @throw ArrayIndexOutOfBoundsException this exception is thrown if the passed index is less than
- * zero or greater than or equal to the capacity of the arrays
+ * @return an array containing the libraries that are imported into this library
*/
- String getKey(int i) => _keys[i];
+ List<ResolvableLibrary> get imports => _importedLibraries;
/**
- * The size of the map.
+ * Return an array containing the libraries that are either imported or exported from this
+ * library.
*
- * @return the size of the map.
+ * @return the libraries that are either imported or exported from this library
*/
- int get size => _size;
+ List<ResolvableLibrary> get importsAndExports {
+ Set<ResolvableLibrary> libraries = new Set<ResolvableLibrary>();
+ for (ResolvableLibrary library in _importedLibraries) {
+ libraries.add(library);
+ }
+ for (ResolvableLibrary library in _exportedLibraries) {
+ libraries.add(library);
+ }
+ return new List.from(libraries);
+ }
/**
- * Get and return the ExecutableElement at the specified location. If the key/value pair has been
- * removed from the set, then then `null` is returned.
+ * Return the inheritance manager for this library.
*
- * @param i some non-zero value less than size
- * @return the key at the passed index
- * @throw ArrayIndexOutOfBoundsException this exception is thrown if the passed index is less than
- * zero or greater than or equal to the capacity of the arrays
+ * @return the inheritance manager for this library
*/
- ExecutableElement getValue(int i) => _values[i];
+ InheritanceManager get inheritanceManager {
+ if (_inheritanceManager == null) {
+ return _inheritanceManager = new InheritanceManager(_libraryElement);
+ }
+ return _inheritanceManager;
+ }
/**
- * Given some key/value pair, store the pair in the map. If the key exists already, then the new
- * value overrides the old value.
+ * Return the library element representing this library, creating it if necessary.
*
- * @param key the key to store in the map
- * @param value the ExecutableElement value to store in the map
+ * @return the library element representing this library
*/
- void put(String key, ExecutableElement value) {
- // If we already have a value with this key, override the value
- for (int i = 0; i < _size; i++) {
- if (_keys[i] != null && _keys[i] == key) {
- _values[i] = value;
- return;
- }
- }
- // If needed, double the size of our arrays and copy values over in both arrays
- if (_size == _keys.length) {
- int newArrayLength = _size * 2;
- List<String> keys_new_array = new List<String>(newArrayLength);
- List<ExecutableElement> values_new_array = new List<ExecutableElement>(newArrayLength);
- for (int i = 0; i < _size; i++) {
- keys_new_array[i] = _keys[i];
- }
- for (int i = 0; i < _size; i++) {
- values_new_array[i] = _values[i];
- }
- _keys = keys_new_array;
- _values = values_new_array;
+ LibraryElementImpl get libraryElement => _libraryElement;
+
+ /**
+ * Return the library scope used when resolving elements within this library's compilation units.
+ *
+ * @return the library scope used when resolving elements within this library's compilation units
+ */
+ LibraryScope get libraryScope {
+ if (_libraryScope == null) {
+ _libraryScope = new LibraryScope(_libraryElement, _errorListener);
}
- // Put new value at end of array
- _keys[_size] = key;
- _values[_size] = value;
- _size++;
+ return _libraryScope;
}
/**
- * Given some [String] key, this method replaces the associated key and value pair with
- * `null`. The size is not decremented with this call, instead it is expected that the users
- * check for `null`.
+ * Return the modification time associated with the given source.
*
- * @param key the key of the key/value pair to remove from the map
+ * @param source the source representing the compilation unit whose modification time is to be
+ * returned
+ * @return the modification time associated with the given source
+ * @throws AnalysisException if an AST structure could not be created for the compilation unit
*/
- void remove(String key) {
- for (int i = 0; i < _size; i++) {
- if (_keys[i] == key) {
- _keys[i] = null;
- _values[i] = null;
- return;
+ int getModificationTime(Source source) {
+ int count = _compilationUnits.length;
+ for (int i = 0; i < count; i++) {
+ if (source == _compilationUnits[i].source) {
+ return _compilationUnits[i].modificationTime;
}
}
+ return -1;
}
/**
- * Sets the ExecutableElement at the specified location.
+ * Return an array containing the compilation units that comprise this library. The defining
+ * compilation unit is always first.
*
- * @param i some non-zero value less than size
- * @param value the ExecutableElement value to store in the map
+ * @return the compilation units that comprise this library
*/
- void setValue(int i, ExecutableElement value) {
- _values[i] = value;
- }
+ List<ResolvableCompilationUnit> get resolvableCompilationUnits => _compilationUnits;
/**
- * Initializes [keys] and [values].
+ * Set the compilation unit in this library to the given compilation units. The defining
+ * compilation unit must be the first element of the array.
+ *
+ * @param units the compilation units in this library
*/
- void _initArrays(int initialCapacity) {
- _keys = new List<String>(initialCapacity);
- _values = new List<ExecutableElement>(initialCapacity);
+ void set resolvableCompilationUnits(List<ResolvableCompilationUnit> units) {
+ _compilationUnits = units;
}
-}
-/**
- * This class is a wrapper for an [AnalysisError] which can also be queried after resolution
- * to find out if the error should actually be reported. In this case, these errors are conditional
- * on the non-existence of an `@proxy` annotation.
- *
- * If we have other conditional error codes in the future, we should have this class implement some
- * ConditionalErrorCode so that after resolution, a list of ConditionalErrorCode can be visited
- * instead of multiple lists of *ConditionalErrorCodes.
- */
-class ProxyConditionalAnalysisError {
/**
- * The enclosing [ClassElement], this is what will determine if the error code should, or
- * should not, be generated on the source.
+ * Set the listener to which analysis errors will be reported to be the given listener.
+ *
+ * @param errorListener the listener to which analysis errors will be reported
*/
- Element _enclosingElement;
+ void set errorListener(AnalysisErrorListener errorListener) {
+ this._errorListener = errorListener;
+ }
/**
- * The conditional analysis error.
+ * Set the libraries that are exported by this library to be those in the given array.
+ *
+ * @param exportedLibraries the libraries that are exported by this library
*/
- AnalysisError analysisError;
+ void set exportedLibraries(List<ResolvableLibrary> exportedLibraries) {
+ this._exportedLibraries = exportedLibraries;
+ }
/**
- * Instantiate a new [ProxyConditionalAnalysisError] with some enclosing element and the
- * conditional analysis error.
+ * Set the libraries that are imported into this library to be those in the given array.
*
- * @param enclosingElement the enclosing element
- * @param analysisError the conditional analysis error
+ * @param importedLibraries the libraries that are imported into this library
*/
- ProxyConditionalAnalysisError(Element enclosingElement, AnalysisError analysisError) {
- this._enclosingElement = enclosingElement;
- this.analysisError = analysisError;
+ void set importedLibraries(List<ResolvableLibrary> importedLibraries) {
+ this._importedLibraries = importedLibraries;
}
/**
- * Return `true` iff the enclosing class has the proxy annotation.
+ * Set the library element representing this library to the given library element.
*
- * @return `true` iff the enclosing class has the proxy annotation
+ * @param libraryElement the library element representing this library
*/
- bool shouldIncludeErrorCode() {
- if (_enclosingElement is ClassElement) {
- return !(_enclosingElement as ClassElement).isOrInheritsProxy;
+ void set libraryElement(LibraryElementImpl libraryElement) {
+ this._libraryElement = libraryElement;
+ if (_inheritanceManager != null) {
+ _inheritanceManager.libraryElement = libraryElement;
}
- return true;
}
+
+ @override
+ String toString() => librarySource.shortName;
}
/**
@@ -10256,6 +11009,19 @@ class ResolverVisitor extends ScopedVisitor {
}
/**
+ * Initialize a newly created visitor to resolve the nodes in a compilation unit.
+ *
+ * @param library the library containing the compilation unit being resolved
+ * @param source the source representing the compilation unit being visited
+ * @param typeProvider the object used to access the types from the core library
+ */
+ ResolverVisitor.con4(ResolvableLibrary library, Source source, TypeProvider typeProvider) : super.con4(library, source, typeProvider) {
+ this._inheritanceManager = library.inheritanceManager;
+ this._elementResolver = new ElementResolver(this);
+ this._typeAnalyzer = new StaticTypeAnalyzer(this);
+ }
+
+ /**
* Return the object keeping track of which elements have had their types overridden.
*
* @return the object keeping track of which elements have had their types overridden
@@ -10992,7 +11758,7 @@ class ResolverVisitor extends ScopedVisitor {
* @param token the token specifying the location of the error
* @param arguments the arguments to the error, used to compose the error message
*/
- void reportErrorProxyConditionalAnalysisError(Element enclosingElement, ErrorCode errorCode, sc.Token token, List<Object> arguments) {
+ void reportProxyConditionalErrorForToken(Element enclosingElement, ErrorCode errorCode, sc.Token token, List<Object> arguments) {
_proxyConditionalAnalysisErrors.add(new ProxyConditionalAnalysisError(enclosingElement, new AnalysisError.con2(source, token.offset, token.length, errorCode, arguments)));
}
@@ -11147,6 +11913,11 @@ class ResolverVisitor extends ScopedVisitor {
return;
}
FunctionType expectedClosureType = mayByFunctionType as FunctionType;
+ // If the expectedClosureType is not more specific than the static type, return.
+ DartType staticClosureType = (closure.element != null ? closure.element.type : null) as DartType;
+ if (staticClosureType != null && !expectedClosureType.isMoreSpecificThan(staticClosureType)) {
+ return;
+ }
// set propagated type for the closure
closure.propagatedType = expectedClosureType;
// set inferred types for parameters
@@ -11553,6 +12324,22 @@ abstract class ScopedVisitor extends UnifyingAstVisitor<Object> {
}
/**
+ * Initialize a newly created visitor to resolve the nodes in a compilation unit.
+ *
+ * @param library the library containing the compilation unit being resolved
+ * @param source the source representing the compilation unit being visited
+ * @param typeProvider the object used to access the types from the core library
+ */
+ ScopedVisitor.con4(ResolvableLibrary library, Source source, TypeProvider typeProvider) {
+ this._definingLibrary = library.libraryElement;
+ this.source = source;
+ LibraryScope libraryScope = library.libraryScope;
+ this._errorListener = libraryScope.errorListener;
+ this._nameScope = libraryScope;
+ this.typeProvider = typeProvider;
+ }
+
+ /**
* Return the library element for the library containing the compilation unit being resolved.
*
* @return the library element for the library containing the compilation unit being resolved
@@ -11627,9 +12414,14 @@ abstract class ScopedVisitor extends UnifyingAstVisitor<Object> {
@override
Object visitClassDeclaration(ClassDeclaration node) {
+ ClassElement classElement = node.element;
Scope outerScope = _nameScope;
try {
- _nameScope = new ClassScope(_nameScope, node.element);
+ if (classElement == null) {
+ AnalysisEngine.instance.logger.logInformation2("Missing element for constructor ${node.name.name} in ${definingLibrary.source.fullName}", new JavaException());
+ } else {
+ _nameScope = new ClassScope(_nameScope, classElement);
+ }
visitClassDeclarationInScope(node);
} finally {
_nameScope = outerScope;
@@ -11651,9 +12443,23 @@ abstract class ScopedVisitor extends UnifyingAstVisitor<Object> {
@override
Object visitConstructorDeclaration(ConstructorDeclaration node) {
+ ConstructorElement constructorElement = node.element;
Scope outerScope = _nameScope;
try {
- _nameScope = new FunctionScope(_nameScope, node.element);
+ if (constructorElement == null) {
+ JavaStringBuilder builder = new JavaStringBuilder();
+ builder.append("Missing element for constructor ");
+ builder.append(node.returnType.name);
+ if (node.name != null) {
+ builder.append(".");
+ builder.append(node.name.name);
+ }
+ builder.append(" in ");
+ builder.append(definingLibrary.source.fullName);
+ AnalysisEngine.instance.logger.logInformation2(builder.toString(), new JavaException());
+ } else {
+ _nameScope = new FunctionScope(_nameScope, constructorElement);
+ }
super.visitConstructorDeclaration(node);
} finally {
_nameScope = outerScope;
@@ -11729,16 +12535,20 @@ abstract class ScopedVisitor extends UnifyingAstVisitor<Object> {
@override
Object visitFunctionDeclaration(FunctionDeclaration node) {
- ExecutableElement function = node.element;
+ ExecutableElement functionElement = node.element;
Scope outerScope = _nameScope;
try {
- _nameScope = new FunctionScope(_nameScope, function);
+ if (functionElement == null) {
+ AnalysisEngine.instance.logger.logInformation2("Missing element for top-level function ${node.name.name} in ${definingLibrary.source.fullName}", new JavaException());
+ } else {
+ _nameScope = new FunctionScope(_nameScope, functionElement);
+ }
super.visitFunctionDeclaration(node);
} finally {
_nameScope = outerScope;
}
- if (function.enclosingElement is! CompilationUnitElement) {
- _nameScope.define(function);
+ if (functionElement.enclosingElement is! CompilationUnitElement) {
+ _nameScope.define(functionElement);
}
return null;
}
@@ -11753,6 +12563,19 @@ abstract class ScopedVisitor extends UnifyingAstVisitor<Object> {
try {
ExecutableElement functionElement = node.element;
if (functionElement == null) {
+ JavaStringBuilder builder = new JavaStringBuilder();
+ builder.append("Missing element for function ");
+ AstNode parent = node.parent;
+ while (parent != null) {
+ if (parent is Declaration) {
+ Element parentElement = (parent as Declaration).element;
+ builder.append(parentElement == null ? "<unknown> " : ("${parentElement.name} "));
+ }
+ parent = parent.parent;
+ }
+ builder.append("in ");
+ builder.append(definingLibrary.source.fullName);
+ AnalysisEngine.instance.logger.logInformation2(builder.toString(), new JavaException());
} else {
_nameScope = new FunctionScope(_nameScope, functionElement);
}
@@ -11799,7 +12622,12 @@ abstract class ScopedVisitor extends UnifyingAstVisitor<Object> {
Object visitMethodDeclaration(MethodDeclaration node) {
Scope outerScope = _nameScope;
try {
- _nameScope = new FunctionScope(_nameScope, node.element);
+ ExecutableElement methodElement = node.element;
+ if (methodElement == null) {
+ AnalysisEngine.instance.logger.logInformation2("Missing element for method ${node.name.name} in ${definingLibrary.source.fullName}", new JavaException());
+ } else {
+ _nameScope = new FunctionScope(_nameScope, methodElement);
+ }
super.visitMethodDeclaration(node);
} finally {
_nameScope = outerScope;
@@ -14601,6 +15429,17 @@ class TypeResolverVisitor extends ScopedVisitor {
_dynamicType = typeProvider.dynamicType;
}
+ /**
+ * Initialize a newly created visitor to resolve the nodes in a compilation unit.
+ *
+ * @param library the library containing the compilation unit being resolved
+ * @param source the source representing the compilation unit being visited
+ * @param typeProvider the object used to access the types from the core library
+ */
+ TypeResolverVisitor.con4(ResolvableLibrary library, Source source, TypeProvider typeProvider) : super.con4(library, source, typeProvider) {
+ _dynamicType = typeProvider.dynamicType;
+ }
+
@override
Object visitCatchClause(CatchClause node) {
super.visitCatchClause(node);
@@ -15652,6 +16491,15 @@ class VariableResolverVisitor extends ScopedVisitor {
*/
VariableResolverVisitor.con2(LibraryElement definingLibrary, Source source, TypeProvider typeProvider, Scope nameScope, AnalysisErrorListener errorListener) : super.con3(definingLibrary, source, typeProvider, nameScope, errorListener);
+ /**
+ * Initialize a newly created visitor to resolve the nodes in a compilation unit.
+ *
+ * @param library the library containing the compilation unit being resolved
+ * @param source the source representing the compilation unit being visited
+ * @param typeProvider the object used to access the types from the core library
+ */
+ VariableResolverVisitor.con3(ResolvableLibrary library, Source source, TypeProvider typeProvider) : super.con4(library, source, typeProvider);
+
@override
Object visitFunctionDeclaration(FunctionDeclaration node) {
ExecutableElement outerFunction = _enclosingFunction;
@@ -15743,6 +16591,9 @@ class ClassScope extends EnclosedScope {
* @param typeElement the element representing the type represented by this scope
*/
ClassScope(Scope enclosingScope, ClassElement typeElement) : super(new EnclosedScope(enclosingScope)) {
+ if (typeElement == null) {
+ throw new IllegalArgumentException("class element cannot be null");
+ }
_defineTypeParameters(typeElement);
_defineMembers(typeElement);
}
@@ -15871,6 +16722,9 @@ class FunctionScope extends EnclosedScope {
* @param functionElement the element representing the type represented by this scope
*/
FunctionScope(Scope enclosingScope, ExecutableElement functionElement) : super(new EnclosedScope(enclosingScope)) {
+ if (functionElement == null) {
+ throw new IllegalArgumentException("function element cannot be null");
+ }
this._functionElement = functionElement;
}
@@ -16772,21 +17626,41 @@ class ScopeBuilder {
}
Scope scope = _scopeForAstNode(parent);
if (node is ClassDeclaration) {
- scope = new ClassScope(scope, node.element);
+ ClassElement element = node.element;
+ if (element == null) {
+ throw new AnalysisException.con1("Cannot build a scope for an unresolved class");
+ }
+ scope = new ClassScope(scope, element);
} else if (node is ClassTypeAlias) {
- scope = new ClassScope(scope, node.element);
+ ClassElement element = node.element;
+ if (element == null) {
+ throw new AnalysisException.con1("Cannot build a scope for an unresolved class type alias");
+ }
+ scope = new ClassScope(scope, element);
} else if (node is ConstructorDeclaration) {
- FunctionScope functionScope = new FunctionScope(scope, node.element);
+ ConstructorElement element = node.element;
+ if (element == null) {
+ throw new AnalysisException.con1("Cannot build a scope for an unresolved constructor");
+ }
+ FunctionScope functionScope = new FunctionScope(scope, element);
functionScope.defineParameters();
scope = functionScope;
} else if (node is FunctionDeclaration) {
- FunctionScope functionScope = new FunctionScope(scope, node.element);
+ ExecutableElement element = node.element;
+ if (element == null) {
+ throw new AnalysisException.con1("Cannot build a scope for an unresolved function");
+ }
+ FunctionScope functionScope = new FunctionScope(scope, element);
functionScope.defineParameters();
scope = functionScope;
} else if (node is FunctionTypeAlias) {
scope = new FunctionTypeScope(scope, node.element);
} else if (node is MethodDeclaration) {
- FunctionScope functionScope = new FunctionScope(scope, node.element);
+ ExecutableElement element = node.element;
+ if (element == null) {
+ throw new AnalysisException.con1("Cannot build a scope for an unresolved method");
+ }
+ FunctionScope functionScope = new FunctionScope(scope, element);
functionScope.defineParameters();
scope = functionScope;
}
@@ -17507,6 +18381,8 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
@override
Object visitClassTypeAlias(ClassTypeAlias node) {
_checkForBuiltInIdentifierAsName(node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME);
+ _checkForExtendsDisallowedClassInTypeAlias(node);
+ _checkForImplementsDisallowedClass(node.implementsClause);
_checkForAllMixinErrorCodes(node.withClause);
ClassElement outerClassElement = _enclosingClass;
try {
@@ -19741,6 +20617,20 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
}
/**
+ * This verifies that the passed type alias does not extend classes such as num or String.
+ *
+ * @param node the extends clause to test
+ * @return `true` if and only if an error code is generated on the passed node
+ * @see CompileTimeErrorCode#EXTENDS_DISALLOWED_CLASS
+ */
+ bool _checkForExtendsDisallowedClassInTypeAlias(ClassTypeAlias node) {
+ if (node == null) {
+ return false;
+ }
+ return _checkForExtendsOrImplementsDisallowedClass(node.superclass, CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS);
+ }
+
+ /**
* This verifies that the passed type name does not extend or implement classes such as 'num' or
* 'String'.
*
« no previous file with comments | « pkg/analyzer/lib/src/generated/engine.dart ('k') | pkg/analyzer/pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698