Skip to content

idempotence problem in import sorter - fixable by paddedCell() #174

Description

@jbduncan

Problem

When building Spotless with ./gradlew spotlessCheck on Windows, with the change mentioned in How to reproduce, it throws the error message shown in Actual result.

I suspect it's a bug with the version of the Eclipse Java formatter we're using, because adding paddedCell() to spotlessSelf.gradle, as mentioned in section How to resolve (at least temporarily), resolves the error.

How to reproduce

  1. Clone and download the Spotless sources locally with git.
  2. Change the following file so it has a static import at the end of its imports section, as following:
    testlib/src/main/java/com/diffplug/spotless/ResourceHarness.java
    
    import java.io.File;
    import java.io.IOException;
    import java.net.URL;
    import java.nio.charset.Charset;
    import java.nio.charset.StandardCharsets;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.logging.Logger;
    import java.util.stream.Collectors;
    
    import org.assertj.core.api.AbstractFileAssert;
    import org.assertj.core.api.Assertions;
    import org.junit.Assert;
    import org.junit.ComparisonFailure;
    import org.junit.Rule;
    import org.junit.rules.TemporaryFolder;
    import org.junit.rules.TestWatcher;
    import org.junit.runner.Description;
    
    import com.diffplug.common.io.Resources;
    
    import static org.assertj.core.api.Assertions.assertThat;
    
  3. Run ./gradlew spotlessCheck.

How to resolve (at least temporarily)

Add paddedCell() to the java block of the spotless configuration in spotlessSelf.gradle. For example:

spotlessSelf.gradle
spotless {
  ...
  java {
    ...
    paddedCell()
  }
  ...
}

Environment details

$ ./gradlew --version

------------------------------------------------------------
Gradle 2.14.1
------------------------------------------------------------

Build time:   2016-07-18 06:38:37 UTC
Revision:     d9e2113d9fb05a5caabba61798bdb8dfdca83719

Groovy:       2.4.4
Ant:          Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM:          1.8.0_144 (Oracle Corporation 25.144-b01)
OS:           Windows 7 6.1 amd64

Expected result

Everything should format fine on Windows.

Actual result

:lib:compileJava UP-TO-DATE
:lib:processResources UP-TO-DATE
:lib:classes UP-TO-DATE
:lib:jar UP-TO-DATE
:lib-extra:compileJava UP-TO-DATE
:lib-extra:processResources UP-TO-DATE
:lib-extra:classes UP-TO-DATE
:lib-extra:jar UP-TO-DATE
:plugin-gradle:compileJava UP-TO-DATE
:plugin-gradle:pluginDescriptors UP-TO-DATE
:plugin-gradle:processResources UP-TO-DATE
:plugin-gradle:classes UP-TO-DATE
:plugin-gradle:pluginUnderTestMetadata UP-TO-DATE
:testlib:compileJava
:testlib:processResources UP-TO-DATE
:testlib:classes
:testlib:jar
:plugin-gradle:compileTestJava
:plugin-gradle:processTestResources UP-TO-DATE
:plugin-gradle:testClasses
:plugin-gradle:spotlessCheck
:spotlessFreshmark UP-TO-DATE
:spotlessFreshmarkCheck UP-TO-DATE
:spotlessGroovyGradle UP-TO-DATE
:spotlessGroovyGradleCheck UP-TO-DATE
:spotlessJava FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':spotlessJava'.
> You have a misbehaving rule which can't make up its mind.
This means that spotlessCheck will fail even after spotlessApply has run.

This is a bug in a formatting rule, not Spotless itself, but Spotless can
work around this bug and generate helpful bug reports for the broken rule
if you add 'paddedCell()' to your build.gradle as such: 

    spotless {
        format 'someFormat', {
            ...
            paddedCell()
        }
    }

The next time you run spotlessCheck, it will put helpful bug reports into
'build\spotless-diagnose-java', and spotlessApply
and spotlessCheck will be self-consistent from here on out.

For details see https://github.com/diffplug/spotless/blob/master/PADDEDCELL.md


* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':spotlessJava'.
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
	at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
	at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:66)
	at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
	at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
	at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
	at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66)
	at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:25)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:110)
	at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
	at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
	at org.gradle.execution.DefaultBuildExecuter.access$000(DefaultBuildExecuter.java:23)
	at org.gradle.execution.DefaultBuildExecuter$1.proceed(DefaultBuildExecuter.java:43)
	at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
	at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:37)
	at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:30)
	at org.gradle.initialization.DefaultGradleLauncher$4.run(DefaultGradleLauncher.java:153)
	at org.gradle.internal.Factories$1.create(Factories.java:22)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:53)
	at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:150)
	at org.gradle.initialization.DefaultGradleLauncher.access$200(DefaultGradleLauncher.java:32)
	at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:98)
	at org.gradle.initialization.DefaultGradleLauncher$1.create(DefaultGradleLauncher.java:92)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:63)
	at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:92)
	at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:83)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:99)
	at org.gradle.tooling.internal.provider.runner.BuildModelActionRunner.run(BuildModelActionRunner.java:46)
	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
	at org.gradle.tooling.internal.provider.runner.SubscribableBuildActionRunner.run(SubscribableBuildActionRunner.java:58)
	at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:48)
	at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:30)
	at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:81)
	at org.gradle.launcher.exec.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:46)
	at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:52)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:37)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:26)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:34)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:74)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:72)
	at org.gradle.util.Swapper.swap(Swapper.java:38)
	at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:72)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.health.DaemonHealthTracker.execute(DaemonHealthTracker.java:47)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:72)
	at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:36)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.health.HintGCAfterBuild.execute(HintGCAfterBuild.java:41)
	at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:120)
	at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:50)
	at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:237)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
	at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
Caused by: org.gradle.api.GradleException: You have a misbehaving rule which can't make up its mind.
This means that spotlessCheck will fail even after spotlessApply has run.

This is a bug in a formatting rule, not Spotless itself, but Spotless can
work around this bug and generate helpful bug reports for the broken rule
if you add 'paddedCell()' to your build.gradle as such: 

    spotless {
        format 'someFormat', {
            ...
            paddedCell()
        }
    }

The next time you run spotlessCheck, it will put helpful bug reports into
'build\spotless-diagnose-java', and spotlessApply
and spotlessCheck will be self-consistent from here on out.

For details see https://github.com/diffplug/spotless/blob/master/PADDEDCELL.md

	at com.diffplug.gradle.spotless.PaddedCellGradle.youShouldTurnOnPaddedCell(PaddedCellGradle.java:60)
	at com.diffplug.gradle.spotless.SpotlessTask.check(SpotlessTask.java:273)
	at com.diffplug.gradle.spotless.SpotlessTask.performAction(SpotlessTask.java:205)
	at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
	at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.doExecute(AnnotationProcessingTaskFactory.java:245)
	at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:221)
	at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$IncrementalTaskAction.execute(AnnotationProcessingTaskFactory.java:232)
	at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:210)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
	... 70 more


BUILD FAILED

Total time: 10.47 secs

Activity

  1. nedtwigg commented on Dec 4, 2017

    @nedtwigg
    Member
  2. jbduncan commented on Dec 4, 2017

    @jbduncan
    MemberAuthor

    @nedtwigg When I run ./gradlew spotlessCheck straight after running ./gradlew clean and thoroughly cleaning all build folders, it doesn't seem to produce build\spotless-diagnose-java at all. The most it generates is lib\build\* and lib-extra\build\* subfolders which just contain the usual suspects: classes\, dependency-cache\, libs\ and tmp\.

    Interestingly, cleaning all the build folders and then running ./gradlew spotlessApply runs without problems. It seems that it's just spotlessCheck that has a problem.

  3. jbduncan commented on Dec 4, 2017

    @jbduncan
    MemberAuthor

    I realised just now that I also failed to clean up .gradle\ and .gradle-selfapply\, but it seems that even deleting those beforehand doesn't improve things.

  4. nedtwigg commented on Dec 7, 2017

    @nedtwigg
    Member

    I don't see how paddedCell is inducing this problem. It sounds like it fixes the problem, correct? This seems like just a normal convergence bug in the import sorter, which paddedCell fixes. Decent chance that fixing #167 might fix this... The spotless-diagnose-java folder would help to confirm this, but I guess something about the weird way that we do selfApply is masking it.

  5. jbduncan commented on Dec 7, 2017

    @jbduncan
    MemberAuthor

    I don't see how paddedCell is inducing this problem. It sounds like it fixes the problem, correct?

    Ah yes, you're right, my apologies. I realised when writing the issue title that I was using the wrong word when I wrote "inducing", but I couldn't think of the right word at the time. I think I meant to say "paddedCell()-related" or "solved-at-least-temporarily-by-paddedCell()".

    The spotless-diagnose-java folder would help to confirm this, but I guess something about the weird way that we do selfApply is masking it.

    I believe you're right. We had problems with selfApply in the past, so I wouldn't be surprised if it was to blame for spotless-diagnose-java not showing up at all in my local build directories.

    Decent chance that fixing #167 might fix this...

    Sounds like a way forward to me. I personally won't have the time or inclination in the foreseeable future to tackle #167, but if it does eventually get solved, we can then see if it fixes this issue. :)

  6. changed the title [-]`paddedCell()`-inducing problem with running `spotlessCheck` on Spotless itself on Windows[/-] [+]convergence problem in import sorter - fixable by `paddedCell()`[/+] on Dec 7, 2017
  7. changed the title [-]convergence problem in import sorter - fixable by `paddedCell()`[/-] [+]idempotence problem in import sorter - fixable by `paddedCell()`[/+] on Dec 7, 2017
  8. nedtwigg commented on Apr 22, 2022

    @nedtwigg
    Member

    paddedCell is always enabled now.

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