Skip to content

Commit

Permalink
Added better toString() for TypeInfo, added more generics tests, move…
Browse files Browse the repository at this point in the history
…d JSOptionalParam outside JSObjectTypeInfo
  • Loading branch information
LatvianModder committed Jun 8, 2024
1 parent e3420d4 commit 763f9dd
Show file tree
Hide file tree
Showing 15 changed files with 286 additions and 33 deletions.
8 changes: 6 additions & 2 deletions src/main/java/dev/latvian/mods/rhino/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,10 @@ public int internalConversionWeight(Object fromObj, TypeInfo target) {
return CONVERSION_NONE;
}

public int internalConversionWeightLast(Object fromObj, TypeInfo target) {
return CONVERSION_NONE;
}

/**
* Create class loader for generated classes.
*/
Expand Down Expand Up @@ -1680,7 +1684,7 @@ public final int getConversionWeight(Object from, TypeInfo target) {
} else if (target instanceof ArrayTypeInfo) {
return 3;
} else {
return CONVERSION_NONE;
return internalConversionWeightLast(from, target);
}
}
case JSTYPE_OBJECT -> {
Expand Down Expand Up @@ -1722,7 +1726,7 @@ public final int getConversionWeight(Object from, TypeInfo target) {
}
}

return CONVERSION_NONE;
return internalConversionWeightLast(from, target);
}

public static int getSizeRank(TypeInfo aType) {
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/dev/latvian/mods/rhino/type/ArrayTypeInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ public String toString() {
return component + "[]";
}

@Override
public void append(TypeStringContext ctx, StringBuilder sb) {
ctx.append(sb, component);
sb.append('[');
sb.append(']');
}

@Override
public String signature() {
return component.signature() + "[]";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import java.util.Map;

public class BasicClassTypeInfo extends ClassTypeInfo {
static final Map<Class<?>, ClassTypeInfo> CACHE = new IdentityHashMap<>();
static final Map<Class<?>, BasicClassTypeInfo> CACHE = new IdentityHashMap<>();

BasicClassTypeInfo(Class<?> type) {
super(type);
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/dev/latvian/mods/rhino/type/ClassTypeInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,9 @@ public boolean equals(Object o) {
public String toString() {
return type.getName();
}

@Override
public void append(TypeStringContext ctx, StringBuilder sb) {
ctx.appendClassName(sb, this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,25 @@ public record JSFixedArrayTypeInfo(TypeInfo... types) implements TypeInfo {
public Class<?> asClass() {
return TypeInfo.class;
}

@Override
public String toString() {
return TypeStringContext.DEFAULT.toString(this);
}

@Override
public void append(TypeStringContext ctx, StringBuilder sb) {
sb.append('[');

for (int i = 0; i < types.length; i++) {
if (i != 0) {
sb.append(',');
ctx.appendSpace(sb);
}

ctx.append(sb, types[i]);
}

sb.append(']');
}
}
34 changes: 32 additions & 2 deletions src/main/java/dev/latvian/mods/rhino/type/JSFunctionTypeInfo.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,41 @@
package dev.latvian.mods.rhino.type;

import java.util.Map;
import java.util.List;

// (a: string) => void
public record JSFunctionTypeInfo(Map<String, TypeInfo> fields, TypeInfo returnType) implements TypeInfo {
public record JSFunctionTypeInfo(List<JSOptionalParam> params, TypeInfo returnType) implements TypeInfo {
@Override
public Class<?> asClass() {
return TypeInfo.class;
}

@Override
public String toString() {
return TypeStringContext.DEFAULT.toString(this);
}

@Override
public void append(TypeStringContext ctx, StringBuilder sb) {
sb.append('(');

boolean first = true;

for (var param : params) {
if (first) {
first = false;
} else {
sb.append(',');
ctx.appendSpace(sb);
}

param.append(ctx, sb);
}

sb.append(')');
ctx.appendSpace(sb);
sb.append('=');
sb.append('>');
ctx.appendSpace(sb);
ctx.append(sb, returnType);
}
}
53 changes: 30 additions & 23 deletions src/main/java/dev/latvian/mods/rhino/type/JSObjectTypeInfo.java
Original file line number Diff line number Diff line change
@@ -1,41 +1,48 @@
package dev.latvian.mods.rhino.type;

import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import java.util.List;

import java.util.Map;
// {a: string, b?: number}
public record JSObjectTypeInfo(List<JSOptionalParam> fields) implements TypeInfo {
public static JSObjectTypeInfo of(JSOptionalParam field) {
return new JSObjectTypeInfo(List.of(field));
}

// {a: string, b: number}
public record JSObjectTypeInfo(Map<String, Field> fields) implements TypeInfo {
public record Field(String name, TypeInfo type, boolean optional) {
public Field(String name, TypeInfo type) {
this(name, type, false);
}
public static JSObjectTypeInfo of(JSOptionalParam field1, JSOptionalParam field2) {
return new JSObjectTypeInfo(List.of(field1, field2));
}

public static JSObjectTypeInfo of(Field field) {
return new JSObjectTypeInfo(Map.of(field.name, field));
public static JSObjectTypeInfo of(JSOptionalParam... fields) {
return new JSObjectTypeInfo(List.of(fields));
}

public static JSObjectTypeInfo of(Field field1, Field field2) {
return new JSObjectTypeInfo(Map.of(field1.name, field1, field2.name, field2));
@Override
public Class<?> asClass() {
return TypeInfo.class;
}

public static JSObjectTypeInfo of(Field field1, Field field2, Field field3) {
return new JSObjectTypeInfo(Map.of(field1.name, field1, field2.name, field2, field3.name, field3));
@Override
public String toString() {
return TypeStringContext.DEFAULT.toString(this);
}

public static JSObjectTypeInfo of(Field... fields) {
var map = new Object2ObjectArrayMap<String, Field>(fields.length);
@Override
public void append(TypeStringContext ctx, StringBuilder sb) {
sb.append('{');

boolean first = true;

for (var field : fields) {
map.put(field.name, field);
if (first) {
first = false;
} else {
sb.append(',');
ctx.appendSpace(sb);
}

field.append(ctx, sb);
}

return new JSObjectTypeInfo(map);
}

@Override
public Class<?> asClass() {
return TypeInfo.class;
sb.append('}');
}
}
26 changes: 26 additions & 0 deletions src/main/java/dev/latvian/mods/rhino/type/JSOptionalParam.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package dev.latvian.mods.rhino.type;

public record JSOptionalParam(String name, TypeInfo type, boolean optional) {
public JSOptionalParam(String name, TypeInfo type) {
this(name, type, false);
}

@Override
public String toString() {
var sb = new StringBuilder();
append(TypeStringContext.DEFAULT, sb);
return sb.toString();
}

public void append(TypeStringContext ctx, StringBuilder sb) {
sb.append(name);

if (optional) {
sb.append('?');
}

sb.append(':');
ctx.appendSpace(sb);
ctx.append(sb, type);
}
}
18 changes: 18 additions & 0 deletions src/main/java/dev/latvian/mods/rhino/type/JSOrTypeInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,22 @@ public TypeInfo or(TypeInfo info) {
arr[types.length] = info;
return new JSOrTypeInfo(arr);
}

@Override
public String toString() {
return TypeStringContext.DEFAULT.toString(this);
}

@Override
public void append(TypeStringContext ctx, StringBuilder sb) {
for (int i = 0; i < types.length; i++) {
if (i != 0) {
ctx.appendSpace(sb);
sb.append('|');
ctx.appendSpace(sb);
}

ctx.append(sb, types[i]);
}
}
}
5 changes: 5 additions & 0 deletions src/main/java/dev/latvian/mods/rhino/type/NoTypeInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ public String toString() {
return "?";
}

@Override
public void append(TypeStringContext ctx, StringBuilder sb) {
sb.append('?');
}

@Override
public TypeInfo asArray() {
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,24 @@ public boolean equals(Object object) {

@Override
public String toString() {
var sb = new StringBuilder(rawType.toString());
return TypeStringContext.DEFAULT.toString(this);
}

@Override
public void append(TypeStringContext ctx, StringBuilder sb) {
ctx.append(sb, rawType);
sb.append('<');

for (int i = 0; i < params.length; i++) {
if (i > 0) {
sb.append(", ");
sb.append(',');
ctx.appendSpace(sb);
}

sb.append(params[i]);
ctx.append(sb, params[i]);
}

sb.append('>');
return sb.toString();
}

@Override
Expand All @@ -78,6 +83,11 @@ public TypeInfo[] params() {
return params;
}

@Override
public Object newArray(int length) {
return rawType.newArray(length);
}

@Override
public TypeInfo withParams(TypeInfo... params) {
return rawType.withParams(params);
Expand Down
20 changes: 19 additions & 1 deletion src/main/java/dev/latvian/mods/rhino/type/TypeInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,21 @@ static TypeInfo of(Type type) {
case ParameterizedType paramType -> of(paramType.getRawType()).withParams(ofArray(paramType.getActualTypeArguments()));
case GenericArrayType arrType -> of(arrType.getGenericComponentType()).asArray();
case TypeVariable<?> ignore -> NONE; // ClassTypeInfo.OBJECT
case WildcardType wildcard -> of(wildcard.getUpperBounds()[0]);
case WildcardType wildcard -> {
var lower = wildcard.getLowerBounds();

if (lower.length == 0) {
var upper = wildcard.getUpperBounds();

if (upper.length == 0 || upper[0] == Object.class) {
yield NONE;
}

yield of(upper[0]);
} else {
yield of(lower[0]);
}
}
case null, default -> NONE;
};
}
Expand Down Expand Up @@ -199,4 +213,8 @@ default List<Object> enumConstants() {
default TypeInfo or(TypeInfo info) {
return new JSOrTypeInfo(this, info);
}

default void append(TypeStringContext ctx, StringBuilder sb) {
sb.append(this);
}
}
24 changes: 24 additions & 0 deletions src/main/java/dev/latvian/mods/rhino/type/TypeStringContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package dev.latvian.mods.rhino.type;

public interface TypeStringContext {
TypeStringContext DEFAULT = new TypeStringContext() {
};

default String toString(TypeInfo info) {
var sb = new StringBuilder();
append(sb, info);
return sb.toString();
}

default void append(StringBuilder sb, TypeInfo type) {
type.append(this, sb);
}

default void appendClassName(StringBuilder sb, ClassTypeInfo type) {
sb.append(type.asClass().getName());
}

default void appendSpace(StringBuilder sb) {
sb.append(' ');
}
}
Loading

0 comments on commit 763f9dd

Please sign in to comment.