diff --git a/co19/tests/co19/co19-compiler.status b/co19/tests/co19/co19-compiler.status index 730d15f4ef5..e5be6848c61 100644 --- a/co19/tests/co19/co19-compiler.status +++ b/co19/tests/co19/co19-compiler.status @@ -131,6 +131,7 @@ LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A02/t02: LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A02/t03: Fail # Bug 5371670. LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A02/t04: Fail # Bug 5371670. LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A03/t01: Fail # Bug 5371670. +LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A03/t02: Fail # Bug 5371670. This will no longer valid due to language spec changes. LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A06/t04: Fail # Bug 5371670. LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A10/t01: Fail # Bug 5371670. LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A13/t01: Fail # Bug 5371670. @@ -216,7 +217,6 @@ LibTest/core/Set/every/Set/every/A01/t04: Skip LangGuideTest/02_Language_Constructs/02_11_Exceptions/A05/t01: Fail LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A05/t01: Fail -LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A12/t01: Fail LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A12/t02: Fail LangGuideTest/02_Language_Constructs/02_1_Class/A02/t04: Skip # Times out. LangGuideTest/02_Language_Constructs/02_5_Meaning_of_Names/A02/t02: Fail diff --git a/compiler/java/com/google/dart/compiler/DartCompilerErrorCode.java b/compiler/java/com/google/dart/compiler/DartCompilerErrorCode.java index be5171be9f8..8b52a11cdcd 100644 --- a/compiler/java/com/google/dart/compiler/DartCompilerErrorCode.java +++ b/compiler/java/com/google/dart/compiler/DartCompilerErrorCode.java @@ -33,6 +33,8 @@ public enum DartCompilerErrorCode implements ErrorCode { CANNOT_RESOLVE_LABEL("cannot resolve label %s"), CANNOT_RESOLVE_METHOD("cannot resolve method %s"), CANNOT_RESOLVE_SUPER_CONSTRUCTOR("cannot resolve method %s"), + CANNOT_RESOLVE_IMPLICIT_CALL_TO_SUPER_CONSTRUCTOR( + "super type %s does not have a default constructor"), CATCH_OR_FINALLY_EXPECTED("catch or finally clause expected."), CONSTRUCTOR_CANNOT_BE_ABSTRACT("A constructor cannot be asbstract"), CONSTRUCTOR_CANNOT_BE_STATIC("A constructor cannot be static"), diff --git a/compiler/java/com/google/dart/compiler/backend/js/GenerateJavascriptAST.java b/compiler/java/com/google/dart/compiler/backend/js/GenerateJavascriptAST.java index 30f70a66ea9..fd31b2fc2b2 100644 --- a/compiler/java/com/google/dart/compiler/backend/js/GenerateJavascriptAST.java +++ b/compiler/java/com/google/dart/compiler/backend/js/GenerateJavascriptAST.java @@ -442,6 +442,11 @@ public class GenerateJavascriptAST { for (Element element : classElement.getMembers()) { classMembers.add(element); } + + if (Elements.needsImplicitDefaultConstructor(classElement)) { + addImplicitDefaultConstructor(x, classElement, classMembers); + } + for (Element member : classMembers) { switch(ElementKind.of(member)) { case METHOD: { @@ -491,6 +496,19 @@ public class GenerateJavascriptAST { return null; } + private void addImplicitDefaultConstructor(DartClass x, ClassElement classElement, + List classElementMembers) { + for (DartNode member : x.getMembers()) { + if (member instanceof DartMethodDefinition) { + DartMethodDefinition method = (DartMethodDefinition) member; + MethodElement symbol = method.getSymbol(); + if (symbol.isConstructor() && "".equals(symbol.getName())) { + classElementMembers.add(symbol); + } + } + } + } + /** * @param classElement * @@ -846,12 +864,6 @@ public class GenerateJavascriptAST { Iterator iterator = initializers.iterator(); Iterator fieldIterator = fieldInitializers.iterator(); - if (hasConstructorInvocation) { - // skip the super call - DartInitializer first = iterator.next(); - assert first.isInvocation(); - } - List jsInitializers = initFunction.getBody().getStatements(); // Do the field inline initializers first. If there are any assignments in the initializer @@ -861,14 +873,19 @@ public class GenerateJavascriptAST { jsInitializers.add(initializer.makeStmt()); } + DartInvocation initInvocation = null; while (iterator.hasNext()) { - jsInitializers.add((JsStatement) generate(iterator.next())); + DartInitializer initializer = iterator.next(); + if (!initializer.isInvocation()) { + jsInitializers.add((JsStatement) generate(initializer)); + } else { + initInvocation = (DartInvocation) initializer.getValue(); + } } if (hasConstructorInvocation) { // Call the super initializer function in the initializer. // Compute the super constructor initializer to call. - DartInvocation initInvocation = (DartInvocation) initializers.get(0).getValue(); ConstructorElement superElement = (ConstructorElement) initInvocation.getSymbol(); // TODO(floitsch): it would be better if we had a js-name and not just a string. // This way the debugging information would be better. @@ -930,10 +947,11 @@ public class GenerateJavascriptAST { // If there are initializers, populate the initializer function. List initializers = constructor.getInitializers(); if (!initializers.isEmpty()) { - DartInitializer firstInit = initializers.get(0); - if (firstInit.isInvocation()) { - JsExprStmt statement = (JsExprStmt) generate(firstInit); - return (JsInvocation) statement.getExpression(); + for (DartInitializer init : initializers) { + if (init.isInvocation()) { + JsExprStmt statement = (JsExprStmt) generate(init); + return (JsInvocation) statement.getExpression(); + } } } return null; @@ -2141,10 +2159,6 @@ public class GenerateJavascriptAST { return expr; } - private JsNameRef nameref(JsName qualifier, String prop) { - return AstUtil.newNameRef(qualifier.makeRef(), prop); - } - private JsBinaryOperation assign(JsNameRef op1, JsExpression op2) { return AstUtil.newAssignment(op1, op2); } @@ -2157,14 +2171,6 @@ public class GenerateJavascriptAST { return new JsBinaryOperation(JsBinaryOperator.OR, op1, op2); } - private JsPrefixOperation not(JsExpression op1) { - return new JsPrefixOperation(JsUnaryOperator.NOT, op1); - } - - private JsBinaryOperation and(JsExpression op1, JsExpression op2) { - return new JsBinaryOperation(JsBinaryOperator.AND, op1, op2); - } - private JsNumberLiteral number(double num) { return translationContext.getProgram().getNumberLiteral(num); } @@ -3028,14 +3034,23 @@ public class GenerateJavascriptAST { // Must use SuperClass.call(this, ...) to get the correct 'this' context in the callee: // .$Constructor.call(this, ...). ConstructorElement element = (ConstructorElement) x.getSymbol(); + Element classElement; + String elementName; + if (element == null) { + classElement = ((ClassElement) currentHolder).getSupertype().getElement(); + elementName = classElement.getName(); + } else { + classElement = element.getEnclosingElement(); + elementName = element.getName(); + } + // TODO(floitsch): it would be good, if we could get a js-name instead of just a string. // This way the debugging information would be better. // We need to generate the JsName (for the initializer/factory) once only and store it // in some hashtable. Then instead of reusing the mangler, we should reuse those JsNames. // The debugging information would then contain a link from the property-access to the // constructor. Without JsName the debugger just assumes we access some random property. - String name = mangler.mangleConstructor(element.getName(), unitLibrary); - Element classElement = element.getEnclosingElement(); + String name = mangler.mangleConstructor(elementName, unitLibrary); JsNameRef constructorRef = AstUtil.newNameRef(getJsName(classElement).makeRef(), name); return generateInvocation(x, constructorRef, true, null, element); } diff --git a/compiler/java/com/google/dart/compiler/backend/js/Normalizer.java b/compiler/java/com/google/dart/compiler/backend/js/Normalizer.java index 72914eec6b7..e049ffda084 100644 --- a/compiler/java/com/google/dart/compiler/backend/js/Normalizer.java +++ b/compiler/java/com/google/dart/compiler/backend/js/Normalizer.java @@ -10,6 +10,7 @@ import com.google.dart.compiler.ast.DartArrayAccess; import com.google.dart.compiler.ast.DartBinaryExpression; import com.google.dart.compiler.ast.DartBlock; import com.google.dart.compiler.ast.DartCase; +import com.google.dart.compiler.ast.DartClass; import com.google.dart.compiler.ast.DartClassMember; import com.google.dart.compiler.ast.DartContext; import com.google.dart.compiler.ast.DartDefault; @@ -35,8 +36,10 @@ import com.google.dart.compiler.ast.DartNodeTraverser; import com.google.dart.compiler.ast.DartParameter; import com.google.dart.compiler.ast.DartParenthesizedExpression; import com.google.dart.compiler.ast.DartPropertyAccess; +import com.google.dart.compiler.ast.DartRedirectConstructorInvocation; import com.google.dart.compiler.ast.DartReturnStatement; import com.google.dart.compiler.ast.DartStatement; +import com.google.dart.compiler.ast.DartSuperConstructorInvocation; import com.google.dart.compiler.ast.DartSwitchMember; import com.google.dart.compiler.ast.DartSwitchStatement; import com.google.dart.compiler.ast.DartThrowStatement; @@ -52,11 +55,17 @@ import com.google.dart.compiler.resolver.ClassElement; import com.google.dart.compiler.resolver.ConstructorElement; import com.google.dart.compiler.resolver.CoreTypeProvider; import com.google.dart.compiler.resolver.Element; +import com.google.dart.compiler.resolver.ElementKind; import com.google.dart.compiler.resolver.Elements; +import com.google.dart.compiler.resolver.EnclosingElement; import com.google.dart.compiler.resolver.FieldElement; import com.google.dart.compiler.resolver.LabelElement; import com.google.dart.compiler.resolver.MethodElement; import com.google.dart.compiler.resolver.VariableElement; +import com.google.dart.compiler.type.FunctionType; +import com.google.dart.compiler.type.InterfaceType; +import com.google.dart.compiler.type.Type; +import com.google.dart.compiler.type.Types; import java.util.ArrayList; import java.util.Arrays; @@ -579,6 +588,112 @@ public class Normalizer { } } + @Override + public DartNode visitClass(DartClass node) { + final ClassElement classElement = node.getSymbol(); + if (Elements.needsImplicitDefaultConstructor(classElement)) { + DartMethodDefinition method = createImplicitDefaultConstructor(classElement); + + // TODO - We should really normalize the class itself. + node.getMembers().add(method); + } + return super.visitClass(node); + } + + static class SyntheticDefaultConstructorElement implements ConstructorElement { + private final DartMethodDefinition method; + private final ClassElement enclosingClass; + + SyntheticDefaultConstructorElement(DartMethodDefinition method, ClassElement enclosingClass) { + this.method = method; + this.enclosingClass = enclosingClass; + } + + @Override + public String getOriginalSymbolName() { + return getName(); + } + + @Override + public DartNode getNode() { + return method; + } + + @Override + public void setNode(DartLabel node) { + } + + @Override + public boolean isDynamic() { + return false; + } + + @Override + public Type getType() { + return null; + } + + @Override + public String getName() { + return ""; + } + + @Override + public Modifiers getModifiers() { + return Modifiers.NONE; + } + + @Override + public ElementKind getKind() { + return ElementKind.CONSTRUCTOR; + } + + @Override + public EnclosingElement getEnclosingElement() { + return enclosingClass; + } + + @Override + public boolean isStatic() { + return false; + } + + @Override + public boolean isConstructor() { + return true; + } + + @Override + public Type getReturnType() { + return null; + } + + @Override + public List getParameters() { + return Collections.emptyList(); + } + + @Override + public FunctionType getFunctionType() { + return null; + } + + @Override + public ClassElement getConstructorType() { + return enclosingClass; + } + } + + private DartMethodDefinition createImplicitDefaultConstructor(final ClassElement classElement) { + assert (Elements.needsImplicitDefaultConstructor(classElement)); + DartFunction function = new DartFunction(Collections.emptyList(), + new DartBlock(Collections.emptyList()), null); + final DartMethodDefinition method = + DartMethodDefinition.create(new DartIdentifier(""), function, Modifiers.NONE, null, null); + method.setSymbol(new SyntheticDefaultConstructorElement(method, classElement)); + return method; + } + @Override public DartExpression visitBinaryExpression(DartBinaryExpression node) { node.visitChildren(this); @@ -605,15 +720,62 @@ public class Normalizer { return node; } + static class NeedsImplicitSuperInvocationDeterminant extends DartNodeTraverser { + private boolean needsSuperInvocation = true; + + @Override + public Void visitSuperConstructorInvocation(DartSuperConstructorInvocation node) { + needsSuperInvocation = false; + return super.visitSuperConstructorInvocation(node); + } + + @Override + public Void visitRedirectConstructorInvocation(DartRedirectConstructorInvocation node) { + needsSuperInvocation = false; + return super.visitRedirectConstructorInvocation(node); + } + + @Override + public Void visitMethodDefinition(DartMethodDefinition node) { + // Ignore everything except the initializers + for (DartInitializer initializer : node.getInitializers()) { + initializer.accept(this); + } + return null; + } + } + @Override public DartMethodDefinition visitMethodDefinition(DartMethodDefinition node) { super.visitMethodDefinition(node); if (Elements.isNonFactoryConstructor(node.getSymbol())) { normalizeParameterInitializer(node); } + return node; } + @Override + public DartNode visitNewExpression(DartNewExpression node) { + ConstructorElement symbol = node.getSymbol(); + if (symbol == null) { + InterfaceType constructorType = Types.constructorType(node); + + // HACK use proper normalized node + ClassElement classToInstantiate = constructorType.getElement(); + if (classToInstantiate.getDefaultClass() != null) { + classToInstantiate = classToInstantiate.getDefaultClass().getElement(); + } + + if (classToInstantiate != null && Elements.needsImplicitDefaultConstructor(classToInstantiate)) { + DartMethodDefinition implicitDefaultConstructor = createImplicitDefaultConstructor(classToInstantiate); + node.setSymbol(implicitDefaultConstructor.getSymbol()); + } + } + + return super.visitNewExpression(node); + } + @Override public DartNode visitSwitchStatement(DartSwitchStatement node) { node.getExpression().accept(this); @@ -647,10 +809,28 @@ public class Normalizer { nInit.add(di); } } + + EnclosingElement enclosingElement = node.getSymbol().getEnclosingElement(); + if (ElementKind.of(enclosingElement) == ElementKind.CLASS) { + ClassElement classElement = (ClassElement) enclosingElement; + if (!classElement.isObject()) { + NeedsImplicitSuperInvocationDeterminant superLocator = new NeedsImplicitSuperInvocationDeterminant(); + node.accept(superLocator); + if (superLocator.needsSuperInvocation) { + DartSuperConstructorInvocation superInvocation = new DartSuperConstructorInvocation( + new DartIdentifier(""), Collections.emptyList()); + superInvocation.setSymbol(new SyntheticDefaultConstructorElement(null, + classElement.getSupertype().getElement())); + nInit.add(new DartInitializer(null, superInvocation)); + } + } + } + if (!nInit.isEmpty()) { if (!node.getInitializers().isEmpty()) { nInit.addAll(0, node.getInitializers()); } + DartMethodDefinition nConstructor = DartMethodDefinition.create( node.getName(), node.getFunction(), node.getModifiers(), nInit, null); nConstructor.setSymbol(node.getSymbol()); diff --git a/compiler/java/com/google/dart/compiler/resolver/Elements.java b/compiler/java/com/google/dart/compiler/resolver/Elements.java index 9241cf7fc02..08d2f3397e7 100644 --- a/compiler/java/com/google/dart/compiler/resolver/Elements.java +++ b/compiler/java/com/google/dart/compiler/resolver/Elements.java @@ -209,4 +209,11 @@ public class Elements { public static Element voidElement() { return VoidElement.getInstance(); } + + /** + * Returns true if the class needs an implicit default constructor. + */ + public static boolean needsImplicitDefaultConstructor(ClassElement classElement) { + return !classElement.isObject() && classElement.getConstructors().isEmpty(); + } } diff --git a/compiler/java/com/google/dart/compiler/resolver/Resolver.java b/compiler/java/com/google/dart/compiler/resolver/Resolver.java index 43e3d6e8410..0067d1ebdab 100644 --- a/compiler/java/com/google/dart/compiler/resolver/Resolver.java +++ b/compiler/java/com/google/dart/compiler/resolver/Resolver.java @@ -237,11 +237,51 @@ public class Resolver { } checkRedirectConstructorCycle(classElement.getConstructors(), context); + if (Elements.needsImplicitDefaultConstructor(classElement)) { + checkImplicitDefaultDefaultSuperInvocation(cls, classElement); + } + context = previousContext; currentHolder = previousHolder; return classElement; } + + /** + * Returns true if the {@link ClassElement} has an implicit or a declared + * default constructor. + */ + boolean hasDefaultConstructor(ClassElement classElement) { + if (Elements.needsImplicitDefaultConstructor(classElement)) { + return true; + } + + ConstructorElement defaultCtor = Elements.lookupConstructor(classElement, ""); + if (defaultCtor != null) { + return defaultCtor.getParameters().isEmpty(); + } + + return false; + } + + private void checkImplicitDefaultDefaultSuperInvocation(DartClass cls, + ClassElement classElement) { + assert (Elements.needsImplicitDefaultConstructor(classElement)); + + InterfaceType supertype = classElement.getSupertype(); + if (supertype != null) { + ClassElement superElement = supertype.getElement(); + if (!superElement.isDynamic()) { + ConstructorElement superCtor = Elements.lookupConstructor(superElement, ""); + if (superCtor != null && !superCtor.getParameters().isEmpty()) { + resolutionError(cls.getName(), + DartCompilerErrorCode.CANNOT_RESOLVE_IMPLICIT_CALL_TO_SUPER_CONSTRUCTOR, + cls.getSuperclass()); + } + } + } + } + private Element resolve(DartNode node) { if (node == null) { return null; @@ -832,11 +872,27 @@ public class Resolver { } }); + if (ElementKind.of(element).equals(ElementKind.CLASS)) { - // Just calling the unnamed constructor. - element = Elements.lookupConstructor(((ClassElement) element), ""); + // Check for default constructor or implicit default constructor + ClassElement classElement = (ClassElement) element; + element = Elements.lookupConstructor(classElement, ""); + if (element == null) { + // Check that the class needs an implicit ctor and no extra args are passed + if (Elements.needsImplicitDefaultConstructor(classElement) && x.getArgs().isEmpty()) { + InterfaceType defaultClass = classElement.getDefaultClass(); + if (defaultClass != null) { + classElement = defaultClass.getElement(); + element = Elements.lookupConstructor(classElement, ""); + } + + if (element == null) { + return recordElement(x, element); + } + } + } } - + // If there is a default implementation, lookup the constructor in the // default class. ConstructorElement constructor = checkIsConstructor(x, element); @@ -850,7 +906,15 @@ public class Resolver { // If the constructor hasn't been found, try the constructor of the default class. // TODO(ngeoffray): check earlier if the default class implements the interface. element = Elements.lookupConstructor(defaultClass, constructor.getName()); + if (element == null && Elements.needsImplicitDefaultConstructor(defaultClass)) { + /* + * Record the element and prevent checkIsConstructor from reporting errors below + * since we know that w don't have an element. + */ + return recordElement(x, element); + } } + // Will check that element is not null. constructor = checkIsConstructor(x, element); } @@ -1106,17 +1170,30 @@ public class Resolver { } private void checkConstructor(DartMethodDefinition node, - ConstructorElement superCall, - boolean firstIsSuper) { + ConstructorElement superCall) { ClassElement currentClass = (ClassElement) currentHolder; + if (superCall == null) { + // Look for a default constructor in our super type + InterfaceType supertype = currentClass.getSupertype(); + if (supertype != null) { + superCall = Elements.lookupConstructor(supertype.getElement(), ""); + } + } + if ((superCall == null) && !currentClass.isObject() && !currentClass.isObjectChild()) { - resolutionError(node, DartCompilerErrorCode.CONSTRUCTOR_MUST_CALL_SUPER); - } else if (!firstIsSuper - && !currentClass.isObject() - && !currentClass.isObjectChild()) { - resolutionError(node, DartCompilerErrorCode.SUPER_CALL_MUST_BE_FIRST); + InterfaceType supertype = currentClass.getSupertype(); + if (supertype != null) { + ClassElement superElement = supertype.getElement(); + if (superElement != null) { + if (!hasDefaultConstructor(superElement)) { + resolutionError(node, + DartCompilerErrorCode.CANNOT_RESOLVE_IMPLICIT_CALL_TO_SUPER_CONSTRUCTOR, + superElement.getName()); + } + } + } } else if ((superCall != null) && node.getModifiers().isConstant() && !superCall.getModifiers().isConstant()) { @@ -1180,22 +1257,17 @@ public class Resolver { private void resolveInitializers(DartMethodDefinition node) { assert null != node; - Element firstElement = null; - DartNode firstNode = null; Iterator initializers = node.getInitializers().iterator(); - if (initializers.hasNext()) { - firstNode = initializers.next(); - firstElement = resolve(firstNode); - } + ConstructorElement constructorElement = null; while (initializers.hasNext()) { - resolve(initializers.next()); + DartInitializer initializer = initializers.next(); + Element element = resolve(initializer); + if (ElementKind.of(element) == ElementKind.CONSTRUCTOR) { + constructorElement = (ConstructorElement) element; + } } - boolean firstIsConstructorInvocation = - ElementKind.of(firstElement).equals(ElementKind.CONSTRUCTOR); - if (firstElement != null && !firstIsConstructorInvocation) { - firstElement = null; - } - checkConstructor(node, (ConstructorElement) firstElement, firstIsConstructorInvocation); + + checkConstructor(node, constructorElement); } private void resolutionError(DartNode node, DartCompilerErrorCode errorCode, diff --git a/compiler/javatests/com/google/dart/compiler/resolver/ConstSuperNegativeTest3.dart b/compiler/javatests/com/google/dart/compiler/resolver/ConstSuperTest.dart similarity index 84% rename from compiler/javatests/com/google/dart/compiler/resolver/ConstSuperNegativeTest3.dart rename to compiler/javatests/com/google/dart/compiler/resolver/ConstSuperTest.dart index 617e4cfb0c1..b540dbad1e0 100644 --- a/compiler/javatests/com/google/dart/compiler/resolver/ConstSuperNegativeTest3.dart +++ b/compiler/javatests/com/google/dart/compiler/resolver/ConstSuperTest.dart @@ -2,7 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// expect one failure - Sub.A omits call to const super. +// expect no failures - Sub.A omits call to const super, but one will be added class Base { const Base(a); diff --git a/compiler/javatests/com/google/dart/compiler/resolver/NegativeResolverTest.java b/compiler/javatests/com/google/dart/compiler/resolver/NegativeResolverTest.java index bbcc0ba2caa..d3c10f7b780 100644 --- a/compiler/javatests/com/google/dart/compiler/resolver/NegativeResolverTest.java +++ b/compiler/javatests/com/google/dart/compiler/resolver/NegativeResolverTest.java @@ -66,15 +66,15 @@ public class NegativeResolverTest extends CompilerTestCase { } public void testConstSuperNegativeTest1() { - checkNumErrors("ConstSuperNegativeTest1.dart", 1); + checkNumErrors("ConstSuperNegativeTest1.dart", 0); } public void testConstSuperNegativeTest2() { checkNumErrors("ConstSuperNegativeTest2.dart", 1); } - public void testConstSuperNegativeTest3() { - checkNumErrors("ConstSuperNegativeTest3.dart", 1); + public void testConstSuperTest() { + checkNumErrors("ConstSuperTest.dart", 0); } public void testParameterInitializerNegativeTest1() { diff --git a/compiler/javatests/com/google/dart/compiler/resolver/ResolverTest.java b/compiler/javatests/com/google/dart/compiler/resolver/ResolverTest.java index 30acde448a4..a87f56db464 100644 --- a/compiler/javatests/com/google/dart/compiler/resolver/ResolverTest.java +++ b/compiler/javatests/com/google/dart/compiler/resolver/ResolverTest.java @@ -214,6 +214,71 @@ public class ResolverTest extends ResolverTestCase { checkExpectedErrors(); } + public void testImplicitDefaultConstructor() { + // Check that the implicit constructor is resolved correctly + resolve(parseUnit( + "class Object {}", + "class B {}", + "class C { main() { new B(); } }"), getContext()); + checkExpectedErrors(); + + /* + * We should check for signature mismatch but that is a TypeAnalyzer issue. + */ + } + + public void testImplicitDefaultConstructor_ThroughFactories() { + // Check that we generate implicit constructors through factories also. + resolve(parseUnit( + "class Object {}", + "interface B factory C {}", + "class C {}", + "class D { main() { new B(); } }"), getContext()); + checkExpectedErrors(); + } + + public void testImplicitDefaultConstructor_WithConstCtor() { + setExpectedErrors(1); + // Check that we generate an error if the implicit constructor would violate const. + resolve(parseUnit( + "class Object {}", + "class B { const B() {} }", + "class C extends B {}", + "class D { main() { new C(); } }"), getContext()); + checkExpectedErrors(); + } + + public void testImplicitSuperCall_ImplicitCtor() { + // Check that we can properly resolve the super ctor that exists. + resolve(parseUnit( + "class Object {}", + "class B { B() {} }", + "class C extends B {}", + "class D { main() { new C(); } }"), getContext()); + checkExpectedErrors(); + } + + public void testImplicitSuperCall_OnExistingCtor() { + // Check that we can properly resolve the super ctor that exists. + resolve(parseUnit( + "class Object {}", + "class B { B() {} }", + "class C extends B { C(){} }", + "class D { main() { new C(); } }"), getContext()); + checkExpectedErrors(); + } + + public void testImplicitSuperCall_NonExistentSuper() { + setExpectedErrors(1); + // Check that we generate an error if the implicit constructor would call a non-existent super. + resolve(parseUnit( + "class Object {}", + "class B { B(Object o) {} }", + "class C extends B {}", + "class D { main() { new C(); } }"), getContext()); + checkExpectedErrors(); + } + public void testCyclicSupertype() { setExpectedErrors(8); resolve(parseUnit( diff --git a/tests/language/language.status b/tests/language/language.status index 096273510bf..4c462be0812 100644 --- a/tests/language/language.status +++ b/tests/language/language.status @@ -57,6 +57,7 @@ NullPointerExceptionTest: Fail # Bug 5391976 CallThroughNullGetterTest: Fail # Bug 5391976 Private3Test: Fail # Bug 5391976 Switch3NegativeTest: Crash # Bug 5318228 +BadNamedParametersTest: Fail # Bug Bug 4202974 - release mode is not throwing NSME # Tests that pass in release mode but fail in debug mode [ ($arch == dartc || $arch == chromium) && $mode == debug ] @@ -67,7 +68,6 @@ Prefix11NegativeTest: Fail # Bug 5406175 Prefix12NegativeTest: Fail,Crash # Bug 5406175 FunctionTypeParameterNegativeTest: Fail # Bug 4568007 ImplicitScopeTest: FAIL # Nested statements can be declarations -ResolveTest: FAIL # 4254120 (implicit constructors) ConstConstructor1NegativeTest: FAIL # 5142545 ConstConstructor2NegativeTest: FAIL # 5142545 MathTest: FAIL # 5165080 @@ -75,7 +75,6 @@ StringConcatTest: FAIL # 5196164 NamedParametersTest: Fail # Implementation in progress. NamedParametersTypeTest: Fail # Implementation in progress. NamedParametersWithConversionsTest: Fail # Implementation in progress. -BadNamedParameters2Test: Fail # Implementation in progress. NamedParametersNegativeTest: Skip # Implementation in progress. NamedParameters2NegativeTest: Skip # Implementation in progress. NamedParameters3NegativeTest: Skip # Implementation in progress. @@ -91,13 +90,13 @@ RegExp3Test: Fail # 5299683 InterfaceFactory3NegativeTest: Fail # 5387405 GenericParameterizedExtendsTest: Skip # Bug 5392297 ConstObjectsAreImmutableTest: Fail # Bug 5202940 +SuperNegativeTest: Fail # Now that super calls are automatically injected this test doesn't make sense # Crashes in dartc. FunctionTypeAliasTest: Crash # Bug 4519208. # Other bugs (or unimplemented features) in dartc. GenericTest: Fail # Bug 5393302 (missing call to super constructor) -GenericInheritanceTest: Fail # Bug 4562150 (implicit constructors). Throw7NegativeTest: Fail # Bug 4208459. Throw3Test: Fail # Bug 4205624. SwitchLabelTest: Fail # Bug 4208467. @@ -108,7 +107,6 @@ PseudoKWNegativeTest: Fail # Bug 4979760. OverriddenNoSuchMethodTest: Fail # Bug 4202974. ManyOverriddenNoSuchMethodTest: Fail # Bug 4202974. NoSuchMethodTest: Fail # Bug 4202974. -BadNamedParametersTest: Fail # Bug 4202974. NumbersTest: Fail # Fails because numbers are mapped to doubles. LocalFunctionTest: Fail # Bug in test. Bug 4202989 (shadowing). LocalFunction3Test: Fail # Bug 4202974. @@ -131,7 +129,6 @@ OverrideFieldMethod3NegativeTest: Fail # Bug 5215249 OverrideFieldMethod4NegativeTest: Fail # Bug 5215249 OverrideFieldMethod5NegativeTest: Fail # Bug 5215249 OverrideFieldMethod6NegativeTest: Fail # Bug 5215249 -DeoptimizationTest: Fail # Bug 4254120 CharEscapeTest: Fail FunctionTypeParameter2NegativeTest: Fail # Bug 4568007