Skip to content

Commit 5c82b28

Browse files
Allow regular TS types as type arguments in customTypeMappings (#384)
example: `Map<string,string>`
1 parent 3c25020 commit 5c82b28

File tree

4 files changed

+66
-56
lines changed

4 files changed

+66
-56
lines changed
Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11

22
package cz.habarta.typescript.generator;
33

4-
import java.lang.reflect.ParameterizedType;
4+
import cz.habarta.typescript.generator.util.Pair;
5+
import cz.habarta.typescript.generator.util.Utils;
56
import java.lang.reflect.Type;
67
import java.util.ArrayList;
78
import java.util.List;
@@ -22,47 +23,46 @@ public CustomMappingTypeProcessor(List<Settings.CustomTypeMapping> customMapping
2223

2324
@Override
2425
public Result processType(Type javaType, Context context) {
25-
if (javaType instanceof Class) {
26-
final Class<?> javaClass = (Class<?>) javaType;
27-
final Settings.CustomTypeMapping mapping = customMappings.get(javaClass.getName());
28-
if (mapping != null) {
29-
return new Result(new TsType.BasicType(mapping.tsType.rawName));
30-
}
26+
final Pair<Class<?>, List<Type>> rawClassAndTypeArguments = Utils.getRawClassAndTypeArguments(javaType);
27+
if (rawClassAndTypeArguments == null) {
28+
return null;
29+
}
30+
final Class<?> rawClass = rawClassAndTypeArguments.getValue1();
31+
final List<Type> typeArguments = rawClassAndTypeArguments.getValue2();
32+
final Settings.CustomTypeMapping mapping = customMappings.get(rawClass.getName());
33+
if (mapping == null) {
34+
return null;
3135
}
32-
if (javaType instanceof ParameterizedType) {
33-
final ParameterizedType parameterizedType = (ParameterizedType) javaType;
34-
if (parameterizedType.getRawType() instanceof Class) {
35-
final Class<?> javaClass = (Class<?>) parameterizedType.getRawType();
36-
final Settings.CustomTypeMapping mapping = customMappings.get(javaClass.getName());
37-
if (mapping != null) {
38-
final List<Class<?>> discoveredClasses = new ArrayList<>();
39-
final Function<Integer, TsType> processGenericParameter = index -> {
40-
final Type typeArgument = parameterizedType.getActualTypeArguments()[index];
41-
final TypeProcessor.Result typeArgumentResult = context.processType(typeArgument);
42-
discoveredClasses.addAll(typeArgumentResult.getDiscoveredClasses());
43-
return typeArgumentResult.getTsType();
44-
};
45-
if (mapping.tsType.typeParameters != null) {
46-
final List<TsType> tsTypeArguments = new ArrayList<>();
47-
for (String typeParameter : mapping.tsType.typeParameters) {
48-
final int index = mapping.javaType.typeParameters.indexOf(typeParameter);
49-
final TsType tsType = processGenericParameter.apply(index);
50-
tsTypeArguments.add(tsType);
51-
}
52-
return new Result(new TsType.GenericBasicType(mapping.tsType.rawName, tsTypeArguments), discoveredClasses);
53-
} else {
54-
final int index = mapping.javaType.typeParameters.indexOf(mapping.tsType.rawName);
55-
if (index != -1) {
56-
final TsType tsType = processGenericParameter.apply(index);
57-
return new Result(tsType, discoveredClasses);
58-
} else {
59-
return new Result(new TsType.BasicType(mapping.tsType.rawName), discoveredClasses);
60-
}
61-
}
36+
37+
final List<Class<?>> discoveredClasses = new ArrayList<>();
38+
final Function<Integer, TsType> processGenericParameter = index -> {
39+
final Type typeArgument = typeArguments.get(index);
40+
final TypeProcessor.Result typeArgumentResult = context.processType(typeArgument);
41+
discoveredClasses.addAll(typeArgumentResult.getDiscoveredClasses());
42+
return typeArgumentResult.getTsType();
43+
};
44+
if (mapping.tsType.typeParameters != null) {
45+
final List<TsType> tsTypeArguments = new ArrayList<>();
46+
for (String typeParameter : mapping.tsType.typeParameters) {
47+
final TsType tsType;
48+
final int index = mapping.javaType.indexOfTypeParameter(typeParameter);
49+
if (index != -1) {
50+
tsType = processGenericParameter.apply(index);
51+
} else {
52+
tsType = new TsType.VerbatimType(typeParameter);
6253
}
54+
tsTypeArguments.add(tsType);
55+
}
56+
return new Result(new TsType.GenericBasicType(mapping.tsType.rawName, tsTypeArguments), discoveredClasses);
57+
} else {
58+
final int index = mapping.javaType.indexOfTypeParameter(mapping.tsType.rawName);
59+
if (index != -1) {
60+
final TsType tsType = processGenericParameter.apply(index);
61+
return new Result(tsType, discoveredClasses);
62+
} else {
63+
return new Result(new TsType.BasicType(mapping.tsType.rawName), discoveredClasses);
6364
}
6465
}
65-
return null;
6666
}
6767

6868
}

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/Settings.java

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ public GenericName(String rawName, List<String> typeParameters) {
151151
this.rawName = Objects.requireNonNull(rawName);
152152
this.typeParameters = typeParameters;
153153
}
154+
155+
public int indexOfTypeParameter(String typeParameter) {
156+
return typeParameters != null ? typeParameters.indexOf(typeParameter) : -1;
157+
}
154158
}
155159

156160
private static class TypeScriptGeneratorURLClassLoader extends URLClassLoader {
@@ -413,16 +417,6 @@ public List<CustomTypeMapping> getValidatedCustomTypeMappings() {
413417
"Wrong number of specified generic parameters, required: %s, found: %s. Correct format is: '%s'",
414418
required, specified, signature));
415419
}
416-
if (genericTsName.typeParameters != null) {
417-
final Set<String> parameters = Stream.of(cls.getTypeParameters())
418-
.map(TypeVariable::getName)
419-
.collect(Collectors.toSet());
420-
for (String parameter : genericTsName.typeParameters) {
421-
if (!parameters.contains(parameter)) {
422-
throw new RuntimeException(String.format("Unknown generic type parameter '%s'", parameter));
423-
}
424-
}
425-
}
426420
validatedCustomTypeMappings.add(new CustomTypeMapping(genericJavaName, genericTsName));
427421
} catch (Exception e) {
428422
throw new RuntimeException(String.format("Failed to parse configured custom type mapping '%s:%s': %s", javaName, tsName, e.getMessage()), e);

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/util/Utils.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,20 @@ private static String trimSlash(String path) {
8181
}
8282

8383
public static Class<?> getRawClassOrNull(Type type) {
84-
if (type instanceof Class<?>) {
85-
return (Class<?>) type;
86-
} else if (type instanceof ParameterizedType) {
84+
final Pair<Class<?>, List<Type>> rawClassAndTypeArguments = getRawClassAndTypeArguments(type);
85+
return rawClassAndTypeArguments != null ? rawClassAndTypeArguments.getValue1() : null;
86+
}
87+
88+
public static Pair<Class<?>, List<Type>> getRawClassAndTypeArguments(Type type) {
89+
if (type instanceof Class) {
90+
final Class<?> javaClass = (Class<?>) type;
91+
return Pair.of(javaClass, Collections.emptyList());
92+
}
93+
if (type instanceof ParameterizedType) {
8794
final ParameterizedType parameterizedType = (ParameterizedType) type;
88-
final Type rawType = parameterizedType.getRawType();
89-
if (rawType instanceof Class<?>) {
90-
return (Class<?>) rawType;
95+
if (parameterizedType.getRawType() instanceof Class) {
96+
final Class<?> javaClass = (Class<?>) parameterizedType.getRawType();
97+
return Pair.of(javaClass, Arrays.asList(parameterizedType.getActualTypeArguments()));
9198
}
9299
}
93100
return null;

typescript-generator-core/src/test/java/cz/habarta/typescript/generator/GenericCustomTypeMappingsTest.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,8 @@ private static class IdRepresentation<T> {
7070
public void testInvalidGenerics() {
7171
testInvalid("NonExisting", "string");
7272
testInvalid(NonGeneric.class.getName() + "<T>", "string");
73-
testInvalid(NonGeneric.class.getName(), "string<T>");
7473
testInvalid(Generic2.class.getName(), "string");
7574
testInvalid(Generic2.class.getName() + "<T>", "string");
76-
testInvalid(Generic2.class.getName() + "<T1, T2>", "string<T>");
7775
}
7876

7977
private static void testInvalid(String javaName, String tsName) {
@@ -103,7 +101,18 @@ public void testUnwrap() {
103101
Assert.assertTrue(output.contains("generic: number"));
104102
}
105103

104+
@Test
105+
public void testMapStringString() {
106+
final Settings settings = TestUtils.settings();
107+
settings.customTypeMappings = Collections.singletonMap("cz.habarta.typescript.generator.GenericCustomTypeMappingsTest$NonGeneric", "Map<string, string>");
108+
final String output = new TypeScriptGenerator(settings).generateTypeScript(Input.from(NonGenericUsage.class));
109+
Assert.assertTrue(output.contains("nonGeneric: Map<string, string>"));
110+
}
111+
106112
private static class NonGeneric {}
113+
private static class NonGenericUsage {
114+
public NonGeneric nonGeneric;
115+
}
107116
private static class Generic2<T1, T2> {}
108117
private static class Usage {
109118
public Generic2<String, Integer> generic;

0 commit comments

Comments
 (0)