diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart index a0e7f1fcd32..3ceb7b9ba35 100644 --- a/pkg/analyzer/lib/src/context/context.dart +++ b/pkg/analyzer/lib/src/context/context.dart @@ -1094,7 +1094,6 @@ class AnalysisContextImpl implements InternalAnalysisContext { setValue(LIBRARY_ELEMENT3, library); setValue(LIBRARY_ELEMENT4, library); setValue(LIBRARY_ELEMENT5, library); - setValue(LIBRARY_ELEMENT6, library); setValue(LINE_INFO, new LineInfo([0])); setValue(PARSE_ERRORS, AnalysisError.NO_ERRORS); entry.setState(PARSED_UNIT, CacheState.FLUSHED); diff --git a/pkg/analyzer/lib/src/generated/element.dart b/pkg/analyzer/lib/src/generated/element.dart index 52ef4f5df92..24344aae432 100644 --- a/pkg/analyzer/lib/src/generated/element.dart +++ b/pkg/analyzer/lib/src/generated/element.dart @@ -501,9 +501,15 @@ class ClassElementImpl extends ElementImpl implements ClassElement { List _accessors = PropertyAccessorElement.EMPTY_LIST; /** - * A list containing all of the constructors contained in this class. + * For classes which are not mixin applications, a list containing all of the + * constructors contained in this class, or `null` if the list of + * constructors has not yet been built. + * + * For classes which are mixin applications, the list of constructors is + * computed on the fly by the [constructors] getter, and this field is + * `null`. */ - List _constructors = ConstructorElement.EMPTY_LIST; + List _constructors; /** * A list containing all of the fields contained in this class. @@ -586,18 +592,74 @@ class ClassElementImpl extends ElementImpl implements ClassElement { } @override - List get constructors => _constructors; + List get constructors { + if (!isMixinApplication) { + assert(_constructors != null); + return _constructors == null + ? ConstructorElement.EMPTY_LIST + : _constructors; + } + + return _computeMixinAppConstructors(); + } /** * Set the constructors contained in this class to the given [constructors]. + * + * Should only be used for class elements that are not mixin applications. */ void set constructors(List constructors) { + assert(!isMixinApplication); for (ConstructorElement constructor in constructors) { (constructor as ConstructorElementImpl).enclosingElement = this; } this._constructors = constructors; } + /** + * Return `true` if [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS] should + * be reported for this class. + */ + bool get doesMixinLackConstructors { + if (!isMixinApplication && mixins.isEmpty) { + // This class is not a mixin application and it doesn't have a "with" + // clause, so CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS is + // inapplicable. + return false; + } + if (supertype == null) { + // Should never happen, since Object is the only class that has no + // supertype, and it should have been caught by the test above. + assert(false); + return false; + } + // Find the nearest class in the supertype chain that is not a mixin + // application. + ClassElement nearestNonMixinClass = supertype.element; + if (nearestNonMixinClass.isMixinApplication) { + // Use a list to keep track of the classes we've seen, so that we won't + // go into an infinite loop in the event of a non-trivial loop in the + // class hierarchy. + List classesSeen = [this]; + while (nearestNonMixinClass.isMixinApplication) { + if (classesSeen.contains(nearestNonMixinClass)) { + // Loop in the class hierarchy (which is reported elsewhere). Don't + // confuse the user with further errors. + return false; + } + classesSeen.add(nearestNonMixinClass); + if (nearestNonMixinClass.supertype == null) { + // Should never happen, since Object is the only class that has no + // supertype, and it is not a mixin application. + assert(false); + return false; + } + nearestNonMixinClass = nearestNonMixinClass.supertype.element; + } + } + return !nearestNonMixinClass.constructors.any(isSuperConstructorAccessible); + } + /** * Set whether this class is defined by an enum declaration. */ @@ -732,16 +794,6 @@ class ClassElementImpl extends ElementImpl implements ClassElement { setModifier(Modifier.MIXIN_APPLICATION, isMixinApplication); } - bool get mixinErrorsReported => hasModifier(Modifier.MIXIN_ERRORS_REPORTED); - - /** - * Set whether an error has reported explaining why this class is an - * invalid mixin application. - */ - void set mixinErrorsReported(bool value) { - setModifier(Modifier.MIXIN_ERRORS_REPORTED, value); - } - @override List get typeParameters => _typeParameters; @@ -996,6 +1048,103 @@ class ClassElementImpl extends ElementImpl implements ClassElement { } } + /** + * Compute a list of constructors for this class, which is a mixin + * application. If specified, [visitedClasses] is a list of the other mixin + * application classes which have been visited on the way to reaching this + * one (this is used to detect circularities). + */ + List _computeMixinAppConstructors( + [List visitedClasses = null]) { + // First get the list of constructors of the superclass which need to be + // forwarded to this class. + Iterable constructorsToForward; + if (supertype == null) { + // Shouldn't ever happen, since the only class with no supertype is + // Object, and it isn't a mixin application. But for safety's sake just + // assume an empty list. + assert(false); + constructorsToForward = []; + } else if (!supertype.element.isMixinApplication) { + List superclassConstructors = + supertype.element.constructors; + // Filter out any constructors with optional parameters (see + // dartbug.com/15101). + constructorsToForward = + superclassConstructors.where(isSuperConstructorAccessible); + } else { + if (visitedClasses == null) { + visitedClasses = [this]; + } else { + if (visitedClasses.contains(this)) { + // Loop in the class hierarchy. Don't try to forward any + // constructors. + return []; + } + visitedClasses.add(this); + } + try { + ClassElementImpl superclass = supertype.element; + constructorsToForward = + superclass._computeMixinAppConstructors(visitedClasses); + } finally { + visitedClasses.removeLast(); + } + } + + // Figure out the type parameter substitution we need to perform in order + // to produce constructors for this class. We want to be robust in the + // face of errors, so drop any extra type arguments and fill in any missing + // ones with `dynamic`. + List parameterTypes = + TypeParameterTypeImpl.getTypes(supertype.typeParameters); + List argumentTypes = new List.filled( + parameterTypes.length, DynamicTypeImpl.instance); + for (int i = 0; i < supertype.typeArguments.length; i++) { + if (i >= argumentTypes.length) { + break; + } + argumentTypes[i] = supertype.typeArguments[i]; + } + + // Now create an implicit constructor for every constructor found above, + // substituting type parameters as appropriate. + return constructorsToForward + .map((ConstructorElement superclassConstructor) { + ConstructorElementImpl implicitConstructor = + new ConstructorElementImpl(superclassConstructor.name, -1); + implicitConstructor.synthetic = true; + implicitConstructor.redirectedConstructor = superclassConstructor; + implicitConstructor.const2 = superclassConstructor.isConst; + implicitConstructor.returnType = type; + List superParameters = superclassConstructor.parameters; + int count = superParameters.length; + if (count > 0) { + List implicitParameters = + new List(count); + for (int i = 0; i < count; i++) { + ParameterElement superParameter = superParameters[i]; + ParameterElementImpl implicitParameter = + new ParameterElementImpl(superParameter.name, -1); + implicitParameter.const3 = superParameter.isConst; + implicitParameter.final2 = superParameter.isFinal; + implicitParameter.parameterKind = superParameter.parameterKind; + implicitParameter.synthetic = true; + implicitParameter.type = + superParameter.type.substitute2(argumentTypes, parameterTypes); + implicitParameters[i] = implicitParameter; + } + implicitConstructor.parameters = implicitParameters; + } + FunctionTypeImpl constructorType = + new FunctionTypeImpl(implicitConstructor); + constructorType.typeArguments = type.typeArguments; + implicitConstructor.type = constructorType; + implicitConstructor.enclosingElement = this; + return implicitConstructor; + }).toList(); + } + PropertyAccessorElement _internalLookUpConcreteGetter( String getterName, LibraryElement library, bool includeThisClass) { PropertyAccessorElement getter = @@ -8072,42 +8221,35 @@ class Modifier extends Enum { static const Modifier MIXIN_APPLICATION = const Modifier('MIXIN_APPLICATION', 12); - /** - * Indicates that an error has reported explaining why this class is an - * invalid mixin application. - */ - static const Modifier MIXIN_ERRORS_REPORTED = - const Modifier('MIXIN_ERRORS_REPORTED', 13); - /** * Indicates that the value of a parameter or local variable might be mutated * within the context. */ static const Modifier POTENTIALLY_MUTATED_IN_CONTEXT = - const Modifier('POTENTIALLY_MUTATED_IN_CONTEXT', 14); + const Modifier('POTENTIALLY_MUTATED_IN_CONTEXT', 13); /** * Indicates that the value of a parameter or local variable might be mutated * within the scope. */ static const Modifier POTENTIALLY_MUTATED_IN_SCOPE = - const Modifier('POTENTIALLY_MUTATED_IN_SCOPE', 15); + const Modifier('POTENTIALLY_MUTATED_IN_SCOPE', 14); /** * Indicates that a class contains an explicit reference to 'super'. */ static const Modifier REFERENCES_SUPER = - const Modifier('REFERENCES_SUPER', 16); + const Modifier('REFERENCES_SUPER', 15); /** * Indicates that the pseudo-modifier 'set' was applied to the element. */ - static const Modifier SETTER = const Modifier('SETTER', 17); + static const Modifier SETTER = const Modifier('SETTER', 16); /** * Indicates that the modifier 'static' was applied to the element. */ - static const Modifier STATIC = const Modifier('STATIC', 18); + static const Modifier STATIC = const Modifier('STATIC', 17); /** * Indicates that the element does not appear in the source code but was @@ -8115,7 +8257,7 @@ class Modifier extends Enum { * constructors, an implicit zero-argument constructor will be created and it * will be marked as being synthetic. */ - static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 19); + static const Modifier SYNTHETIC = const Modifier('SYNTHETIC', 18); static const List values = const [ ABSTRACT, @@ -8131,7 +8273,6 @@ class Modifier extends Enum { HAS_EXT_URI, MIXIN, MIXIN_APPLICATION, - MIXIN_ERRORS_REPORTED, POTENTIALLY_MUTATED_IN_CONTEXT, POTENTIALLY_MUTATED_IN_SCOPE, REFERENCES_SUPER, diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart index c047654d161..b93931f940e 100644 --- a/pkg/analyzer/lib/src/generated/element_resolver.dart +++ b/pkg/analyzer/lib/src/generated/element_resolver.dart @@ -1049,7 +1049,7 @@ class ElementResolver extends SimpleAstVisitor { ConstructorElement element = superType.lookUpConstructor(superName, _definingLibrary); if (element == null || - (!enclosingClass.mixinErrorsReported && + (!enclosingClass.doesMixinLackConstructors && !enclosingClass.isSuperConstructorAccessible(element))) { if (name != null) { _resolver.reportErrorForNode( diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart index 85ea9015c10..e80e02abdd0 100644 --- a/pkg/analyzer/lib/src/generated/error_verifier.dart +++ b/pkg/analyzer/lib/src/generated/error_verifier.dart @@ -422,6 +422,7 @@ class ErrorVerifier extends RecursiveAstVisitor { _checkForConflictingInstanceGetterAndSuperclassMember(); _checkImplementsSuperClass(node); _checkImplementsFunctionWithoutCall(node); + _checkForMixinHasNoConstructors(node); } } visitClassDeclarationIncrementally(node); @@ -474,6 +475,7 @@ class ErrorVerifier extends RecursiveAstVisitor { _checkForImplementsDeferredClass(implementsClause); _checkForRecursiveInterfaceInheritance(_enclosingClass); _checkForNonAbstractClassInheritsAbstractMember(node.name); + _checkForMixinHasNoConstructors(node); } } finally { _enclosingClass = outerClassElement; @@ -4164,6 +4166,18 @@ class ErrorVerifier extends RecursiveAstVisitor { return false; } + /** + * Report the error [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS] if + * appropriate. + */ + void _checkForMixinHasNoConstructors(AstNode node) { + if ((_enclosingClass as ClassElementImpl).doesMixinLackConstructors) { + ErrorCode errorCode = CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS; + _errorReporter.reportErrorForNode( + errorCode, node, [_enclosingClass.supertype]); + } + } + /** * Verify that the given mixin has the 'Object' superclass. The [mixinName] is * the node to report problem on. The [mixinElement] is the mixing to @@ -4290,7 +4304,7 @@ class ErrorVerifier extends RecursiveAstVisitor { ClassDeclaration declaration) { // do nothing if mixin errors have already been reported for this class. ClassElementImpl enclosingClass = _enclosingClass; - if (enclosingClass.mixinErrorsReported) { + if (enclosingClass.doesMixinLackConstructors) { return false; } // do nothing if there is explicit constructor @@ -5183,7 +5197,7 @@ class ErrorVerifier extends RecursiveAstVisitor { } // do nothing if mixin errors have already been reported for this class. ClassElementImpl enclosingClass = _enclosingClass; - if (enclosingClass.mixinErrorsReported) { + if (enclosingClass.doesMixinLackConstructors) { return false; } // diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart index 3cc06268aa9..6f5480d992f 100644 --- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart +++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart @@ -184,7 +184,6 @@ class DeclarationMatcher extends RecursiveAstVisitor { _enclosingClass = element; _processElement(element); _assertSameTypeParameters(node.typeParameters, element.typeParameters); - _processElement(element.unnamedConstructor); super.visitClassTypeAlias(node); } diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart index 422a8e2f14d..2d337b4b8d0 100644 --- a/pkg/analyzer/lib/src/generated/resolver.dart +++ b/pkg/analyzer/lib/src/generated/resolver.dart @@ -5,9 +5,6 @@ library engine.resolver; import 'dart:collection'; -import "dart:math" as math; - -import 'package:analyzer/src/generated/utilities_collection.dart'; import 'ast.dart'; import 'constant.dart'; @@ -2506,7 +2503,6 @@ class ElementBuilder extends RecursiveAstVisitor { interfaceType.typeArguments = typeArguments; element.type = interfaceType; // set default constructor - element.constructors = _createDefaultConstructors(interfaceType); for (FunctionTypeImpl functionType in _functionTypesToFix) { functionType.typeArguments = typeArguments; } @@ -2631,6 +2627,11 @@ class ElementBuilder extends RecursiveAstVisitor { enumElement.enum2 = true; InterfaceTypeImpl enumType = new InterfaceTypeImpl(enumElement); enumElement.type = enumType; + // The equivalent code for enums in the spec shows a single constructor, + // but that constructor is not callable (since it is a compile-time error + // to subclass, mix-in, implement, or explicitly instantiate an enum). So + // we represent this as having no constructors. + enumElement.constructors = ConstructorElement.EMPTY_LIST; _currentHolder.addEnum(enumElement); enumName.staticElement = enumElement; return super.visitEnumDeclaration(node); @@ -5144,275 +5145,6 @@ class HtmlUnitBuilder implements ht.XmlVisitor { } } -/** - * 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. - * - * 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 SimpleElementVisitor { - final AnalysisErrorListener errorListener; - - /** - * Callback to receive the computations to be performed. - */ - final ImplicitConstructorBuilderCallback _callback; - - /** - * Initialize a newly created visitor to build implicit constructors. - * - * The visit methods will pass closures to [_callback] to indicate what - * computation needs to be performed, and its dependency order. - */ - ImplicitConstructorBuilder(this.errorListener, this._callback); - - @override - void visitClassElement(ClassElement classElement) { - (classElement as ClassElementImpl).mixinErrorsReported = false; - if (classElement.isMixinApplication) { - _visitClassTypeAlias(classElement); - } else { - _visitClassDeclaration(classElement); - } - } - - @override - void visitCompilationUnitElement(CompilationUnitElement element) { - element.types.forEach(visitClassElement); - } - - @override - void visitLibraryElement(LibraryElement element) { - element.units.forEach(visitCompilationUnitElement); - } - - /** - * Create an implicit constructor that is copied from the given constructor, but that is in the - * given class. - * - * @param classType the class in which the implicit constructor is defined - * @param explicitConstructor the constructor on which the implicit constructor is modeled - * @param parameterTypes the types to be replaced when creating parameters - * @param argumentTypes the types with which the parameters are to be replaced - * @return the implicit constructor that was created - */ - ConstructorElement _createImplicitContructor(InterfaceType classType, - ConstructorElement explicitConstructor, List parameterTypes, - List argumentTypes) { - ConstructorElementImpl implicitConstructor = - new ConstructorElementImpl(explicitConstructor.name, -1); - implicitConstructor.synthetic = true; - implicitConstructor.redirectedConstructor = explicitConstructor; - implicitConstructor.const2 = explicitConstructor.isConst; - implicitConstructor.returnType = classType; - List explicitParameters = explicitConstructor.parameters; - int count = explicitParameters.length; - if (count > 0) { - List implicitParameters = - new List(count); - for (int i = 0; i < count; i++) { - ParameterElement explicitParameter = explicitParameters[i]; - ParameterElementImpl implicitParameter = - new ParameterElementImpl(explicitParameter.name, -1); - implicitParameter.const3 = explicitParameter.isConst; - implicitParameter.final2 = explicitParameter.isFinal; - implicitParameter.parameterKind = explicitParameter.parameterKind; - implicitParameter.synthetic = true; - implicitParameter.type = - explicitParameter.type.substitute2(argumentTypes, parameterTypes); - implicitParameters[i] = implicitParameter; - } - implicitConstructor.parameters = implicitParameters; - } - FunctionTypeImpl type = new FunctionTypeImpl(implicitConstructor); - type.typeArguments = classType.typeArguments; - implicitConstructor.type = type; - return implicitConstructor; - } - - /** - * Find all the constructors that should be forwarded from the given - * [superType], to the class or mixin application [classElement], - * and pass information about them to [callback]. - * - * Return true if some constructors were considered. (A false return value - * can only happen if the supeclass is a built-in type, in which case it - * can't be used as a mixin anyway). - */ - bool _findForwardedConstructors(ClassElementImpl classElement, - InterfaceType superType, void callback( - ConstructorElement explicitConstructor, List parameterTypes, - List argumentTypes)) { - ClassElement superclassElement = superType.element; - List constructors = superclassElement.constructors; - int count = constructors.length; - if (count == 0) { - return false; - } - List parameterTypes = - TypeParameterTypeImpl.getTypes(superType.typeParameters); - List argumentTypes = _getArgumentTypes(superType, parameterTypes); - for (int i = 0; i < count; i++) { - ConstructorElement explicitConstructor = constructors[i]; - if (!explicitConstructor.isFactory && - classElement.isSuperConstructorAccessible(explicitConstructor)) { - callback(explicitConstructor, parameterTypes, argumentTypes); - } - } - return true; - } - - /** - * Return a list of argument types that corresponds to the [parameterTypes] - * and that are derived from the type arguments of the given [superType]. - */ - List _getArgumentTypes( - InterfaceType superType, List parameterTypes) { - DynamicTypeImpl dynamic = DynamicTypeImpl.instance; - int parameterCount = parameterTypes.length; - List types = new List(parameterCount); - if (superType == null) { - types = new List.filled(parameterCount, dynamic); - } else { - List typeArguments = superType.typeArguments; - int argumentCount = math.min(typeArguments.length, parameterCount); - for (int i = 0; i < argumentCount; i++) { - types[i] = typeArguments[i]; - } - for (int i = argumentCount; i < parameterCount; i++) { - types[i] = dynamic; - } - } - return types; - } - - void _visitClassDeclaration(ClassElementImpl classElement) { - DartType superType = classElement.supertype; - if (superType != null && classElement.mixins.isNotEmpty) { - // We don't need to build any implicitly constructors for the mixin - // application (since there isn't an explicit element for it), but we - // need to verify that they _could_ be built. - if (superType is! InterfaceType) { - TypeProvider typeProvider = classElement.context.typeProvider; - superType = typeProvider.objectType; - } - ClassElement superElement = superType.element; - if (superElement != null) { - _callback(classElement, superElement, () { - bool constructorFound = false; - void callback(ConstructorElement explicitConstructor, - List parameterTypes, List argumentTypes) { - constructorFound = true; - } - if (_findForwardedConstructors(classElement, superType, callback) && - !constructorFound) { - SourceRange withRange = classElement.withClauseRange; - errorListener.onError(new AnalysisError(classElement.source, - withRange.offset, withRange.length, - CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS, - [superElement.name])); - classElement.mixinErrorsReported = true; - } - }); - } - } - } - - void _visitClassTypeAlias(ClassElementImpl classElement) { - InterfaceType superType = classElement.supertype; - if (superType is InterfaceType) { - ClassElement superElement = superType.element; - _callback(classElement, superElement, () { - List implicitConstructors = - new List(); - void callback(ConstructorElement explicitConstructor, - List parameterTypes, List argumentTypes) { - implicitConstructors.add(_createImplicitContructor(classElement.type, - explicitConstructor, parameterTypes, argumentTypes)); - } - if (_findForwardedConstructors(classElement, superType, callback)) { - if (implicitConstructors.isEmpty) { - errorListener.onError(new AnalysisError(classElement.source, - classElement.nameOffset, classElement.name.length, - CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS, - [superElement.name])); - } else { - classElement.constructors = implicitConstructors; - } - } - }); - } - } -} - -/** - * An instance of this class is capable of running ImplicitConstructorBuilder - * over all classes in a library cycle. - */ -class ImplicitConstructorComputer { - /** - * 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 _dependencies = new DirectedGraph(); - - /** - * Map from ClassElement to the function which will compute the class's - * implicit constructors. - */ - Map _computations = - new HashMap(); - - /** - * Add the given [libraryElement] to the list of libraries which need to have - * implicit constructors built for them. - */ - void add(AnalysisErrorListener errorListener, LibraryElement libraryElement) { - libraryElement - .accept(new ImplicitConstructorBuilder(errorListener, _defer)); - } - - /** - * Compute the implicit constructors for all compilation units that have been - * passed to [add]. - */ - void compute() { - List> topologicalSort = - _dependencies.computeTopologicalSort(); - for (List 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. @@ -7917,7 +7649,6 @@ class LibraryResolver { _typeProvider = new TypeProviderImpl(coreElement, asyncElement); _buildEnumMembers(); _buildTypeHierarchies(); - _buildImplicitConstructors(); // // Perform resolution and type analysis. // @@ -8197,22 +7928,6 @@ class LibraryResolver { }); } - /** - * Finish steps that the [buildTypeHierarchies] could not perform, see - * [ImplicitConstructorBuilder]. - * - * @throws AnalysisException if any of the type hierarchies could not be resolved - */ - void _buildImplicitConstructors() { - PerformanceStatistics.resolve.makeCurrentWhile(() { - ImplicitConstructorComputer computer = new ImplicitConstructorComputer(); - for (Library library in _librariesInCycles) { - computer.add(_errorListener, library.libraryElement); - } - computer.compute(); - }); - } - /** * Resolve the type hierarchy across all of the types declared in the libraries in the current * cycle. @@ -8653,7 +8368,6 @@ class LibraryResolver2 { _typeProvider = new TypeProviderImpl(coreElement, asyncElement); _buildEnumMembers(); _buildTypeHierarchies(); - _buildImplicitConstructors(); // // Perform resolution and type analysis. // @@ -8855,22 +8569,6 @@ class LibraryResolver2 { }); } - /** - * Finish steps that the [buildTypeHierarchies] could not perform, see - * [ImplicitConstructorBuilder]. - * - * @throws AnalysisException if any of the type hierarchies could not be resolved - */ - void _buildImplicitConstructors() { - PerformanceStatistics.resolve.makeCurrentWhile(() { - ImplicitConstructorComputer computer = new ImplicitConstructorComputer(); - for (ResolvableLibrary library in _librariesInCycle) { - computer.add(_errorListener, library.libraryElement); - } - computer.compute(); - }); - } - HashMap _buildLibraryMap() { HashMap libraryMap = new HashMap(); diff --git a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart index cc90ec648f3..217a0d83b96 100644 --- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart +++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart @@ -268,6 +268,7 @@ class TestTypeProvider implements TypeProvider { "iterator", false, iteratorType.substitute4([eType])), ElementFactory.getterElement("last", false, eType) ]); + iterableElement.constructors = ConstructorElement.EMPTY_LIST; _propagateTypeArguments(iterableElement); } return _iterableType; @@ -282,6 +283,7 @@ class TestTypeProvider implements TypeProvider { _setAccessors(iteratorElement, [ ElementFactory.getterElement("current", false, eType) ]); + iteratorElement.constructors = ConstructorElement.EMPTY_LIST; _propagateTypeArguments(iteratorElement); } return _iteratorType; @@ -330,6 +332,7 @@ class TestTypeProvider implements TypeProvider { ElementFactory.methodElement( "[]=", VoidTypeImpl.instance, [kType, vType]) ]; + mapElement.constructors = ConstructorElement.EMPTY_LIST; _propagateTypeArguments(mapElement); } return _mapType; @@ -356,7 +359,9 @@ class TestTypeProvider implements TypeProvider { @override InterfaceType get nullType { if (_nullType == null) { - _nullType = ElementFactory.classElement2("Null").type; + ClassElementImpl nullElement = ElementFactory.classElement2("Null"); + nullElement.constructors = ConstructorElement.EMPTY_LIST; + _nullType = nullElement.type; } return _nullType; } @@ -552,7 +557,9 @@ class TestTypeProvider implements TypeProvider { ]; fromEnvironment.factory = true; fromEnvironment.isCycleFree = true; + numElement.constructors = ConstructorElement.EMPTY_LIST; intElement.constructors = [fromEnvironment]; + doubleElement.constructors = ConstructorElement.EMPTY_LIST; List fields = [ ElementFactory.fieldElement("NAN", true, false, true, _doubleType), ElementFactory.fieldElement("INFINITY", true, false, true, _doubleType), diff --git a/pkg/analyzer/lib/src/plugin/engine_plugin.dart b/pkg/analyzer/lib/src/plugin/engine_plugin.dart index 6269cf7b102..eb516de99ac 100644 --- a/pkg/analyzer/lib/src/plugin/engine_plugin.dart +++ b/pkg/analyzer/lib/src/plugin/engine_plugin.dart @@ -62,12 +62,10 @@ class EnginePlugin implements Plugin { // // Register Dart tasks. // - registerExtension(taskId, BuildClassConstructorsTask.DESCRIPTOR); registerExtension(taskId, BuildCompilationUnitElementTask.DESCRIPTOR); registerExtension(taskId, BuildDirectiveElementsTask.DESCRIPTOR); registerExtension(taskId, BuildEnumMemberElementsTask.DESCRIPTOR); registerExtension(taskId, BuildExportNamespaceTask.DESCRIPTOR); - registerExtension(taskId, BuildLibraryConstructorsTask.DESCRIPTOR); registerExtension(taskId, BuildLibraryElementTask.DESCRIPTOR); registerExtension(taskId, BuildPublicNamespaceTask.DESCRIPTOR); registerExtension(taskId, BuildSourceExportClosureTask.DESCRIPTOR); diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart index 849ae337630..f785b365556 100644 --- a/pkg/analyzer/lib/src/task/dart.dart +++ b/pkg/analyzer/lib/src/task/dart.dart @@ -5,7 +5,6 @@ library analyzer.src.task.dart; import 'dart:collection'; -import 'dart:math' as math; import 'package:analyzer/src/context/cache.dart'; import 'package:analyzer/src/generated/ast.dart'; @@ -58,17 +57,6 @@ final ListResultDescriptor BUILD_LIBRARY_ERRORS = new ListResultDescriptor( 'BUILD_LIBRARY_ERRORS', AnalysisError.NO_ERRORS); -/** - * The [ClassElement]s of a [Source] representing a Dart library. - * - * The list contains the elements for all of the classes defined in the library, - * not just those in the defining compilation unit. The list will be empty if - * there are no classes, but will not be `null`. - */ -final ListResultDescriptor CLASS_ELEMENTS = - new ListResultDescriptor('CLASS_ELEMENTS', null, - cachingPolicy: ELEMENT_CACHING_POLICY); - /** * A list of the [ConstantEvaluationTarget]s defined in a unit. This includes * constants defined at top level, statically inside classes, and local to @@ -111,23 +99,6 @@ final ResultDescriptor CONSTANT_VALUE = new ResultDescriptor('CONSTANT_VALUE', null, cachingPolicy: ELEMENT_CACHING_POLICY); -/** - * The [ConstructorElement]s of a [ClassElement]. - */ -final ListResultDescriptor CONSTRUCTORS = - new ListResultDescriptor('CONSTRUCTORS', null); - -/** - * The errors produced while building a [ClassElement] constructors. - * - * The list will be empty if there were no errors, but will not be `null`. - * - * The result is only available for targets representing a [ClassElement]. - */ -final ListResultDescriptor CONSTRUCTORS_ERRORS = - new ListResultDescriptor( - 'CONSTRUCTORS_ERRORS', AnalysisError.NO_ERRORS); - /** * The sources representing the libraries that include a given source as a part. * @@ -232,17 +203,6 @@ final ResultDescriptor LIBRARY_ELEMENT5 = new ResultDescriptor('LIBRARY_ELEMENT5', null, cachingPolicy: ELEMENT_CACHING_POLICY); -/** - * The partial [LibraryElement] associated with a library. - * - * [LIBRARY_ELEMENT5] plus resolved elements and types for all expressions. - * - * The result is only available for [Source]s representing a library. - */ -final ResultDescriptor LIBRARY_ELEMENT6 = - new ResultDescriptor('LIBRARY_ELEMENT6', null, - cachingPolicy: ELEMENT_CACHING_POLICY); - /** * The flag specifying whether all analysis errors are computed in a specific * library. @@ -426,234 +386,6 @@ List removeDuplicateErrors(List errors) { return errors.toSet().toList(); } -/** - * A task that builds implicit constructors for a [ClassElement], or keeps - * the existing explicit constructors if the class has them. - */ -class BuildClassConstructorsTask extends SourceBasedAnalysisTask { - /** - * The name of the [CONSTRUCTORS] input for the superclass. - */ - static const String SUPER_CONSTRUCTORS = 'SUPER_CONSTRUCTORS'; - - /** - * The task descriptor describing this kind of task. - */ - static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( - 'BuildConstructorsForClassTask', createTask, buildInputs, - [CONSTRUCTORS, CONSTRUCTORS_ERRORS]); - - BuildClassConstructorsTask( - InternalAnalysisContext context, AnalysisTarget target) - : super(context, target); - - @override - TaskDescriptor get descriptor => DESCRIPTOR; - - @override - void internalPerform() { - List errors = []; - // - // Prepare inputs. - // - ClassElementImpl classElement = this.target; - List superConstructors = inputs[SUPER_CONSTRUCTORS]; - DartType superType = classElement.supertype; - if (superType == null) { - return; - } - // - // Shortcut for ClassElement(s) without implicit constructors. - // - if (superConstructors == null) { - outputs[CONSTRUCTORS] = classElement.constructors; - outputs[CONSTRUCTORS_ERRORS] = AnalysisError.NO_ERRORS; - return; - } - // - // ClassTypeAlias - // - if (classElement.isMixinApplication) { - List implicitConstructors = - new List(); - void callback(ConstructorElement explicitConstructor, - List parameterTypes, List argumentTypes) { - implicitConstructors.add(_createImplicitContructor(classElement.type, - explicitConstructor, parameterTypes, argumentTypes)); - } - if (_findForwardedConstructors(classElement, superType, callback)) { - if (implicitConstructors.isEmpty) { - errors.add(new AnalysisError(classElement.source, - classElement.nameOffset, classElement.name.length, - CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS, - [superType.element.name])); - } else { - classElement.constructors = implicitConstructors; - } - } - outputs[CONSTRUCTORS] = classElement.constructors; - outputs[CONSTRUCTORS_ERRORS] = errors; - } - // - // ClassDeclaration - // - if (!classElement.isMixinApplication) { - bool constructorFound = false; - void callback(ConstructorElement explicitConstructor, - List parameterTypes, List argumentTypes) { - constructorFound = true; - } - if (_findForwardedConstructors(classElement, superType, callback) && - !constructorFound) { - SourceRange withRange = classElement.withClauseRange; - errors.add(new AnalysisError(classElement.source, withRange.offset, - withRange.length, CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS, - [superType.element.name])); - classElement.mixinErrorsReported = true; - } - outputs[CONSTRUCTORS] = classElement.constructors; - outputs[CONSTRUCTORS_ERRORS] = errors; - } - } - - /** - * Return a map from the names of the inputs of this kind of task to the task - * input descriptors describing those inputs for a task with the - * given [classElement]. - */ - static Map buildInputs(AnalysisTarget target) { - ClassElement element = target; - Source librarySource = element.library.source; - DartType superType = element.supertype; - if (superType is InterfaceType) { - if (element.isMixinApplication || element.mixins.isNotEmpty) { - ClassElement superElement = superType.element; - return { - 'libraryDep': LIBRARY_ELEMENT5.of(librarySource), - SUPER_CONSTRUCTORS: CONSTRUCTORS.of(superElement) - }; - } - } - // No implicit constructors. - // Depend on LIBRARY_ELEMENT5 for invalidation. - return { - 'libraryDep': LIBRARY_ELEMENT5.of(librarySource) - }; - } - - /** - * Create a [BuildClassConstructorsTask] based on the given - * [target] in the given [context]. - */ - static BuildClassConstructorsTask createTask( - AnalysisContext context, AnalysisTarget target) { - return new BuildClassConstructorsTask(context, target); - } - - /** - * Create an implicit constructor that is copied from the given - * [explicitConstructor], but that is in the given class. - * - * [classType] - the class in which the implicit constructor is defined. - * [explicitConstructor] - the constructor on which the implicit constructor - * is modeled. - * [parameterTypes] - the types to be replaced when creating parameters. - * [argumentTypes] - the types with which the parameters are to be replaced. - */ - static ConstructorElement _createImplicitContructor(InterfaceType classType, - ConstructorElement explicitConstructor, List parameterTypes, - List argumentTypes) { - ConstructorElementImpl implicitConstructor = - new ConstructorElementImpl(explicitConstructor.name, -1); - implicitConstructor.synthetic = true; - implicitConstructor.redirectedConstructor = explicitConstructor; - implicitConstructor.const2 = explicitConstructor.isConst; - implicitConstructor.returnType = classType; - List explicitParameters = explicitConstructor.parameters; - int count = explicitParameters.length; - if (count > 0) { - List implicitParameters = - new List(count); - for (int i = 0; i < count; i++) { - ParameterElement explicitParameter = explicitParameters[i]; - ParameterElementImpl implicitParameter = - new ParameterElementImpl(explicitParameter.name, -1); - implicitParameter.const3 = explicitParameter.isConst; - implicitParameter.final2 = explicitParameter.isFinal; - implicitParameter.parameterKind = explicitParameter.parameterKind; - implicitParameter.synthetic = true; - implicitParameter.type = - explicitParameter.type.substitute2(argumentTypes, parameterTypes); - implicitParameters[i] = implicitParameter; - } - implicitConstructor.parameters = implicitParameters; - } - FunctionTypeImpl type = new FunctionTypeImpl(implicitConstructor); - type.typeArguments = classType.typeArguments; - implicitConstructor.type = type; - return implicitConstructor; - } - - /** - * Find all the constructors that should be forwarded from the given - * [superType], to the class or mixin application [classElement], - * and pass information about them to [callback]. - * - * Return `true` if some constructors were considered. (A `false` return value - * can only happen if the supeclass is a built-in type, in which case it - * can't be used as a mixin anyway). - */ - static bool _findForwardedConstructors(ClassElementImpl classElement, - InterfaceType superType, void callback( - ConstructorElement explicitConstructor, List parameterTypes, - List argumentTypes)) { - if (superType == null) { - return false; - } - ClassElement superclassElement = superType.element; - List constructors = superclassElement.constructors; - int count = constructors.length; - if (count == 0) { - return false; - } - List parameterTypes = - TypeParameterTypeImpl.getTypes(superType.typeParameters); - List argumentTypes = _getArgumentTypes(superType, parameterTypes); - for (int i = 0; i < count; i++) { - ConstructorElement explicitConstructor = constructors[i]; - if (!explicitConstructor.isFactory && - classElement.isSuperConstructorAccessible(explicitConstructor)) { - callback(explicitConstructor, parameterTypes, argumentTypes); - } - } - return true; - } - - /** - * Return a list of argument types that corresponds to the [parameterTypes] - * and that are derived from the type arguments of the given [superType]. - */ - static List _getArgumentTypes( - InterfaceType superType, List parameterTypes) { - DynamicTypeImpl dynamic = DynamicTypeImpl.instance; - int parameterCount = parameterTypes.length; - List types = new List(parameterCount); - if (superType == null) { - types = new List.filled(parameterCount, dynamic); - } else { - List typeArguments = superType.typeArguments; - int argumentCount = math.min(typeArguments.length, parameterCount); - for (int i = 0; i < argumentCount; i++) { - types[i] = typeArguments[i]; - } - for (int i = argumentCount; i < parameterCount; i++) { - types[i] = dynamic; - } - } - return types; - } -} - /** * A task that builds a compilation unit element for a single compilation unit. */ @@ -1127,59 +859,6 @@ class BuildExportNamespaceTask extends SourceBasedAnalysisTask { } } -/** - * This task builds [LIBRARY_ELEMENT6] by forcing building constructors for - * all the classes of the defining and part units of a library. - */ -class BuildLibraryConstructorsTask extends SourceBasedAnalysisTask { - /** - * The name of the [LIBRARY_ELEMENT5] input. - */ - static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; - - /** - * The task descriptor describing this kind of task. - */ - static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( - 'BuildLibraryConstructorsTask', createTask, buildInputs, - [LIBRARY_ELEMENT6]); - - BuildLibraryConstructorsTask( - InternalAnalysisContext context, AnalysisTarget target) - : super(context, target); - - @override - TaskDescriptor get descriptor => DESCRIPTOR; - - @override - void internalPerform() { - LibraryElement library = getRequiredInput(LIBRARY_INPUT); - outputs[LIBRARY_ELEMENT6] = library; - } - - /** - * Return a map from the names of the inputs of this kind of task to the task - * input descriptors describing those inputs for a task with the - * given [target]. - */ - static Map buildInputs(AnalysisTarget target) { - Source source = target; - return { - LIBRARY_INPUT: LIBRARY_ELEMENT5.of(source), - 'resolvedConstructors': CLASS_ELEMENTS.of(source).toListOf(CONSTRUCTORS), - }; - } - - /** - * Create a [BuildLibraryConstructorsTask] based on the given [target] in - * the given [context]. - */ - static BuildLibraryConstructorsTask createTask( - AnalysisContext context, AnalysisTarget target) { - return new BuildLibraryConstructorsTask(context, target); - } -} - /** * A task that builds a library element for a Dart library. */ @@ -1201,7 +880,6 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask { static final TaskDescriptor DESCRIPTOR = new TaskDescriptor( 'BuildLibraryElementTask', createTask, buildInputs, [ BUILD_LIBRARY_ERRORS, - CLASS_ELEMENTS, LIBRARY_ELEMENT1, IS_LAUNCHABLE ]); @@ -1337,17 +1015,9 @@ class BuildLibraryElementTask extends SourceBasedAnalysisTask { _patchTopLevelAccessors(libraryElement); } // - // Prepare all class elements. - // - List classElements = libraryElement.units - .map((CompilationUnitElement unitElement) => unitElement.types) - .expand((List unitClassElements) => unitClassElements) - .toList(); - // // Record outputs. // outputs[BUILD_LIBRARY_ERRORS] = errors; - outputs[CLASS_ELEMENTS] = classElements; outputs[LIBRARY_ELEMENT1] = libraryElement; outputs[IS_LAUNCHABLE] = entryPoint != null; } @@ -2613,11 +2283,6 @@ class LibraryUnitErrorsTask extends SourceBasedAnalysisTask { */ static const String VERIFY_ERRORS_INPUT = 'VERIFY_ERRORS'; - /** - * The name of the [CONSTRUCTORS_ERRORS] input. - */ - static const String CONSTRUCTORS_ERRORS_INPUT = 'CONSTRUCTORS_ERRORS'; - /** * The task descriptor describing this kind of task. */ @@ -2637,7 +2302,6 @@ class LibraryUnitErrorsTask extends SourceBasedAnalysisTask { // Prepare inputs. // List> errorLists = >[]; - errorLists.addAll(getRequiredInput(CONSTRUCTORS_ERRORS_INPUT)); errorLists.add(getRequiredInput(HINTS_INPUT)); errorLists.add(getRequiredInput(RESOLVE_REFERENCES_ERRORS_INPUT)); errorLists.add(getRequiredInput(RESOLVE_TYPE_NAMES_ERRORS_INPUT)); @@ -2657,10 +2321,6 @@ class LibraryUnitErrorsTask extends SourceBasedAnalysisTask { static Map buildInputs(AnalysisTarget target) { LibrarySpecificUnit unit = target; return { - CONSTRUCTORS_ERRORS_INPUT: COMPILATION_UNIT_ELEMENT - .of(unit) - .mappedToList((CompilationUnitElement element) => element.types) - .toListOf(CONSTRUCTORS_ERRORS), HINTS_INPUT: HINTS.of(unit), RESOLVE_REFERENCES_ERRORS_INPUT: RESOLVE_REFERENCES_ERRORS.of(unit), RESOLVE_TYPE_NAMES_ERRORS_INPUT: RESOLVE_TYPE_NAMES_ERRORS.of(unit), @@ -3010,7 +2670,7 @@ class ReferencedNamesBuilder extends RecursiveAstVisitor { */ class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask { /** - * The name of the [LIBRARY_ELEMENT6] input. + * The name of the [LIBRARY_ELEMENT5] input. */ static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; @@ -3060,7 +2720,7 @@ class ResolveLibraryReferencesTask extends SourceBasedAnalysisTask { static Map buildInputs(AnalysisTarget target) { Source source = target; return { - LIBRARY_INPUT: LIBRARY_ELEMENT6.of(source), + LIBRARY_INPUT: LIBRARY_ELEMENT5.of(source), UNITS_INPUT: UNITS.of(source).toList((Source unit) => RESOLVED_UNIT5.of(new LibrarySpecificUnit(source, unit))), 'resolvedUnits': IMPORT_EXPORT_SOURCE_CLOSURE @@ -3140,7 +2800,7 @@ class ResolveLibraryTypeNamesTask extends SourceBasedAnalysisTask { */ class ResolveUnitReferencesTask extends SourceBasedAnalysisTask { /** - * The name of the [LIBRARY_ELEMENT6] input. + * The name of the [LIBRARY_ELEMENT5] input. */ static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; @@ -3206,8 +2866,8 @@ class ResolveUnitReferencesTask extends SourceBasedAnalysisTask { return { 'fullyBuiltLibraryElements': IMPORT_EXPORT_SOURCE_CLOSURE .of(unit.library) - .toListOf(LIBRARY_ELEMENT6), - LIBRARY_INPUT: LIBRARY_ELEMENT6.of(unit.library), + .toListOf(LIBRARY_ELEMENT5), + LIBRARY_INPUT: LIBRARY_ELEMENT5.of(unit.library), UNIT_INPUT: RESOLVED_UNIT4.of(unit), TYPE_PROVIDER_INPUT: TYPE_PROVIDER.of(AnalysisContextTarget.request) }; @@ -3313,7 +2973,7 @@ class ResolveUnitTypeNamesTask extends SourceBasedAnalysisTask { */ class ResolveVariableReferencesTask extends SourceBasedAnalysisTask { /** - * The name of the [LIBRARY_ELEMENT6] input. + * The name of the [LIBRARY_ELEMENT1] input. */ static const String LIBRARY_INPUT = 'LIBRARY_INPUT'; diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart index e163fd06e83..0a1b03a5778 100644 --- a/pkg/analyzer/test/generated/all_the_rest_test.dart +++ b/pkg/analyzer/test/generated/all_the_rest_test.dart @@ -1061,6 +1061,8 @@ class ConstantFinderTest extends EngineTestCase { ElementFactory.constructorElement(classElement, '', true); constructorDeclaration.element = constructorElement; classElement.constructors = [constructorElement]; + } else { + classElement.constructors = ConstructorElement.EMPTY_LIST; } return variableDeclaration; } @@ -8256,7 +8258,6 @@ final Map LIBRARIES = const { } } - @reflectiveTest class StringScannerTest extends AbstractScannerTest { @override diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart index cfc2f626a02..e2124442a74 100644 --- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart +++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart @@ -1912,10 +1912,7 @@ class C = a.A with M;''' class M {} class C = bool with M;'''); computeLibrarySourceErrors(source); - assertErrors(source, [ - CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, - CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS - ]); + assertErrors(source, [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]); verify([source]); } @@ -1933,10 +1930,7 @@ class C = double with M;'''); class M {} class C = int with M;'''); computeLibrarySourceErrors(source); - assertErrors(source, [ - CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, - CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS - ]); + assertErrors(source, [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]); verify([source]); } @@ -1963,10 +1957,7 @@ class C = num with M;'''); class M {} class C = String with M;'''); computeLibrarySourceErrors(source); - assertErrors(source, [ - CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS, - CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS - ]); + assertErrors(source, [CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS]); verify([source]); } @@ -5282,6 +5273,22 @@ class M2 = Object with M1;'''); verify([source]); } + void test_recursiveInterfaceInheritance_mixin_superclass() { + // Make sure we don't get CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS in + // addition--that would just be confusing. + Source source = addSource(''' +class C = D with M; +class D = C with M; +class M {} +'''); + computeLibrarySourceErrors(source); + assertErrors(source, [ + CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE, + CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE + ]); + verify([source]); + } + void test_recursiveInterfaceInheritance_tail() { Source source = addSource(r''' abstract class A implements A {} diff --git a/pkg/analyzer/test/generated/element_test.dart b/pkg/analyzer/test/generated/element_test.dart index 5bdceca03be..d5f9ffb2f6a 100644 --- a/pkg/analyzer/test/generated/element_test.dart +++ b/pkg/analyzer/test/generated/element_test.dart @@ -2380,6 +2380,7 @@ class InterfaceTypeImplTest extends EngineTestCase { void test_getConstructors_empty() { ClassElementImpl typeElement = ElementFactory.classElement2("A"); + typeElement.constructors = ConstructorElement.EMPTY_LIST; InterfaceTypeImpl type = new InterfaceTypeImpl(typeElement); expect(type.constructors, isEmpty); } diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart index a796d5e5d64..e3607589b03 100644 --- a/pkg/analyzer/test/generated/resolver_test.dart +++ b/pkg/analyzer/test/generated/resolver_test.dart @@ -13365,11 +13365,6 @@ class TypeResolverVisitorTest extends EngineTestCase { */ TypeResolverVisitor _visitor; - /** - * The visitor used to resolve types needed to form the type hierarchy. - */ - ImplicitConstructorBuilder _implicitConstructorBuilder; - void fail_visitConstructorDeclaration() { fail("Not yet tested"); _listener.assertNoErrors(); @@ -13420,14 +13415,6 @@ class TypeResolverVisitorTest extends EngineTestCase { _typeProvider = new TestTypeProvider(); _visitor = new TypeResolverVisitor.con1(_library, librarySource, _typeProvider); - _implicitConstructorBuilder = new ImplicitConstructorBuilder(_listener, - (ClassElement classElement, ClassElement superclassElement, - void computation()) { - // For these tests, we assume the classes for which implicit - // constructors need to be built are visited in proper dependency order, - // so we just invoke the computation immediately. - computation(); - }); } void test_visitCatchClause_exception() { @@ -13827,9 +13814,6 @@ class TypeResolverVisitorTest extends EngineTestCase { } } node.accept(_visitor); - if (node is Declaration) { - node.element.accept(_implicitConstructorBuilder); - } } } diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart index c89e6e9e919..77db0102ae1 100644 --- a/pkg/analyzer/test/src/task/dart_test.dart +++ b/pkg/analyzer/test/src/task/dart_test.dart @@ -28,14 +28,12 @@ import '../context/abstract_context.dart'; main() { groupSep = ' | '; - runReflectiveTests(BuildClassConstructorsTaskTest); runReflectiveTests(BuildCompilationUnitElementTaskTest); runReflectiveTests(BuildDirectiveElementsTaskTest); runReflectiveTests(BuildEnumMemberElementsTaskTest); runReflectiveTests(BuildSourceExportClosureTaskTest); runReflectiveTests(BuildSourceImportExportClosureTaskTest); runReflectiveTests(BuildExportNamespaceTaskTest); - runReflectiveTests(BuildLibraryConstructorsTaskTest); runReflectiveTests(BuildLibraryElementTaskTest); runReflectiveTests(BuildPublicNamespaceTaskTest); runReflectiveTests(BuildTypeProviderTaskTest); @@ -58,112 +56,6 @@ main() { runReflectiveTests(VerifyUnitTaskTest); } -@reflectiveTest -class BuildClassConstructorsTaskTest extends _AbstractDartTaskTest { - test_perform_ClassDeclaration_errors_mixinHasNoConstructors() { - Source source = newSource('/test.dart', ''' -class B { - B({x}); -} -class M {} -class C extends B with M {} -'''); - LibraryElement libraryElement; - { - computeResult(source, LIBRARY_ELEMENT5); - libraryElement = outputs[LIBRARY_ELEMENT5]; - } - // prepare C - ClassElement c = libraryElement.getType('C'); - expect(c, isNotNull); - // build constructors - computeResult(c, CONSTRUCTORS); - expect(task, new isInstanceOf()); - _fillErrorListener(CONSTRUCTORS_ERRORS); - errorListener.assertErrorsWithCodes( - [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS]); - } - - test_perform_ClassDeclaration_explicitConstructors() { - Source source = newSource('/test.dart', ''' -class B { - B(p); -} -class C extends B { - C(int a, String b) {} -} -'''); - LibraryElement libraryElement; - { - computeResult(source, LIBRARY_ELEMENT5); - libraryElement = outputs[LIBRARY_ELEMENT5]; - } - // prepare C - ClassElement c = libraryElement.getType('C'); - expect(c, isNotNull); - // build constructors - computeResult(c, CONSTRUCTORS); - expect(task, new isInstanceOf()); - // no errors - expect(outputs[CONSTRUCTORS_ERRORS], isEmpty); - // explicit constructor - List constructors = outputs[CONSTRUCTORS]; - expect(constructors, hasLength(1)); - expect(constructors[0].parameters, hasLength(2)); - } - - test_perform_ClassTypeAlias() { - Source source = newSource('/test.dart', ''' -class B { - B(int i); -} -class M1 {} -class M2 {} - -class C2 = C1 with M2; -class C1 = B with M1; -'''); - LibraryElement libraryElement; - { - computeResult(source, LIBRARY_ELEMENT5); - libraryElement = outputs[LIBRARY_ELEMENT5]; - } - // prepare C2 - ClassElement class2 = libraryElement.getType('C2'); - expect(class2, isNotNull); - // build constructors - computeResult(class2, CONSTRUCTORS); - expect(task, new isInstanceOf()); - List constructors = outputs[CONSTRUCTORS]; - expect(constructors, hasLength(1)); - expect(constructors[0].parameters, hasLength(1)); - } - - test_perform_ClassTypeAlias_errors_mixinHasNoConstructors() { - Source source = newSource('/test.dart', ''' -class B { - B({x}); -} -class M {} -class C = B with M; -'''); - LibraryElement libraryElement; - { - computeResult(source, LIBRARY_ELEMENT5); - libraryElement = outputs[LIBRARY_ELEMENT5]; - } - // prepare C - ClassElement c = libraryElement.getType('C'); - expect(c, isNotNull); - // build constructors - computeResult(c, CONSTRUCTORS); - expect(task, new isInstanceOf()); - _fillErrorListener(CONSTRUCTORS_ERRORS); - errorListener.assertErrorsWithCodes( - [CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS]); - } -} - @reflectiveTest class BuildCompilationUnitElementTaskTest extends _AbstractDartTaskTest { Source source; @@ -714,40 +606,6 @@ int topLevelB; } } -@reflectiveTest -class BuildLibraryConstructorsTaskTest extends _AbstractDartTaskTest { - test_perform() { - Source source = newSource('/test.dart', ''' -class B { - B(int i); -} -class M1 {} -class M2 {} - -class C2 = C1 with M2; -class C1 = B with M1; -class C3 = B with M2; -'''); - computeResult(source, LIBRARY_ELEMENT6); - expect(task, new isInstanceOf()); - LibraryElement libraryElement = outputs[LIBRARY_ELEMENT6]; - // C1 - { - ClassElement classElement = libraryElement.getType('C2'); - List constructors = classElement.constructors; - expect(constructors, hasLength(1)); - expect(constructors[0].parameters, hasLength(1)); - } - // C3 - { - ClassElement classElement = libraryElement.getType('C3'); - List constructors = classElement.constructors; - expect(constructors, hasLength(1)); - expect(constructors[0].parameters, hasLength(1)); - } - } -} - @reflectiveTest class BuildLibraryElementTaskTest extends _AbstractDartTaskTest { Source librarySource; @@ -798,7 +656,7 @@ part of lib; part of lib; ''' }); - expect(outputs, hasLength(4)); + expect(outputs, hasLength(3)); // simple outputs expect(outputs[BUILD_LIBRARY_ERRORS], isEmpty); expect(outputs[IS_LAUNCHABLE], isFalse); @@ -839,28 +697,6 @@ part of lib; (libraryUnit.directives[2] as PartDirective).element, same(secondPart)); } - test_perform_classElements() { - _performBuildTask({ - '/lib.dart': ''' -library lib; -part 'part1.dart'; -part 'part2.dart'; -class A {} -''', - '/part1.dart': ''' -part of lib; -class B {} -''', - '/part2.dart': ''' -part of lib; -class C {} -''' - }); - List classElements = outputs[CLASS_ELEMENTS]; - List classNames = classElements.map((c) => c.displayName).toList(); - expect(classNames, unorderedEquals(['A', 'B', 'C'])); - } - test_perform_error_missingLibraryDirectiveWithPart_hasCommon() { _performBuildTask({ '/lib.dart': ''' @@ -2054,7 +1890,6 @@ class LibraryUnitErrorsTaskTest extends _AbstractDartTaskTest { .buildInputs(new LibrarySpecificUnit(emptySource, emptySource)); expect(inputs, isNotNull); expect(inputs.keys, unorderedEquals([ - LibraryUnitErrorsTask.CONSTRUCTORS_ERRORS_INPUT, LibraryUnitErrorsTask.HINTS_INPUT, LibraryUnitErrorsTask.RESOLVE_REFERENCES_ERRORS_INPUT, LibraryUnitErrorsTask.RESOLVE_TYPE_NAMES_ERRORS_INPUT,