Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1742,7 +1742,7 @@ private void checkParams(Element where, String preMsg, List<Expr> args, List<Wur
// if (expected instanceof AstElementWithTypeArgs)
if (!actual.isSubtypeOf(expected, where)) {
args.get(i).addError(
preMsg + "Expected " + expected + " as parameter " + (i + 1) + " but found " + actual);
preMsg + "Expected " + expected + " as parameter " + (i + 1) + " but found " + actual);
}
}
}
Expand Down Expand Up @@ -2363,22 +2363,30 @@ private void checkConstructor(ConstructorDef d) {
WurstTypeClass ct = c.attrTypC();
WurstTypeClass extendedClass = ct.extendedClass();
if (extendedClass != null) {
// check if super constructor is called correctly...
// TODO check constr: get it from ct so that it has the correct type binding
// Use the *bound* super-constructor signature
ConstructorDef sc = d.attrSuperConstructor();
if (sc == null) {
d.addError("No super constructor found.");
} else {
List<WurstType> paramTypes = Lists.newArrayList();
// Build expected param types in the subclass binding context
List<WurstType> expected = Lists.newArrayList();

// The binding that maps the superclass type params to the subclass type args
VariableBinding binding = extendedClass.getTypeArgBinding();

for (WParameter p : sc.getParameters()) {
paramTypes.add(p.attrTyp());
WurstType t = p.attrTyp();
t = t.setTypeArgs(binding);

expected.add(t);
}

if (d.getSuperConstructorCall() instanceof NoSuperConstructorCall
&& paramTypes.size() > 0) {
&& !expected.isEmpty()) {
c.addError("The extended class <" + extendedClass.getName() + "> does not expose a no-arg constructor. " +
"You must define a constructor that calls super(..) appropriately, in this class.");
"You must define a constructor that calls super(..) appropriately, in this class.");
} else {
checkParams(d, "Incorrect call to super constructor: ", superArgs(d), paramTypes);
checkParams(d, "Incorrect call to super constructor: ", superArgs(d), expected);
}
}
}
Expand All @@ -2390,6 +2398,7 @@ private void checkConstructor(ConstructorDef d) {
}



private void checkArrayAccess(ExprVarArrayAccess ea) {
checkNameRefDeprecated(ea, ea.tryGetNameDef());
for (Expr index : ea.getIndexes()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1472,5 +1472,41 @@ public void callingDestroyThisInConstructor() {
" testSuccess()",
"endpackage");
}
@Test
public void derivedGenericClassConstructor() {
testAssertOkLinesWithStdLib(true,
"package test",
"import LinkedList",
"public class ListIterator<T> extends LLIterator<T>",
" construct(LinkedList<T> parent)",
" super(parent)",
"init",
" let b = new ListIterator<int>(new LinkedList<int>())",
" if b != null",
" testSuccess()",
"endpackage");
}

@Test
public void derivedGenericClassConstructorNewGenerics() {
testAssertOkLines(true,
"package test",
"native testSuccess()",
"class A<T:>",
" T value",
"class B<X:>",
" A<X> a",
" construct(A<X> a)",
" this.a = a",
"public class C<T:> extends B<T>",
" construct(A<T> parent)",
" super(parent)",
"init",
" let b = new C<int>(new A<int>())",
" if b != null",
" testSuccess()",
"endpackage");
}


}
Loading