CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-palantir-javapoet--javapoet

JavaPoet is a Java API for generating .java source files programmatically with support for modern Java features including records and sealed types

Overview
Eval results
Files

name-allocator.mddocs/

Name Allocator

NameAllocator manages unique Java identifiers and helps avoid name collisions when generating code. It automatically suggests unique names by appending numeric suffixes when names conflict, and can convert arbitrary strings into valid Java identifiers.

Capabilities

Creating a NameAllocator

/**
 * Creates a new NameAllocator instance
 */
public NameAllocator();

Usage Example:

NameAllocator allocator = new NameAllocator();

Converting to Valid Identifiers

Convert arbitrary strings to valid Java identifiers.

/**
 * Converts a string to a valid Java identifier
 * @param suggestion - The string to convert
 * @return Valid Java identifier derived from the suggestion
 */
static String toJavaIdentifier(String suggestion);

Usage Examples:

// Convert strings with special characters
String id1 = NameAllocator.toJavaIdentifier("my-variable");  // "my_variable"
String id2 = NameAllocator.toJavaIdentifier("user name");    // "user_name"
String id3 = NameAllocator.toJavaIdentifier("123abc");       // "_123abc"
String id4 = NameAllocator.toJavaIdentifier("class");        // "class_" (reserved word)

Allocating Unique Names

Allocate unique names that won't collide with each other.

/**
 * Allocates a new unique name based on a suggestion
 * @param suggestion - Suggested name
 * @return Unique name (may have numeric suffix if suggestion conflicts)
 */
String newName(String suggestion);

/**
 * Allocates a new unique name with an associated tag
 * @param suggestion - Suggested name
 * @param tag - Object to associate with this name for later retrieval
 * @return Unique name (may have numeric suffix if suggestion conflicts)
 */
String newName(String suggestion, Object tag);

Usage Examples:

NameAllocator allocator = new NameAllocator();

// Simple allocation
String var1 = allocator.newName("value");      // "value"
String var2 = allocator.newName("value");      // "value_" (conflict avoided)
String var3 = allocator.newName("value");      // "value__" (conflict avoided)

// Using tags
String userId = allocator.newName("id", "userId");     // "id"
String productId = allocator.newName("id", "productId"); // "id_"

// Can retrieve by tag later
String retrievedUserId = allocator.get("userId");      // "id"
String retrievedProductId = allocator.get("productId"); // "id_"

Retrieving Allocated Names

Retrieve previously allocated names by their tag.

/**
 * Retrieves a previously allocated name by its tag
 * @param tag - The tag associated with the name
 * @return The allocated name for this tag
 * @throws IllegalArgumentException if tag not found
 */
String get(Object tag);

Usage Example:

NameAllocator allocator = new NameAllocator();

allocator.newName("user", "currentUser");
allocator.newName("user", "activeUser");

String current = allocator.get("currentUser"); // "user"
String active = allocator.get("activeUser");   // "user_"

Cloning NameAllocator

Create a copy of the allocator with its current state.

/**
 * Creates a clone of this NameAllocator
 * @return Cloned NameAllocator with same allocated names
 */
NameAllocator clone();

Usage Example:

NameAllocator original = new NameAllocator();
original.newName("value");
original.newName("count");

NameAllocator copy = original.clone();
String name = copy.newName("value"); // "value_" (knows about original allocation)

Common Patterns

Avoiding Reserved Words

NameAllocator allocator = new NameAllocator();

// Java keywords are automatically avoided
String className = allocator.newName("class");    // "class_"
String ifVar = allocator.newName("if");           // "if_"
String forVar = allocator.newName("for");         // "for_"
String returnVar = allocator.newName("return");   // "return_"

Method Parameter Generation

NameAllocator allocator = new NameAllocator();

// Generate unique parameter names
String param1 = allocator.newName("value");    // "value"
String param2 = allocator.newName("value");    // "value_"
String param3 = allocator.newName("result");   // "result"

MethodSpec method = MethodSpec.methodBuilder("process")
    .addParameter(String.class, param1)
    .addParameter(int.class, param2)
    .addParameter(boolean.class, param3)
    .build();

Field Name Generation

NameAllocator allocator = new NameAllocator();

// Generate unique field names
List<FieldSpec> fields = new ArrayList<>();
for (String name : Arrays.asList("id", "name", "id", "value")) {
    String uniqueName = allocator.newName(name);
    fields.add(FieldSpec.builder(String.class, uniqueName)
        .addModifiers(Modifier.PRIVATE)
        .build());
}
// Results in fields: id, name, id_, value

Variable Name Generation in Code

NameAllocator allocator = new NameAllocator();

CodeBlock.Builder code = CodeBlock.builder();

// Generate unique local variable names
String counter = allocator.newName("i");
String temp = allocator.newName("temp");
String result = allocator.newName("result");

code.addStatement("int $N = 0", counter);
code.beginControlFlow("for (int $N = 0; $N < 10; $N++)", counter, counter, counter);
code.addStatement("$T $N = process($N)", String.class, temp, counter);
code.addStatement("$N.add($N)", result, temp);
code.endControlFlow();

Database Column Mapping

NameAllocator allocator = new NameAllocator();

// Map database columns to Java field names
Map<String, String> columnToField = new HashMap<>();
columnToField.put("user_name", allocator.newName("userName", "user_name"));
columnToField.put("user_id", allocator.newName("userId", "user_id"));
columnToField.put("user-email", allocator.newName("userEmail", "user-email"));

// Generate fields
for (Map.Entry<String, String> entry : columnToField.entrySet()) {
    String fieldName = allocator.get(entry.getValue());
    FieldSpec field = FieldSpec.builder(String.class, fieldName)
        .addModifiers(Modifier.PRIVATE)
        .build();
}

Nested Class Name Generation

NameAllocator allocator = new NameAllocator();

// Ensure unique nested class names
String builderClass = allocator.newName("Builder");
String nodeClass = allocator.newName("Node");
String entryClass = allocator.newName("Entry");

TypeSpec outer = TypeSpec.classBuilder("Container")
    .addType(TypeSpec.classBuilder(builderClass).build())
    .addType(TypeSpec.classBuilder(nodeClass).build())
    .addType(TypeSpec.classBuilder(entryClass).build())
    .build();

Scope Management

// Create allocator for method scope
NameAllocator methodScope = new NameAllocator();

// Add parameter names to scope
methodScope.newName("input", "param1");
methodScope.newName("output", "param2");

// Clone for nested scope (e.g., lambda or anonymous class)
NameAllocator nestedScope = methodScope.clone();

// Add local variables in nested scope
String local = nestedScope.newName("temp");      // "temp"
String local2 = nestedScope.newName("input");    // "input_" (avoids parameter)

Import Alias Generation

NameAllocator allocator = new NameAllocator();

// Generate unique import aliases for classes with same simple name
Map<String, String> imports = new HashMap<>();
imports.put("java.util.Date", allocator.newName("Date", "java.util.Date"));
imports.put("java.sql.Date", allocator.newName("Date", "java.sql.Date"));

String utilDate = allocator.get("java.util.Date");  // "Date"
String sqlDate = allocator.get("java.sql.Date");    // "Date_"

Generated Getter/Setter Names

NameAllocator allocator = new NameAllocator();

String fieldName = "userName";
String getterName = allocator.newName("get" + capitalize(fieldName));
String setterName = allocator.newName("set" + capitalize(fieldName));

MethodSpec getter = MethodSpec.methodBuilder(getterName)
    .addModifiers(Modifier.PUBLIC)
    .returns(String.class)
    .addStatement("return $N", fieldName)
    .build();

MethodSpec setter = MethodSpec.methodBuilder(setterName)
    .addModifiers(Modifier.PUBLIC)
    .addParameter(String.class, fieldName)
    .addStatement("this.$N = $N", fieldName, fieldName)
    .build();

Handling Special Characters

NameAllocator allocator = new NameAllocator();

// Convert database column names with special characters
String id = allocator.newName(NameAllocator.toJavaIdentifier("user-id"));
String email = allocator.newName(NameAllocator.toJavaIdentifier("email_address"));
String created = allocator.newName(NameAllocator.toJavaIdentifier("created at"));

// Results: user_id, email_address, created_at

Code Generation from Templates

NameAllocator allocator = new NameAllocator();

// Generate multiple similar methods
List<String> operations = Arrays.asList("create", "read", "update", "delete");
List<MethodSpec> methods = new ArrayList<>();

for (String op : operations) {
    String methodName = allocator.newName(op + "User");
    methods.add(MethodSpec.methodBuilder(methodName)
        .addModifiers(Modifier.PUBLIC)
        .returns(void.class)
        .build());
}

With Prefixes and Suffixes

NameAllocator allocator = new NameAllocator();

// Generate names with consistent patterns
String field = allocator.newName("m" + "value");    // "mValue"
String getter = allocator.newName("getValue");       // "getValue"
String setter = allocator.newName("setValue");       // "setValue"
String local = allocator.newName("value");           // "value"

Annotation Processing

// In annotation processor
NameAllocator allocator = new NameAllocator();

for (Element element : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
    String fieldName = element.getSimpleName().toString();
    String uniqueName = allocator.newName(fieldName, element);

    // Generate code using unique name
    FieldSpec field = FieldSpec.builder(String.class, uniqueName)
        .addModifiers(Modifier.PRIVATE)
        .build();
}

// Later retrieve by element
Element someElement = ...;
String allocatedName = allocator.get(someElement);

Best Practices

  1. Use tags for retrieval: When you need to retrieve allocated names later, always use the tag variant
  2. Clone for nested scopes: Create clones when entering nested scopes to maintain parent scope awareness
  3. Convert before allocating: Use toJavaIdentifier() for user input or external data before allocation
  4. One allocator per scope: Create separate allocators for different scopes (class-level, method-level, etc.)
  5. Consistent naming: Apply consistent prefixes/suffixes before allocating to maintain code style

Types

class NameAllocator implements Cloneable {
    NameAllocator();

    static String toJavaIdentifier(String suggestion);

    String newName(String suggestion);
    String newName(String suggestion, Object tag);
    String get(Object tag);
    NameAllocator clone();
}

Install with Tessl CLI

npx tessl i tessl/maven-com-palantir-javapoet--javapoet

docs

annotation-specifications.md

array-type-names.md

class-names.md

code-blocks.md

field-specifications.md

index.md

java-files.md

method-specifications.md

name-allocator.md

parameter-specifications.md

parameterized-type-names.md

type-names.md

type-specifications.md

type-variable-names.md

wildcard-type-names.md

tile.json