EclipseCodeFormatter icon indicating copy to clipboard operation
EclipseCodeFormatter copied to clipboard

Plugin + Intellij optimize Import for static imports out of order

Open thespags opened this issue 5 years ago • 14 comments
trafficstars

If the formating is different than expected:

  • make sure you are comparing with the same Eclipse version
  • provide a code example (both from Eclipse and from IntelliJ) and settings files

Define this class,

package somePackage;

import static somePackage.SomeZClass;
import static somePackage.SomeEnum.Bar;

import java.util.function.Supplier;

// Use as a type argument to be a static import.
public class Foo implements Supplier<SomeZClass> {

    public void someMethod() {
        SomeEnum e = Bar;
    }

    @Override
    public SomeZClass get() {
        return null;
    }

    public enum SomeEnum {
        Bar
    }

    // Add Z this should be sorted after SomeEnum
    public static class SomeZClass {

    }
}

What steps will reproduce the issue?

Run optimize import in the IDE.

What is the expected result?

import static somePackage.SomeEnum.Bar;
import static somePackage.SomeZClass;

What happens instead?

import static somePackage.SomeZClass;
import static somePackage.SomeEnum.Bar;

Paste information about IDE and OS (it can be copied from Help | About dialog).

Intellij Version: 193.6015.39 Using Plugin with Eclipse Format: 4.5.1+

Note: mvn spotless:apply uses the expected behavior, and turning off the eclipse formatter plugin then Intellij will optimize the import with the expected behavior.

thespags avatar Feb 03 '20 18:02 thespags

Hmm, spotless uses my old implementation for import sorting. Are you sure you configured it properly? What is your config for import order?

krasa avatar Feb 04 '20 22:02 krasa

My settings are. 4=com.xxx 3=java 2=javax 1= 0=#

My spotless configuration points to my resource/myTeam.importOrder and the plugin points to the same file for import order.

thespags avatar Feb 04 '20 22:02 thespags

I am starting to remember that there is some kind of hack in sorting static imports....

I think this is not supported:

import static somePackage.SomeZClass;

I don't even know what that is, is this some new language feature? Could you post the whole compilable code?

This would work fine:

import static somePackage.SomeZClass.*;

krasa avatar Feb 04 '20 22:02 krasa

Here's what I wrote locally

package somePackage;

import static somePackage.Foo.SomeZClass;
import static somePackage.Foo.SomeEnum.Bar;

import java.util.function.Supplier;

// Use as a type argument to be a static import.
public class Foo implements Supplier<SomeZClass> {

    public void someMethod() {
        SomeEnum e = Bar;
    }

    @Override
    public SomeZClass get() {
        return null;
    }

    public enum SomeEnum {
        Bar
    }

    // Add Z this should be sorted after SomeEnum
    public static class SomeZClass {

    }
}

Sorry I missed the imports including the top level class. It's suppose to be somePackage.Foo.SomeZClass in the example. So I'm doing static imports of SomeZClass for the type argument and Bar.

thespags avatar Feb 04 '20 23:02 thespags

It is probably simplified too much, Eclipse converts it to this:

import static somePackage.Foo.SomeEnum.Bar;

import java.util.function.Supplier;

import somePackage.Foo.SomeZClass;

krasa avatar Feb 04 '20 23:02 krasa

If I do this:

package somePackage;


import static somePackage.Foo.SomeZClass;
import static somePackage.Foo.SomeEnum.Bar;


public class X {
	{
		SomeZClass();	
	}
	
	somePackage.Foo.SomeEnum bar=Bar;
}

then Eclipse 2019-03 and 2019-12 sorts SomeZClass as first.

krasa avatar Feb 04 '20 23:02 krasa

Just to confirm the expected behavior is that we have

import static somePackage.Foo.SomeEnum.Bar;
import static somePackage.Foo.SomeZClass;

?

thespags avatar Feb 04 '20 23:02 thespags

Have you actually tried it in Eclipse? because Eclipse produces:

package somePackage;

import static somePackage.Foo.SomeZClass;
import static somePackage.Foo.SomeEnum.Bar;

public class Bar {
	{
		
		SomeZClass.name();
	}
	
	somePackage.Foo.SomeEnum bar=Bar;
}

package somePackage;

public enum Foo  {
	SomeZClass ;
	
    public enum SomeEnum {
        Bar
    }

}

krasa avatar Feb 04 '20 23:02 krasa

Yes I just ran it in eclipse and see the behavior you mention. But the plugin for Intellij has a different behavior than what is in eclipse. And spotless has a third behavior.

So is your goal to align with the behavior as much in eclipse?

Personally I feel the ordering that spotless does is what I'd expect, but I can understand if you want 1-1 parity with eclipse and I can reach out to spotless' organization.

thespags avatar Feb 05 '20 01:02 thespags

But the plugin for Intellij has a different behavior than what is in eclipse.

where?

So is your goal to align with the behavior as much in eclipse?

yes

krasa avatar Feb 05 '20 07:02 krasa

For clarity the three behaviors I observe from my given import above

import static somePackage.Foo.SomeZClass;
import static somePackage.Foo.SomeEnum.Bar;

import java.util.function.Supplier;

Eclipse running "Organize Import" produces:

import static somePackage.Foo.SomeEnum.Bar;

import java.util.function.Supplier;

import somePackage.Foo.SomeZClass;

Eclipse Plugin for Intellij running "Optimize Import" produces:

import static somePackage.Foo.SomeZClass;
import static somePackage.Foo.SomeEnum.Bar;

import java.util.function.Supplier;

Spotless plugin running "mvn spotless:apply" produces:

import static somePackage.Foo.SomeEnum.Bar;
import static somePackage.Foo.SomeZClass;

import java.util.function.Supplier;

To further show that Eclipse Plugin behavior is not expected we can add


   public void callM() {
       m(); // call m with a static import
   }
    public static class SomeZClass {
        // static method to be imported by Foo
        static void m() {

        }
    }

Eclipse Plugin will order imports:

import static somePackage.Foo.SomeZClass;
import static somePackage.Foo.SomeEnum.Bar;
import static somePackage.Foo.SomeZClass.m;

Eclipse will order imports:

import static somePackage.Foo.SomeEnum.Bar;
import static somePackage.Foo.SomeZClass.m;

import java.util.function.Supplier;

import somePackage.Foo.SomeZClass;

and spotless will order imports


import static somePackage.Foo.SomeEnum.Bar;
import static somePackage.Foo.SomeZClass;
import static somePackage.Foo.SomeZClass.m;

import java.util.function.Supplier;

So I expect the behavior of the Eclipse Plugin to respect alphabetical ordering for static imports, SomeZClass should be imported after SomeEnum.

thespags avatar Feb 05 '20 17:02 thespags

Ok, I see.

The problem is that Intellij does not convert import static somePackage.Foo.SomeZClass; into import somePackage.Foo.SomeZClass; like Eclipse. This plugin only handles the order, not the actual content of imports.

You could workaround it by fixing the import manually or not writing such code in the first place :) Not sure how you ended up with it, my IntelliJ makes public class Foo implements Supplier<somePackage.Foo.SomeZClass> { and has no intention to convert it to an import.

Spotless is missing this fix: https://github.com/krasa/EclipseCodeFormatter/issues/105 so its order is wrong.

krasa avatar Feb 05 '20 17:02 krasa

Thank you for the response.

I statically import SomeZcClass to avoid the FQN in the argument. The other option is if I manually format it like Eclipse than spotless and EclipseFormatter won't change it.

I've filed an issue to Spotless as well to get #105. Is it possible to have the plugin change the contents or is there a limitation that makes this difficult?

thespags avatar Feb 06 '20 18:02 thespags

This plugin could change the imports in the same way IntelliJ does it, using PSI, that should be easy.

krasa avatar Apr 16 '20 22:04 krasa