Skip to content

Add formatter step to shorten unnecessary fully qualified class names #2945

@adwsingh

Description

@adwsingh

Motivation

LLM-generated Java code is showing up more often, and one pattern I keep seeing is fully qualified class names used inline even when normal imports would be cleaner.

The code compiles, but the file becomes noisy.

For example:

package com.example.service;

public class UserService {
    private final java.util.Map<String, java.util.List<String>> cache = new java.util.HashMap<>();

    public java.util.List<String> getUsers(java.util.function.Predicate<String> filter) throws java.io.IOException {
        java.util.List<String> result = new java.util.ArrayList<>();
        return java.util.Collections.unmodifiableList(result);
    }
}

Running Spotless today leaves this unchanged.

Proposed behavior

Add an optional Java formatter step that rewrites safe fully qualified type references to simple names and adds the required imports.

For example:

package com.example.service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

public class UserService {
    private final Map<String, List<String>> cache = new HashMap<>();

    public List<String> getUsers(Predicate<String> filter) throws IOException {
        List<String> result = new ArrayList<>();
        return Collections.unmodifiableList(result);
    }
}

This step can run before Spotless' existing removeUnusedImports() and importOrder() steps. The normal Spotless pipeline can then clean up and order the final imports.

Safety / constraints

Only rewrite references when the change is clearly safe and semantics-preserving.

Avoid rewriting when:

  • the simple name conflicts with another import, top-level type, nested type, or type in the same package
  • the fully qualified name appears in a string, comment, annotation value, reflective lookup, or other non-type context
  • the reference is part of static member access where shortening the qualifier changes meaning
  • the formatter cannot confidently determine that the qualified name is a type

The scope should stay limited to mechanical cleanup of type references.

Why this belongs in Spotless

This fits well with import cleanup. The code remains equivalent, and the formatted output becomes closer to idiomatic Java.

Spotless already removes unused imports and orders imports. This step would handle the matching cleanup in the other direction: introduce imports when a fully qualified type name is used inline for no real benefit.

This is useful in CI and pre-commit flows where IDE cleanup actions are not always available or consistently configured.

I am happy to create a PR if this feature sounds acceptable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions