Revert "Revert "Eliminate retarded constructors.""
This reverts r66 which was a revert of r64. The original commit failed because "optimized" mode builds won't generate NoSuchMethodErrors and that is why the release mode test won't pass. So for that issue, I updated the language.status file. The client failure appears to be test infrastructure flakiness because my rollback failed but the subsequent build succeeded and I'm unable to reproduce the failure at my desk. Review URL: https://chromereviews.googleplex.com/3508025 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@88 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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<Element> 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<DartInitializer> iterator = initializers.iterator();
|
||||
Iterator<DartField> fieldIterator = fieldInitializers.iterator();
|
||||
|
||||
if (hasConstructorInvocation) {
|
||||
// skip the super call
|
||||
DartInitializer first = iterator.next();
|
||||
assert first.isInvocation();
|
||||
}
|
||||
|
||||
List<JsStatement> 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<DartInitializer> 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:
|
||||
// <super-class>.<name>$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);
|
||||
}
|
||||
|
||||
@@ -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<VariableElement> 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.<DartParameter>emptyList(),
|
||||
new DartBlock(Collections.<DartStatement>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<Void> {
|
||||
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.<DartExpression>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());
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 <code>true</code> 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<DartInitializer> 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,
|
||||
|
||||
+1
-1
@@ -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);
|
||||
@@ -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() {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user