Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace static imports with non-static imports #1379

Open
szpigielm opened this issue Oct 19, 2022 · 8 comments
Open

Replace static imports with non-static imports #1379

szpigielm opened this issue Oct 19, 2022 · 8 comments

Comments

@szpigielm
Copy link

Hi is it possible to setup spotless to replace static imports with non-static imports in Java?

Example:

Static import:

import static org.enums.Value.SOME_ENUM_VALUE;

public class Test {
    public void method() {
        var example = SOME_ENUM_VALUE;
    }
}

Replace with

import org.enums.Value.SOME_ENUM_VALUE;

public class Test {
    public void method() {
        var example = Value.SOME_ENUM_VALUE;
    }
}
@nedtwigg nedtwigg changed the title How to replace static imports with non-static imports? Reeplace static imports with non-static imports Oct 19, 2022
@nedtwigg
Copy link
Member

This is not possible right now, but we'd be happy to merge a PR which added support for this.

@nedtwigg nedtwigg changed the title Reeplace static imports with non-static imports Replace static imports with non-static imports Oct 19, 2022
@Chasson1992
Copy link

@szpigielm I was going to implement this since I would be intersted in using this as well.

I was going to add to the Java extension a function called replaceStaticImports to enable this formatting.

spotless {
  java {
    replaceStaticImports()
  }
}

The basic case is straight forward.

Instead of

import static org.junit.jupiter.api.Assertions.assertTrue;
...
    assertTrue(true)
...

Replace with

import org.junit.jupiter.api.Assertions;
...
    Assertions.assertTrue(true)
...

The more complicated case would be with wildcard imports, in order for that to work we would need access to the compilation classpath which is beyond the scope of most formatters.

Any suggestions on how to handle the wildcard static imports?

@nedtwigg
Copy link
Member

nedtwigg commented Dec 30, 2022

In this place

protected void setupTask(SpotlessTask task) {
if (target == null) {
JavaPluginConvention javaPlugin = getProject().getConvention().findPlugin(JavaPluginConvention.class);
if (javaPlugin == null) {
throw new GradleException("You must either specify 'target' manually or apply the 'java' plugin.");
}
FileCollection union = getProject().files();
for (SourceSet sourceSet : javaPlugin.getSourceSets()) {
union = union.plus(sourceSet.getAllJava());
}
target = union;
}
steps.replaceAll(step -> {
if (isLicenseHeaderStep(step)) {
return step.filterByFile(LicenseHeaderStep.unsupportedJvmFilesFilter());
} else {
return step;
}
});

You have:

  • the java plugin
  • you can replace a StaticImportStep that doesn't have the classpath with a new StaticImportStep which does have the classpath

so that should be everything you need. I'm not sure how to make it work with maven, but it's fine to have features which only work for one plugin or another.

@agreedSkiing
Copy link

Would this be possible to do in the maven plugin if the dependecy for org.eclipse.jdt.ls.core is included since it has a helper method that does this? https://github.com/eclipse/eclipse.jdt.ls/blob/master/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/cleanup/StaticAccessUsesClassNameCleanUp.java

It atleast works in VSCode when having the qualifyStaticMembers identifier set in the redhat.java VSCode plugin

import static org.junit.jupiter.api.Assertions.*;

public class Test { 
@Test
  public void fake_test() {
    assertTrue(true);
    assertFalse(true);
  }
}

to

import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Assertions;

public class Test { 
@Test
  public void fake_test() {
    Assertions.assertTrue(true);
    Assertions.assertFalse(true);
  }
}

@agreedSkiing
Copy link

@nedtwigg
Copy link
Member

Would this be possible to do in the maven plugin

It's definitely possible. The trouble is that currently Spotless provides only source code to the formatters. It does not provide compiled jars or the classpath.

Normally people can add a FormatterStep to Spotless and making it work in the build plugins is very little work. In this case, the classpath will have to piped from the build plugin to the FormatterStep, which we have never done before. I know how to do that in the Gradle plugin (shown above), and it can certainly be done in Maven, I just don't know how.

Once someone has done it once, we'll be able to standardize it and make it easier to make other classpath-dependent steps in the future.

@Chasson1992
Copy link

I have the classpath access working with Gradle, I just need to implement the FormatterStep logic. Grad school classes started again so I'm a little crunched for time.

Like Ned, I don't have any experience with the Maven API but I have a lot of experience with the Gradle API. If there's someone that knows how to get the classpath in Maven, I'd certainly add that to the PR.

@nedtwigg
Copy link
Member

Amazing @Chasson1992, thanks for getting something going! Don't worry about the Maven stuff at all, that should be a separate PR. From our root README.md Why are there empty squares?

image

Many projects get harder to work on as they get bigger. Spotless is easier to work on than ever, and one of the reasons why is that we don't require contributors to "fill the matrix". ... Once someone has filled in one square of the formatter/build system matrix, it's easy for interested parties to fill in any empty squares, since you'll now have a working example for every piece needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants