Skip to content

Commit 7f67dc4

Browse files
danielkaneidervojtechhabarta
authored andcommitted
Conditionally use non-const enums based on annotation (#248) (#249)
* Conditionally use non-const enums based on annotation (#248) * some cleanup * converted TsEnumModel.isNonConstEnum to final * backwards-compatibility
1 parent c9b76b0 commit 7f67dc4

File tree

8 files changed

+85
-14
lines changed

8 files changed

+85
-14
lines changed

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public class Settings {
4848
public DateMapping mapDate; // default is DateMapping.asDate
4949
public EnumMapping mapEnum; // default is EnumMapping.asUnion
5050
public boolean nonConstEnums = false;
51+
public List<Class<? extends Annotation>> nonConstEnumAnnotations = new ArrayList<>();
5152
public ClassMapping mapClasses; // default is ClassMapping.asInterfaces
5253
public List<String> mapClassesAsClassesPatterns;
5354
private Predicate<String> mapClassesAsClassesFilter = null;
@@ -102,7 +103,7 @@ public TypeScriptGeneratorURLClassLoader(String name, URL[] urls, ClassLoader pa
102103
public String toString() {
103104
return "TsGenURLClassLoader{" + name + ", parent: " + getParent() + "}";
104105
}
105-
106+
106107
}
107108

108109
public static URLClassLoader createClassLoader(String name, URL[] urls, ClassLoader parent) {
@@ -140,6 +141,13 @@ public void loadExtensions(ClassLoader classLoader, List<String> extensions, Lis
140141
}
141142
}
142143

144+
public static List<Class<? extends Annotation>> loadAnnotations(ClassLoader classLoader, List<String> stringAnnotations) {
145+
if (stringAnnotations != null) {
146+
return new ArrayList<>(loadClasses(classLoader, stringAnnotations, Annotation.class));
147+
}
148+
return new ArrayList<>(0);
149+
}
150+
143151
public void loadIncludePropertyAnnotations(ClassLoader classLoader, List<String> includePropertyAnnotations) {
144152
if (includePropertyAnnotations != null) {
145153
this.includePropertyAnnotations = loadClasses(classLoader, includePropertyAnnotations, Annotation.class);
@@ -232,7 +240,7 @@ public void validate() {
232240
defaultStringEnumsOverriddenByExtension = true;
233241
}
234242
}
235-
if (nonConstEnums && outputFileType != TypeScriptFileType.implementationFile) {
243+
if ((nonConstEnums || !nonConstEnumAnnotations.isEmpty()) && outputFileType != TypeScriptFileType.implementationFile) {
236244
throw new RuntimeException("Non-const enums can only be used in implementation files but 'outputFileType' parameter is not set to 'implementationFile'.");
237245
}
238246
if (mapClasses == ClassMapping.asClasses && outputFileType != TypeScriptFileType.implementationFile) {

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/compiler/ModelCompiler.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ private <T> TsBeanModel processBean(SymbolTable symbolTable, Model model, Map<Ty
176176
extendsList.add(parentType);
177177
}
178178
}
179-
179+
180180
final List<TsType> interfaces = new ArrayList<>();
181181
for (Type aInterface : bean.getInterfaces()) {
182182
final TsType interfaceType = typeFromJava(symbolTable, aInterface);
@@ -189,7 +189,7 @@ private <T> TsBeanModel processBean(SymbolTable symbolTable, Model model, Map<Ty
189189
} else {
190190
extendsList.addAll(interfaces);
191191
}
192-
192+
193193
final List<TsPropertyModel> properties = processProperties(symbolTable, model, bean, "", "");
194194

195195
if (bean.getDiscriminantProperty() != null && !containsProperty(properties, bean.getDiscriminantProperty())) {
@@ -297,7 +297,21 @@ private TsPropertyModel processProperty(SymbolTable symbolTable, BeanModel bean,
297297

298298
private TsEnumModel processEnum(SymbolTable symbolTable, EnumModel enumModel) {
299299
final Symbol beanIdentifier = symbolTable.getSymbol(enumModel.getOrigin());
300-
return TsEnumModel.fromEnumModel(beanIdentifier, enumModel);
300+
TsEnumModel tsEnumModel = TsEnumModel.fromEnumModel(beanIdentifier, enumModel, isEnumNonConst(enumModel));
301+
return tsEnumModel;
302+
}
303+
304+
private boolean isEnumNonConst(EnumModel enumModel) {
305+
boolean isNonConst = settings.nonConstEnums;
306+
if (!isNonConst) {
307+
for (Class<? extends Annotation> nonConstAnnotation : settings.nonConstEnumAnnotations) {
308+
if (enumModel.getOrigin().isAnnotationPresent(nonConstAnnotation)) {
309+
isNonConst = true;
310+
break;
311+
}
312+
}
313+
}
314+
return isNonConst;
301315
}
302316

303317
private TsType typeFromJava(SymbolTable symbolTable, Type javaType) {
@@ -342,13 +356,13 @@ private TsModel addImplementedProperties(SymbolTable symbolTable, TsModel tsMode
342356
for (TsBeanModel bean : tsModel.getBeans()) {
343357
if (bean.isClass()) {
344358
final List<TsPropertyModel> resultProperties = new ArrayList<>(bean.getProperties());
345-
359+
346360
final Set<String> classPropertyNames = new LinkedHashSet<>();
347361
for (TsPropertyModel property : bean.getProperties()) {
348362
classPropertyNames.add(property.getName());
349363
}
350364
classPropertyNames.addAll(getInheritedProperties(symbolTable, tsModel, bean.getExtendsList()).keySet());
351-
365+
352366
final List<TsPropertyModel> implementedProperties = getImplementedProperties(symbolTable, tsModel, bean.getImplementsList());
353367
Collections.reverse(implementedProperties);
354368
for (TsPropertyModel implementedProperty : implementedProperties) {
@@ -357,7 +371,7 @@ private TsModel addImplementedProperties(SymbolTable symbolTable, TsModel tsMode
357371
classPropertyNames.add(implementedProperty.getName());
358372
}
359373
}
360-
374+
361375
beans.add(bean.withProperties(resultProperties));
362376
} else {
363377
beans.add(bean);
@@ -622,7 +636,7 @@ public TsType transform(TsType.Context context, TsType type) {
622636
}
623637
}
624638
return type;
625-
639+
626640
}
627641
});
628642
return model.withTypeAliases(new ArrayList<>(typeAliases));

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/emitter/Emitter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ private void emitLiteralEnum(TsEnumModel enumModel, boolean exportKeyword, boole
365365
writeNewLine();
366366
emitComments(enumModel.getComments());
367367
final String declareText = declareKeyword ? "declare " : "";
368-
final String constText = settings.nonConstEnums ? "" : "const ";
368+
final String constText = enumModel.isNonConstEnum() ? "" : "const ";
369369
writeIndentedLine(exportKeyword, declareText + constText + "enum " + enumModel.getName().getSimpleName() + " {");
370370
indent++;
371371
for (EnumMemberModel member : enumModel.getMembers()) {

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/emitter/TsEnumModel.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,22 @@ public class TsEnumModel extends TsDeclarationModel {
1212

1313
private final EnumKind kind;
1414
private final List<EnumMemberModel> members;
15+
private final boolean isNonConstEnum;
1516

17+
@Deprecated
1618
public TsEnumModel(Class<?> origin, Symbol name, EnumKind kind, List<EnumMemberModel> members, List<String> comments) {
19+
this(origin, name, kind, members, comments, false);
20+
}
21+
22+
public TsEnumModel(Class<?> origin, Symbol name, EnumKind kind, List<EnumMemberModel> members, List<String> comments, boolean isNonConstEnum) {
1723
super(origin, null, name, comments);
1824
this.kind = kind;
1925
this.members = members;
26+
this.isNonConstEnum = isNonConstEnum;
2027
}
2128

22-
public static TsEnumModel fromEnumModel(Symbol name, EnumModel enumModel) {
23-
return new TsEnumModel(enumModel.getOrigin(), name, enumModel.getKind(), enumModel.getMembers(), enumModel.getComments());
29+
public static TsEnumModel fromEnumModel(Symbol name, EnumModel enumModel, boolean isNonConstEnum) {
30+
return new TsEnumModel(enumModel.getOrigin(), name, enumModel.getKind(), enumModel.getMembers(), enumModel.getComments(), isNonConstEnum);
2431
}
2532

2633
public EnumKind getKind() {
@@ -31,8 +38,13 @@ public List<EnumMemberModel> getMembers() {
3138
return members;
3239
}
3340

41+
public boolean isNonConstEnum() {
42+
return isNonConstEnum;
43+
}
44+
3445
public TsEnumModel withMembers(List<EnumMemberModel> members) {
35-
return new TsEnumModel(origin, name, kind, members, comments);
46+
TsEnumModel model = new TsEnumModel(origin, name, kind, members, comments, isNonConstEnum);
47+
return model;
3648
}
3749

3850
}

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/ext/ClassEnumExtension.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ public TsModel transformModel(SymbolTable symbolTable, TsModel model) {
5959
tsBeanModel.getName(),
6060
EnumKind.StringBased,
6161
members,
62-
null
62+
null,
63+
false
6364
);
6465
stringEnums.add(temp);
6566
}

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
import cz.habarta.typescript.generator.parser.Model;
99
import cz.habarta.typescript.generator.parser.ModelParser;
1010
import java.io.File;
11+
import java.lang.annotation.ElementType;
12+
import java.lang.annotation.Retention;
13+
import java.lang.annotation.RetentionPolicy;
14+
import java.lang.annotation.Target;
1115
import java.util.Arrays;
1216
import org.junit.Assert;
1317
import org.junit.Test;
@@ -54,6 +58,20 @@ public void testNonConstEnum() {
5458
output.trim());
5559
}
5660

61+
@Test
62+
public void testNonConstAnnotationEnum() {
63+
final Settings settings = TestUtils.settings();
64+
settings.outputFileType = TypeScriptFileType.implementationFile;
65+
settings.nonConstEnumAnnotations.add(SomeNonConstAnnotation.class);
66+
final String output = new TypeScriptGenerator(settings).generateTypeScript(Input.from(SomeCode.class));
67+
Assert.assertEquals(
68+
"enum SomeCode {\n" +
69+
" VALUE0 = 10,\n" +
70+
" VALUE1 = 11,\n" +
71+
"}",
72+
output.trim());
73+
}
74+
5775
@Test
5876
public void testJavadoc() {
5977
final Settings settings = TestUtils.settings();
@@ -68,6 +86,7 @@ public void testJavadoc() {
6886
* Documentation for SomeCode enum.
6987
*/
7088
@JsonFormat(shape = JsonFormat.Shape.NUMBER_INT)
89+
@SomeNonConstAnnotation
7190
public static enum SomeCode {
7291

7392
/**
@@ -91,4 +110,9 @@ public Integer getJsonValue() {
91110
}
92111
}
93112

113+
@Retention(RetentionPolicy.RUNTIME)
114+
@Target({ElementType.TYPE})
115+
public @interface SomeNonConstAnnotation {
116+
}
117+
94118
}

typescript-generator-gradle-plugin/src/main/java/cz/habarta/typescript/generator/gradle/GenerateTask.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public class GenerateTask extends DefaultTask {
4545
public DateMapping mapDate;
4646
public EnumMapping mapEnum;
4747
public boolean nonConstEnums;
48+
public List<String> nonConstEnumAnnotations;
4849
public ClassMapping mapClasses;
4950
public List<String> mapClassesAsClassesPatterns;
5051
public boolean disableTaggedUnions;
@@ -133,6 +134,7 @@ public void generate() throws Exception {
133134
settings.mapDate = mapDate;
134135
settings.mapEnum = mapEnum;
135136
settings.nonConstEnums = nonConstEnums;
137+
settings.nonConstEnumAnnotations = Settings.loadAnnotations(classLoader, nonConstEnumAnnotations);
136138
settings.mapClasses = mapClasses;
137139
settings.mapClassesAsClassesPatterns = mapClassesAsClassesPatterns;
138140
settings.disableTaggedUnions = disableTaggedUnions;

typescript-generator-maven-plugin/src/main/java/cz/habarta/typescript/generator/maven/GenerateMojo.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,15 @@ public class GenerateMojo extends AbstractMojo {
293293
@Parameter
294294
private boolean nonConstEnums;
295295

296+
/**
297+
* If this list is not empty, then generated enums will not have <code>const</code> keyword,
298+
* if the enum contains one of the annotations defined in this list.
299+
* See {@link #nonConstEnums}
300+
*
301+
*/
302+
@Parameter
303+
private List<String> nonConstEnumAnnotations;
304+
296305
/**
297306
* Specifies whether Java classes will be mapped to TypeScript classes or interfaces.
298307
* Java interfaces are always mapped as TypeScript interfaces.
@@ -596,6 +605,7 @@ public void execute() {
596605
settings.mapDate = mapDate;
597606
settings.mapEnum = mapEnum;
598607
settings.nonConstEnums = nonConstEnums;
608+
settings.nonConstEnumAnnotations = Settings.loadAnnotations(classLoader, nonConstEnumAnnotations);
599609
settings.mapClasses = mapClasses;
600610
settings.mapClassesAsClassesPatterns = mapClassesAsClassesPatterns;
601611
settings.disableTaggedUnions = disableTaggedUnions;

0 commit comments

Comments
 (0)