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

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

Closed
jbduncan opened this issue Dec 4, 2017 · 6 comments
Closed

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

jbduncan opened this issue Dec 4, 2017 · 6 comments

Comments

@jbduncan
Copy link
Member

jbduncan commented Dec 4, 2017

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
@nedtwigg
Copy link
Member

nedtwigg commented Dec 4, 2017 via email

@jbduncan
Copy link
Member Author

jbduncan commented Dec 4, 2017

@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.

@jbduncan
Copy link
Member Author

jbduncan commented Dec 4, 2017

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.

@nedtwigg
Copy link
Member

nedtwigg commented Dec 7, 2017

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.

@jbduncan
Copy link
Member Author

jbduncan commented Dec 7, 2017

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. :)

@nedtwigg nedtwigg changed the title paddedCell()-inducing problem with running spotlessCheck on Spotless itself on Windows convergence problem in import sorter - fixable by paddedCell() Dec 7, 2017
@nedtwigg nedtwigg changed the title convergence problem in import sorter - fixable by paddedCell() idempotence problem in import sorter - fixable by paddedCell() Dec 7, 2017
@nedtwigg nedtwigg added the bug label Dec 25, 2017
@nedtwigg
Copy link
Member

paddedCell is always enabled now.

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

2 participants