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

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

Issue 738863005: Respect order dependencies in ImplicitConstructorBuilder. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Sort unit/class members. Created 6 years 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 | « no previous file | pkg/analyzer/test/generated/non_error_resolver_test.dart » ('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 bc8654af222cc3cf98577b3028221355e97b59f2..e04800b770cd1a104e0233aed29472f8d141986b 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -7,6 +7,8 @@ library engine.resolver;
import "dart:math" as math;
import 'dart:collection';
+import 'package:analyzer/src/generated/utilities_collection.dart';
+
import 'ast.dart';
import 'constant.dart';
import 'element.dart';
@@ -26,6 +28,18 @@ import 'utilities_dart.dart';
import 'utilities_general.dart';
/**
+ * Callback signature used by ImplicitConstructorBuilder to register
+ * computations to be performed, and their dependencies. A call to this
+ * callback indicates that [computation] may be used to compute implicit
+ * constructors for [classElement], but that the computation may not be invoked
+ * until after implicit constructors have been built for [superclassElement].
+ */
+typedef void ImplicitConstructorBuilderCallback(ClassElement classElement,
+ ClassElement superclassElement, void computation());
+
+typedef void VoidFunction();
+
+/**
* Instances of the class `AngularCompilationUnitBuilder` build an Angular specific element
* model for a single compilation unit.
*/
@@ -5539,35 +5553,38 @@ class HtmlUnitBuilder implements ht.XmlVisitor<Object> {
}
/**
- * Instances of the class `SecondTypeResolverVisitor` are used to finish any resolve steps
- * after the [TypeResolverVisitor] that cannot happen in the [TypeResolverVisitor], but
- * should happen before the next tasks.
+ * Instances of the class `ImplicitConstructorBuilder` are used to build
+ * implicit constructors for mixin applications, and to check for errors
+ * related to super constructor calls in class declarations with mixins.
*
- * Currently this visitor only finishes the resolution of [ClassTypeAlias]s, thus the scopes
- * of other top level AST nodes do not currently have to be built.
+ * The visitor methods don't directly build the implicit constructors or check
+ * for errors, since they don't in general visit the classes in the proper
+ * order to do so correctly. Instead, they pass closures to
+ * ImplicitConstructorBuilderCallback to inform it of the computations to be
+ * done and their ordering dependencies.
*/
class ImplicitConstructorBuilder extends ScopedVisitor {
/**
- * Initialize a newly created visitor to finish resolution in 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
+ * Callback to receive the computations to be performed.
*/
- ImplicitConstructorBuilder.con1(Library library, Source source,
- TypeProvider typeProvider)
- : super.con1(library, source, typeProvider);
+ final ImplicitConstructorBuilderCallback _callback;
/**
- * Initialize a newly created visitor to finish resolution in the nodes in a compilation unit.
+ * Initialize a newly created visitor to build implicit constructors for file
+ * [source], in library [libraryElement], which has scope [libraryScope]. Use
+ * [typeProvider] to access types from the core library.
*
- * @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
+ * The visit methods will pass closures to [_callback] to indicate what
+ * computation needs to be performed, and its dependency order.
*/
- ImplicitConstructorBuilder.con2(ResolvableLibrary library, Source source,
- TypeProvider typeProvider)
- : super.con4(library, source, typeProvider);
+ ImplicitConstructorBuilder(Source source, LibraryElement libraryElement,
+ LibraryScope libraryScope, TypeProvider typeProvider, this._callback)
+ : super.con3(
+ libraryElement,
+ source,
+ typeProvider,
+ libraryScope,
+ libraryScope.errorListener);
@override
Object visitClassDeclaration(ClassDeclaration node) {
@@ -5587,23 +5604,25 @@ class ImplicitConstructorBuilder extends ScopedVisitor {
}
ClassElement superclassElement = classElement.supertype.element;
if (superclassElement != null) {
- bool constructorFound = false;
- void callback(ConstructorElement explicitConstructor,
- List<DartType> parameterTypes, List<DartType> argumentTypes) {
- constructorFound = true;
- }
- if (_findForwardedConstructors(
- classElement,
- superclassName,
- superclassType,
- callback) &&
- !constructorFound) {
- reportErrorForNode(
- CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS,
- node.withClause,
- [superclassType.element.name]);
- classElement.mixinErrorsReported = true;
- }
+ _callback(classElement, superclassElement, () {
+ bool constructorFound = false;
+ void callback(ConstructorElement explicitConstructor,
+ List<DartType> parameterTypes, List<DartType> argumentTypes) {
+ constructorFound = true;
+ }
+ if (_findForwardedConstructors(
+ classElement,
+ superclassName,
+ superclassType,
+ callback) &&
+ !constructorFound) {
+ reportErrorForNode(
+ CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS,
+ node.withClause,
+ [superclassType.element.name]);
+ classElement.mixinErrorsReported = true;
+ }
+ });
}
}
return null;
@@ -5622,32 +5641,35 @@ class ImplicitConstructorBuilder extends ScopedVisitor {
}
ClassElementImpl classElement = node.element as ClassElementImpl;
if (classElement != null) {
- if (superclassType.element != null) {
- List<ConstructorElement> implicitConstructors =
- new List<ConstructorElement>();
- void callback(ConstructorElement explicitConstructor,
- List<DartType> parameterTypes, List<DartType> argumentTypes) {
- implicitConstructors.add(
- _createImplicitContructor(
- classElement.type,
- explicitConstructor,
- parameterTypes,
- argumentTypes));
- }
- if (_findForwardedConstructors(
- classElement,
- superclassName,
- superclassType,
- callback)) {
- if (implicitConstructors.isEmpty) {
- reportErrorForNode(
- CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS,
- node,
- [superclassType.element.name]);
- } else {
- classElement.constructors = implicitConstructors;
+ ClassElement superclassElement = superclassType.element;
+ if (superclassElement != null) {
+ _callback(classElement, superclassElement, () {
+ List<ConstructorElement> implicitConstructors =
+ new List<ConstructorElement>();
+ void callback(ConstructorElement explicitConstructor,
+ List<DartType> parameterTypes, List<DartType> argumentTypes) {
+ implicitConstructors.add(
+ _createImplicitContructor(
+ classElement.type,
+ explicitConstructor,
+ parameterTypes,
+ argumentTypes));
}
- }
+ if (_findForwardedConstructors(
+ classElement,
+ superclassName,
+ superclassType,
+ callback)) {
+ if (implicitConstructors.isEmpty) {
+ reportErrorForNode(
+ CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS,
+ node,
+ [superclassElement.name]);
+ } else {
+ classElement.constructors = implicitConstructors;
+ }
+ }
+ });
}
}
return null;
@@ -5773,6 +5795,88 @@ class ImplicitConstructorBuilder extends ScopedVisitor {
}
/**
+ * An instance of this class is capable of running ImplicitConstructorBuilder
+ * over all classes in a library cycle.
+ */
+class ImplicitConstructorComputer {
+ /**
+ * The object used to access the types from the core library.
+ */
+ final TypeProvider typeProvider;
+
+ /**
+ * Directed graph of dependencies between classes that need to have their
+ * implicit constructors computed. Each edge in the graph points from a
+ * derived class to its superclass. Implicit constructors will be computed
+ * for the superclass before they are compute for the derived class.
+ */
+ DirectedGraph<ClassElement> _dependencies = new DirectedGraph<ClassElement>();
+
+ /**
+ * Map from ClassElement to the function which will compute the class's
+ * implicit constructors.
+ */
+ Map<ClassElement, VoidFunction> _computations =
+ new HashMap<ClassElement, VoidFunction>();
+
+ /**
+ * Create an ImplicitConstructorComputer which will use [typeProvider] to
+ * access types from the core library.
+ */
+ ImplicitConstructorComputer(this.typeProvider);
+
+ /**
+ * Add the given [unit] to the list of units which need to have implicit
+ * constructors built for them. [source] is the source file corresponding to
+ * the compilation unit, [libraryElement] is the library element containing
+ * that source, and [libraryScope] is the scope for the library element.
+ */
+ void add(CompilationUnit unit, Source source, LibraryElement libraryElement,
+ LibraryScope libraryScope) {
+ unit.accept(
+ new ImplicitConstructorBuilder(
+ source,
+ libraryElement,
+ libraryScope,
+ typeProvider,
+ _defer));
+ }
+
+ /**
+ * Compute the implicit constructors for all compilation units that have been
+ * passed to [add].
+ */
+ void compute() {
+ List<List<ClassElement>> topologicalSort =
+ _dependencies.computeTopologicalSort();
+ for (List<ClassElement> classesInCycle in topologicalSort) {
+ // Note: a cycle could occur if there is a loop in the inheritance graph.
+ // Such loops are forbidden by Dart but could occur in the analysis of
+ // incorrect code. If this happens, we simply visit the classes
+ // constituting the loop in any order.
+ for (ClassElement classElement in classesInCycle) {
+ VoidFunction computation = _computations[classElement];
+ if (computation != null) {
+ computation();
+ }
+ }
+ }
+ }
+
+ /**
+ * Defer execution of [computation], which builds implicit constructors for
+ * [classElement], until after implicit constructors have been built for
+ * [superclassElement].
+ */
+ void _defer(ClassElement classElement, ClassElement superclassElement, void
+ computation()) {
+ assert(!_computations.containsKey(classElement));
+ _computations[classElement] = computation;
+ _dependencies.addEdge(classElement, superclassElement);
+ }
+}
+
+/**
* Instances of the class `ImplicitLabelScope` represent the scope statements
* that can be the target of unlabeled break and continue statements.
*/
@@ -8737,13 +8841,18 @@ class LibraryResolver {
TimeCounter_TimeCounterHandle timeCounter =
PerformanceStatistics.resolve.start();
try {
+ ImplicitConstructorComputer computer =
+ new ImplicitConstructorComputer(_typeProvider);
for (Library library in _librariesInCycles) {
for (Source source in library.compilationUnitSources) {
- ImplicitConstructorBuilder visitor =
- new ImplicitConstructorBuilder.con1(library, source, _typeProvider);
- library.getAST(source).accept(visitor);
+ computer.add(
+ library.getAST(source),
+ source,
+ library.libraryElement,
+ library.libraryScope);
}
}
+ computer.compute();
} finally {
timeCounter.stop();
}
@@ -9477,16 +9586,21 @@ class LibraryResolver2 {
TimeCounter_TimeCounterHandle timeCounter =
PerformanceStatistics.resolve.start();
try {
+ ImplicitConstructorComputer computer =
+ new ImplicitConstructorComputer(_typeProvider);
for (ResolvableLibrary library in _librariesInCycle) {
for (ResolvableCompilationUnit unit in
library.resolvableCompilationUnits) {
Source source = unit.source;
CompilationUnit ast = unit.compilationUnit;
- ImplicitConstructorBuilder visitor =
- new ImplicitConstructorBuilder.con2(library, source, _typeProvider);
- ast.accept(visitor);
+ computer.add(
+ ast,
+ source,
+ library.libraryElement,
+ library.libraryScope);
}
}
+ computer.compute();
} finally {
timeCounter.stop();
}
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/non_error_resolver_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698