Skip to content

Spotless with Eclipse Import Order has different ordering than Eclipse Formatter #522

Description

@thespags

If you are submitting a bug, please include the following:

  • summary of problem
    Spotless with eclipse formatter orders static imports differently than eclipse or eclipse plugin in Intellij
  • gradle or maven version
    mvn 3.3.3
  • spotless version
    1.27.0
  • operating system and version
    Description: Ubuntu 16.04.6 LTS
  • copy-paste your full Spotless configuration block(s), and a link to a public git repo that reproduces the problem if possible
                   <java>
                       <importOrder>
                           <file>/style/myTeam.importorder</file>
                       </importOrder>
                   </java>
               </configuration>

with order

#Organize Import Order
#Fri Jun 28 15:00:43 PDT 2019
4=com.myTeam
3=java
2=javax
1=
0=\#
  • copy-paste the full content of any console errors emitted by gradlew spotless[Apply/Check] --stacktrace
    N/A

If you're just submitting a feature request or question, no need for the above.

EclipseFormatter issues
krasa/EclipseCodeFormatter#200
krasa/EclipseCodeFormatter#105

Write

package somePackage;

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

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;
        m(); // call m with a static import
    }

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

    public enum SomeEnum {
        Bar
    }

    // Add Z this should be sorted after SomeEnum
    public static class SomeZClass {
        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;

Spotless using Eclipse format rules should have the same behavior as Eclipse

Activity

  1. nedtwigg commented on Feb 6, 2020

    @nedtwigg
    Member

    Thanks for another example. Related: #167, #174

  2. thespags commented on Feb 6, 2020

    @thespags
    Author

    Sorry I forgot to look up relevant issues, would you like me to dupe this issue out?

  3. nedtwigg commented on Feb 7, 2020

    @nedtwigg
    Member

    I think your issue adds helpful new information. Looks like krasa/EclipseCodeFormatter#105 fixed part of this problem (so they are closer to a fix than we are), and krasa/EclipseCodeFormatter#200 fixes the rest of it. If someone ever gets around to a PR for one of these import sorter issues, I'd like to resolve all of them, to minimize back-compat issues.

    What I mean by back-compat is that it's important for Spotless users to have the option to freeze their formatting. Fixing this bug will change the order of imports in existing code. So it's important to have something like <importOrder><mode>legacy</mode>... for people who don't want to choose between "reorder all your imports" and "get new bugfixes and features". If we fix these bugs all at once, then there's just two modes, but if we fix them bit by bit it gets more complicated.

  4. ekropotin commented on Apr 24, 2020

    @ekropotin

    Hello. I have another case of inconsistent import order handling which is not related neither upper case packages(EclipseCodeFormatter#105) nor static imports(EclipseCodeFormatter#200). Do I need to file a new issue against it or it's ok to provide details here?

  5. nedtwigg commented on Apr 24, 2020

    @nedtwigg
    Member

    Is the problem that it's different than eclipse? If so this issue is a good place for it. Otherwise a new issue is better.

  6. ekropotin commented on Apr 24, 2020

    @ekropotin

    @nedtwigg yes it is.
    So, in a nutshell the problem is that Spotless tries to arrange imports of packages that are not specified in "importorder" config in alphabetical order with respect to other imports. Eclipse Code Fromatter, in turn, places such imports at the end of the imports block.
    Below is an example:
    build.gradle:

    plugins {
        // Language plugins
        id 'java'
        id "com.diffplug.gradle.spotless" version "3.28.1"
    }
    
    repositories {
        maven { url "https://plugins.gradle.org/m2/" }
        mavenCentral()
        jcenter()
    }
    
    dependencies {
        implementation 'io.opencensus:opencensus-api:0.26.0'
    }
    
    spotless {
        java {
            importOrderFile 'Test.importorder'
            eclipse().configFile 'CodeStyle.xml'
        }
    }
    

    Test.importorder:

    5=org
    4=com
    0=com.test
    

    The file pre-formatted with ECF with Test.importorder:

    package com.test;
    
    import com.test.foo.Bar;
    
    import org.xml.sax.SAXException;
    
    import io.grpc.Deadline;
    
    public class Example {
    
        public void test() throws SAXException {
            Deadline.getSystemTicker();
            throw new SAXException(Bar.BAR);
        }
    }
    

    Output of gradle spotlessCheck:

    > Task :spotlessJava FAILED
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':spotlessJava'.
    > The following files had format violations:
          src/main/java/com/test/Example.java
              @@ -2,10 +2,10 @@
    
               import·com.test.foo.Bar;
    
              +import·io.grpc.Deadline;
              +
               import·org.xml.sax.SAXException;
    
              -import·io.grpc.Deadline;
              -
               public·class·Example·{
    
               ····public·void·test()·throws·SAXException·{
      Run 'gradlew spotlessApply' to fix these violations.
    
  7. ekropotin commented on Jun 24, 2020

    @ekropotin

    @nedtwigg any update on this issue?

  8. nedtwigg commented on Jun 25, 2020

    @nedtwigg
    Member

    I have no personal plans to work on any of the importsorter issues. I don't care what the order is, I just care that something enforces it. I agree it's a bug, and I'm happy to merge a solution from anyone.

  9. cimi commented on Jul 21, 2020

    @cimi

    So, in a nutshell the problem is that Spotless tries to arrange imports of packages that are not specified in "importorder" config in alphabetical order with respect to other imports. Eclipse Code Fromatter, in turn, places such imports at the end of the imports block.

    @ekropotin we can work around this issue by adding an additional item to the .importorder file that forces unspecified imports to go at the end, for example:

    #Organize Import Order
    #Mon Apr 15 23:51:55 CEST 2019
    0=java
    1=javax
    2=org
    3=com
    4=
    

    This makes spotless formatting consistent with IDEA/Eclipse code formatter, so I'm able to use save actions with reformat on save without causing any conflicts.

  10. ekropotin commented on Jul 22, 2020

    @ekropotin

    @cimi This works like a charm! Thanks. You made my day!

  11. bwRavencl commented on Jul 22, 2020

    @bwRavencl

    So, in a nutshell the problem is that Spotless tries to arrange imports of packages that are not specified in "importorder" config in alphabetical order with respect to other imports. Eclipse Code Fromatter, in turn, places such imports at the end of the imports block.

    @ekropotin we can work around this issue by adding an additional item to the .importorder file that forces unspecified imports to go at the end, for example:

    #Organize Import Order
    #Mon Apr 15 23:51:55 CEST 2019
    0=java
    1=javax
    2=org
    3=com
    4=
    

    This makes spotless formatting consistent with IDEA/Eclipse code formatter, so I'm able to use save actions with reformat on save without causing any conflicts.

    Good advice, however unfortunately this still doesn't seem fix the issue entirely in some cases:

    Eclipse:

    import com.sun.jna.platform.win32.Guid.CLSID;
    import com.sun.jna.platform.win32.Guid.GUID;
    import com.sun.jna.platform.win32.Guid.IID;
    import com.sun.jna.platform.win32.Ole32;
    import com.sun.jna.platform.win32.Variant;
    import com.sun.jna.platform.win32.WinDef.BOOLByReference;
    import com.sun.jna.platform.win32.WinDef.DWORD;
    import com.sun.jna.platform.win32.WinDef.UINT;
    import com.sun.jna.platform.win32.WinDef.UINTByReference;
    import com.sun.jna.platform.win32.WinNT.HRESULT;
    import com.sun.jna.platform.win32.COM.Unknown;
    

    Spotless:

    import com.sun.jna.platform.win32.COM.Unknown;
    import com.sun.jna.platform.win32.Guid.CLSID;
    import com.sun.jna.platform.win32.Guid.GUID;
    import com.sun.jna.platform.win32.Guid.IID;
    import com.sun.jna.platform.win32.Ole32;
    import com.sun.jna.platform.win32.Variant;
    import com.sun.jna.platform.win32.WinDef.BOOLByReference;
    import com.sun.jna.platform.win32.WinDef.DWORD;
    import com.sun.jna.platform.win32.WinDef.UINT;
    import com.sun.jna.platform.win32.WinDef.UINTByReference;
    import com.sun.jna.platform.win32.WinNT.HRESULT;
    

    Eclipse seems to order segments consisting entirely of uppercase letters below segments with mixed case, regardless of the characters.

  12. 16 remaining items

  13. added a commit that references this issue on May 22, 2023
    8d4f402
  14. jhonnen commented on May 23, 2023

    @jhonnen
    Contributor

    I just tried this change (thanks!) and found a few differences compared to the eclipse formatter:

    1. fields first or last? checked again, this is just a side-effect of the case-sensitive sorting, lower case fields are not sorted first
      eclipse:

      import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
      import static org.mockito.Mockito.mock;
      import static org.mockito.Mockito.when;
      

      spotless:

      import static org.mockito.Mockito.mock;
      import static org.mockito.Mockito.when;
      import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
      
    2. members case-sensitive?
      eclipse:

      import static pkg.SomeClass.WARMUP_TIME_MSEC;
      import static pkg.SomeClass.ignoreCaseStrategy;
      

      spotless:

      import static pkg.SomeClass.ignoreCaseStrategy;
      import static pkg.SomeClass.WARMUP_TIME_MSEC;
      

    Can you tell which of these differences are expected behavior?

  15. Frettman commented on May 23, 2023

    @Frettman
    Contributor

    @jhonnen, you definitely found a bug that explains both differences. Within each group (package, class, member) sorting should only be using the natural/lexicographical order for strings, which means upper case before lower case. Just to be clear, it was my intention that Spotless produces the same order as Eclipse here (which seems straight forward enough to be used as a general mode and not just e.g. an Eclipse-compatibility mode).

    @nedtwigg Should I create a new PR for the fix?

  16. nedtwigg commented on May 23, 2023

    @nedtwigg
    Member

    Yes, I'd be happy to merge a PR to fix these issues. In this unique case don't add a changelog entry since we haven't released the original yet.

  17. added 2 commits that reference this issue on May 23, 2023
    d8746a6
    a8a94c0
  18. nedtwigg commented on May 24, 2023

    @nedtwigg
    Member

    Fixed in plugin-gradle 6.19.0 and plugin-maven 2.37.0 thanks to @Frettman.

  19. added a commit that references this issue on May 30, 2023
  20. added a commit that references this issue on Jul 21, 2023
  21. added a commit that references this issue on Jul 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions