Skip to content

Commit 1c3a8d2

Browse files
committed
Added unit tests + parsing of Java classes with wildcard generics
1 parent 683d3a4 commit 1c3a8d2

File tree

14 files changed

+241
-34
lines changed

14 files changed

+241
-34
lines changed

CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/TypeMatcher.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public Boolean visitOptional(Matching context, OptionalTypeID type) {
147147
public Boolean visitWildcardIn(Matching context, WildcardInTypeID type) throws RuntimeException {
148148
if (context.type instanceof WildcardInTypeID) {
149149
WildcardInTypeID wildcardIn = (WildcardInTypeID) context.type;
150-
return match(context, wildcardIn.upperBound, type.upperBound);
150+
return match(context, wildcardIn.lowerBound, type.lowerBound);
151151
} else {
152152
return false;
153153
}
@@ -157,7 +157,7 @@ public Boolean visitWildcardIn(Matching context, WildcardInTypeID type) throws R
157157
public Boolean visitWildcardOut(Matching context, WildcardOutTypeID type) throws RuntimeException {
158158
if (context.type instanceof WildcardOutTypeID) {
159159
WildcardOutTypeID wildcardOut = (WildcardOutTypeID) context.type;
160-
return match(context, wildcardOut.lowerBound, type.lowerBound);
160+
return match(context, wildcardOut.upperBound, type.upperBound);
161161
} else {
162162
return false;
163163
}

CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/WildcardInTypeID.java

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,22 @@
66
import org.openzen.zenscript.codemodel.type.member.MemberSet;
77

88
import java.util.List;
9+
import java.util.Objects;
910

1011
/**
11-
* Represents a wildcard type with an upper bound. (e.g. ? super Number)
12+
* Represents a wildcard type with a lower bound. (e.g. ? super Number)
1213
*/
1314
public class WildcardInTypeID implements TypeID {
14-
public final TypeID upperBound;
15+
public final TypeID lowerBound;
1516

16-
public WildcardInTypeID(TypeID upperBound) {
17-
this.upperBound = upperBound;
17+
public WildcardInTypeID(TypeID lowerBound) {
18+
this.lowerBound = lowerBound;
1819
}
1920

2021
@Override
2122
public TypeID instance(GenericMapper mapper) {
22-
TypeID mappedUpperBound = upperBound.instance(mapper);
23-
return mappedUpperBound == upperBound ? this : new WildcardInTypeID(mappedUpperBound);
23+
TypeID mappedLowerBound = lowerBound.instance(mapper);
24+
return mappedLowerBound == lowerBound ? this : new WildcardInTypeID(mappedLowerBound);
2425
}
2526

2627
@Override
@@ -30,7 +31,7 @@ public boolean hasDefaultValue() {
3031

3132
@Override
3233
public void extractTypeParameters(List<TypeParameter> typeParameters) {
33-
upperBound.extractTypeParameters(typeParameters);
34+
lowerBound.extractTypeParameters(typeParameters);
3435
}
3536

3637
@Override
@@ -53,4 +54,22 @@ public ResolvingType resolve() {
5354
// No members to inherit, since there is no lower bound...
5455
return MemberSet.create(this).build();
5556
}
57+
58+
@Override
59+
public String toString() {
60+
return "in " + lowerBound;
61+
}
62+
63+
@Override
64+
public boolean equals(Object o) {
65+
if (this == o) return true;
66+
if (o == null || getClass() != o.getClass()) return false;
67+
WildcardInTypeID that = (WildcardInTypeID) o;
68+
return Objects.equals(lowerBound, that.lowerBound);
69+
}
70+
71+
@Override
72+
public int hashCode() {
73+
return Objects.hashCode(lowerBound);
74+
}
5675
}

CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/WildcardOutTypeID.java

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
import org.openzen.zenscript.codemodel.GenericMapper;
44
import org.openzen.zenscript.codemodel.compilation.ResolvingType;
55
import org.openzen.zenscript.codemodel.generic.TypeParameter;
6-
import org.openzen.zenscript.codemodel.type.member.MemberSet;
76

87
import java.util.List;
8+
import java.util.Objects;
99

1010
/**
1111
* Represents a wildcard type with an upper bound. (eg. ? extends Number)
@@ -14,16 +14,16 @@
1414
* subtype of the given bound.
1515
*/
1616
public class WildcardOutTypeID implements TypeID {
17-
public final TypeID lowerBound;
17+
public final TypeID upperBound;
1818

19-
public WildcardOutTypeID(TypeID lowerBound) {
20-
this.lowerBound = lowerBound;
19+
public WildcardOutTypeID(TypeID upperBound) {
20+
this.upperBound = upperBound;
2121
}
2222

2323
@Override
2424
public TypeID instance(GenericMapper mapper) {
25-
TypeID mappedLowerBound = lowerBound.instance(mapper);
26-
return mappedLowerBound == lowerBound ? this : new WildcardOutTypeID(mappedLowerBound);
25+
TypeID mappedUpperBound = upperBound.instance(mapper);
26+
return mappedUpperBound == upperBound ? this : new WildcardOutTypeID(mappedUpperBound);
2727
}
2828

2929
@Override
@@ -33,7 +33,7 @@ public boolean hasDefaultValue() {
3333

3434
@Override
3535
public void extractTypeParameters(List<TypeParameter> typeParameters) {
36-
lowerBound.extractTypeParameters(typeParameters);
36+
upperBound.extractTypeParameters(typeParameters);
3737
}
3838

3939
@Override
@@ -53,7 +53,24 @@ public boolean isValueType() {
5353

5454
@Override
5555
public ResolvingType resolve() {
56-
// No members to inherit, since there is no lower bound...
57-
return MemberSet.create(this).build();
56+
return upperBound.resolve();
57+
}
58+
59+
@Override
60+
public String toString() {
61+
return "out " + upperBound;
62+
}
63+
64+
@Override
65+
public boolean equals(Object o) {
66+
if (this == o) return true;
67+
if (o == null || getClass() != o.getClass()) return false;
68+
WildcardOutTypeID that = (WildcardOutTypeID) o;
69+
return Objects.equals(upperBound, that.upperBound);
70+
}
71+
72+
@Override
73+
public int hashCode() {
74+
return Objects.hashCode(upperBound);
5875
}
5976
}

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaTypeExpressionVisitor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ public Void visitWildcardIn(JavaWriter writer, WildcardInTypeID type) throws Run
128128

129129
@Override
130130
public Void visitWildcardOut(JavaWriter writer, WildcardOutTypeID type) throws RuntimeException {
131-
type.lowerBound.accept(writer, this);
131+
type.upperBound.accept(writer, this);
132132
return null;
133133
}
134134
}

JavaIntegration/src/main/java/org/openzen/zencode/java/impl/conversion/JavaRuntimeTypeConverterImpl.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.openzen.zenscript.codemodel.FunctionHeader;
1313
import org.openzen.zenscript.codemodel.GenericMapper;
1414
import org.openzen.zenscript.codemodel.Modifiers;
15+
import org.openzen.zenscript.codemodel.SemanticModule;
1516
import org.openzen.zenscript.codemodel.compilation.CompileContext;
1617
import org.openzen.zenscript.codemodel.definition.ClassDefinition;
1718
import org.openzen.zenscript.codemodel.definition.ZSPackage;
@@ -130,7 +131,7 @@ private TypeID loadType(TypeVariableContext context, JavaAnnotatedType type) {
130131
case TYPE_VARIABLE:
131132
return loadTypeVariable(context, (TypeVariable<?>) type.getType());
132133
case WILDCARD:
133-
return loadWildcard();
134+
return loadWildcard(context, (WildcardType) type.getType());
134135
}
135136
} catch (final IllegalArgumentException e) {
136137
throw new IllegalArgumentException("Unable to analyze type: " + type, e);
@@ -238,8 +239,16 @@ private TypeID loadTypeVariable(TypeVariableContext context, TypeVariable<?> var
238239
return new GenericTypeID(context.get(variable));
239240
}
240241

241-
private TypeID loadWildcard() {
242-
return BasicTypeID.UNDETERMINED;
242+
private TypeID loadWildcard(TypeVariableContext context, WildcardType wildcardType) {
243+
if (wildcardType.getUpperBounds().length > 0) {
244+
TypeID upperBound = loadType(context, JavaAnnotatedType.of(wildcardType.getUpperBounds()[0]));
245+
return new WildcardOutTypeID(upperBound);
246+
} else if (wildcardType.getLowerBounds().length > 0) {
247+
TypeID lowerBound = loadType(context, JavaAnnotatedType.of(wildcardType.getLowerBounds()[0]));
248+
return new WildcardInTypeID(lowerBound);
249+
} else {
250+
return BasicTypeID.UNDETERMINED;
251+
}
243252
}
244253

245254
private TypeSymbol findType(Class<?> cls) {
@@ -252,10 +261,14 @@ private TypeSymbol findType(Class<?> cls) {
252261
TypeSymbol result = packageInfo.getRoot().getImport(Arrays.asList("stdlib", "Object"), 0);
253262
if (result == null) {
254263

255-
ZSPackage stdlib = packageInfo.getRoot().getOptional("stdlib").orElseThrow(() -> new IllegalStateException("Must depend on stdlib if trying to register java.lang.Object"));
256-
ModuleSymbol module = nativeModuleSpace.moduleSpace.getModule("stdlib").module;
264+
Optional<ZSPackage> stdlib = packageInfo.getRoot().getOptional("stdlib");
265+
ZSPackage targetPackage = stdlib.orElseGet(() -> packageInfo.getRoot().getOrCreatePackage("stdlib"));
266+
ModuleSymbol module = Optional.ofNullable(nativeModuleSpace.moduleSpace.getModule("stdlib"))
267+
.map(x -> x.module)
268+
.orElse(packageInfo.getModule());
269+
257270
// registers itself to the package automatically
258-
new ClassDefinition(CodePosition.BUILTIN, module, stdlib, "Object", Modifiers.PUBLIC, null);
271+
new ClassDefinition(CodePosition.BUILTIN, module, targetPackage, "Object", Modifiers.PUBLIC, null);
259272
result = packageInfo.getRoot().getImport(Arrays.asList("stdlib", "Object"), 0);
260273
}
261274
return result;

JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaSyntheticTypeSignatureConverter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,11 @@ public String visitOptional(OptionalTypeID type) {
148148

149149
@Override
150150
public String visitWildcardIn(WildcardInTypeID type) {
151-
return "-" + type.upperBound.accept(this);
151+
return "-" + type.lowerBound.accept(this);
152152
}
153153

154154
@Override
155155
public String visitWildcardOut(WildcardOutTypeID type) {
156-
return "+" + type.lowerBound.accept(this);
156+
return "+" + type.upperBound.accept(this);
157157
}
158158
}

JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaTypeGenericVisitor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ public String visitWildcardIn(WildcardInTypeID type) {
202202

203203
@Override
204204
public String visitWildcardOut(WildcardOutTypeID type) {
205-
return type.lowerBound.accept(this);
205+
return type.upperBound.accept(this);
206206
}
207207

208208
public String getMethodSignatureExpansion(FunctionHeader header, TypeID expandedClass) {

JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaTypeNameVisitor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,11 @@ public String visitOptional(OptionalTypeID type) {
118118

119119
@Override
120120
public String visitWildcardIn(WildcardInTypeID type) {
121-
return "In" + type.upperBound.accept(this);
121+
return "In" + type.lowerBound.accept(this);
122122
}
123123

124124
@Override
125125
public String visitWildcardOut(WildcardOutTypeID type) {
126-
return "Out" + type.lowerBound.accept(this);
126+
return "Out" + type.upperBound.accept(this);
127127
}
128128
}

JavaShared/src/main/java/org/openzen/zenscript/javashared/prepare/JavaPrepareTypeVisitor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,13 @@ public Void visitOptional(OptionalTypeID type) {
6969

7070
@Override
7171
public Void visitWildcardIn(WildcardInTypeID type) {
72-
type.upperBound.accept(this);
72+
type.lowerBound.accept(this);
7373
return null;
7474
}
7575

7676
@Override
7777
public Void visitWildcardOut(WildcardOutTypeID type) {
78-
type.lowerBound.accept(this);
78+
type.upperBound.accept(this);
7979
return null;
8080
}
8181
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#output: Hello
2+
3+
interface Stringable {
4+
toString(): string;
5+
}
6+
7+
expand string {
8+
implements Stringable {
9+
toString(): string {
10+
return this;
11+
}
12+
}
13+
}
14+
15+
class MyClass<T> {
16+
val value as T : get;
17+
18+
this(value: T) {
19+
this.value = value;
20+
}
21+
}
22+
23+
val a: MyClass<out Stringable> = new MyClass<string>("Hello");
24+
println(a.value.toString());

0 commit comments

Comments
 (0)