Skip to content

Commit

Permalink
feat: Generate enum with no keys for large properties files
Browse files Browse the repository at this point in the history
Use EnumType#NO_KEYS in @L10nProperties to generate an enum with no keys.

This can be used to work with large properties files that generate the following compilation
error: "error: code too large" when the enum becomes too large with {@link #KEYS_ONLY} due
the number of keys.

Obviously strong typing does not apply anymore but other enum attribute can be used for
example to create an instance of L10nMessages with {@link L10nMessages#builder(Class)}
  • Loading branch information
aurambaj committed Jan 12, 2024
1 parent 08073bb commit e9d8902
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ public static String toEnum(

String enumValues =
deduplicatedWithReporting.keySet().stream()
.map(key -> String.format(" %s(\"%s\")", toJavaIdentifier.convert(key), key))
.collect(Collectors.joining(",\n"));
.map(key -> String.format(" %s(\"%s\")", toJavaIdentifier.convert(key), key))
.collect(Collectors.joining(",\n"))
+ ";";

String packageString =
nameParts.getDotPackageName().isEmpty()
Expand All @@ -67,32 +68,42 @@ public static String toEnum(
+ "\n"
+ "@Generated(\"%4$s\")\n"
+ "public enum %5$s {\n"
+ "%6$s;\n"
+ "%6$s\n"
+ "\n"
+ " public static final String BASENAME = \"%7$s\";\n"
+ " public static final String MESSAGE_FORMAT_ADAPTER_PROVIDERS = \"%8$s\";\n"
+ "\n"
+ " private String key;\n"
+ "\n"
+ " %5$s(String key) {\n"
+ " this.key = key;\n"
+ " }\n"
+ "\n"
+ " @Override\n"
+ " public String toString() {\n"
+ " return key;\n"
+ " }\n"
+ "%9$s"
+ "%10$s"
+ "}\n",
packageString, // 1
enumType.WITH_ARGUMENT_BUILDERS.equals(enumType) ? IMPORT_STATEMENT_FOR_ARGUMENTS : "", // 2
IMPORT_GENERATED_ANNOTATION, // 3
generatedAnnotationValue, // 4
nameParts.getEnumName(), // 5
enumValues, // 6
enumType.NO_KEYS.equals(enumType) ? " ;" : enumValues, // 6
nameParts.getBaseName(), // 7
messageFormatAdapterProviders, // 8
enumType.WITH_ARGUMENT_BUILDERS.equals(enumType) ? formatContexts + "\n" : ""); // 9
enumType.NO_KEYS.equals(enumType) ? "" : generateConstructorBlock(nameParts.getEnumName()),
// 9
enumType.WITH_ARGUMENT_BUILDERS.equals(enumType) ? formatContexts + "\n" : "" // 10
);
}

private static String generateConstructorBlock(String enumName) {
return String.format(
""
+ " private String key;\n"
+ "\n"
+ " %1$s(String key) {\n"
+ " this.key = key;\n"
+ " }\n"
+ "\n"
+ " @Override\n"
+ " public String toString() {\n"
+ " return key;\n"
+ " }\n",
enumName);
}

private static String generateFormatContextForEntry(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,41 @@ void toEnum() {
+ "}\n",
enumString);
}

@Test
void toEnumWithNoKeys() {
String baseName = "com.pinterest.l10nmessages.Messages";
NameParts nameParts = NameParts.fromBaseName(baseName);

LinkedHashMap<String, String> entries =
(LinkedHashMap<String, String>)
Maps.of(
"hello_username", "Hello {userName}, {count}",
"bye", "Bye");

String enumString =
L10nPropertiesEnumGenerator.toEnum(
entries,
nameParts,
ToJavaIdentifiers.ESCAPING_AND_UNDERSCORE,
MessageFormatAdapterProviders.JDK_NAMED_ARGS,
L10nPropertiesProcessor.class.getName(),
EnumType.NO_KEYS);

assertThat(enumString)
.isEqualTo(
"package com.pinterest.l10nmessages;\n"
+ "\n"
+ L10nPropertiesEnumGenerator.IMPORT_GENERATED_ANNOTATION
+ "\n"
+ "@Generated(\"com.pinterest.l10nmessages.L10nPropertiesProcessor\")\n"
+ "public enum Messages {\n"
+ " ;\n"
+ "\n"
+ " public static final String BASENAME = \"com.pinterest.l10nmessages.Messages\";\n"
+ " public static final String MESSAGE_FORMAT_ADAPTER_PROVIDERS = \"JDK_NAMED_ARGS\";\n"
+ "\n"
+ "}\n",
enumString);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ public void validArgumentBuilder() {
checkGenerationSuccessful(compilation);
}

@Test
public void validNoKey() {
assumeTrue(shouldUseOldGeneratedAnnotation());
Compilation compilation = defaultCompile();
checkGenerationSuccessful(compilation);
}

@Test
public void validJava9() {
assumeFalse(shouldUseOldGeneratedAnnotation());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.pinterest.l10nmessages.L10nPropertiesProcessorTest_IO.valid;

import com.pinterest.l10nmessages.EnumType;
import com.pinterest.l10nmessages.L10nProperties;

@L10nProperties(baseName = "com.pinterest.l10nmessages.L10nPropertiesProcessorTest_IO.validNoKey.TestMessages",
enumType = EnumType.NO_KEYS)
public class TestApp {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.pinterest.l10nmessages.L10nPropertiesProcessorTest_IO.validNoKey;

import javax.annotation.Generated;

@Generated("com.pinterest.l10nmessages.L10nPropertiesProcessor")
public enum TestMessages {
;

public static final String BASENAME = "com.pinterest.l10nmessages.L10nPropertiesProcessorTest_IO.validNoKey.TestMessages";
public static final String MESSAGE_FORMAT_ADAPTER_PROVIDERS = "AUTO";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello_user=Hello {username}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
*
* <p>{@link #WITH_ARGUMENT_BUILDERS} provide stronger typing but requires one class to be generated
* by message with arguments. If this not acceptable, use {@link #KEYS_ONLY} (default value).
*
* <p>For large files with messages that are not referenced explicitly by key in code it is possible
* to generate the enum with no keys {@link #NO_KEYS}. The enum can still be used to create the
* L10nMessages instance but obviously there no type checking anymore.
*/
public enum EnumType {
/**
Expand All @@ -28,5 +32,17 @@ public enum EnumType {
*
* <p>Typically used with {@link com.pinterest.l10nmessages.L10nMessages#format(FormatContext)}
*/
WITH_ARGUMENT_BUILDERS
WITH_ARGUMENT_BUILDERS,
/**
* Generates an enum with no keys.
*
* <p>This can be used to work with large properties files that generate the following compilation
* error: "error: code too large" when the enum becomes too large with {@link #KEYS_ONLY}.
*
* <p>Obviously strong typing does not apply anymore but other enum attribute can be used for
* example to create an instance of L10nMessages with {@link L10nMessages#builder(Class)}
*
* <p>Typically used with {@link com.pinterest.l10nmessages.L10nMessages#format(Object)}
*/
NO_KEYS,
}

0 comments on commit e9d8902

Please sign in to comment.