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

SpotlessTaskService (towards configuration-cache) #982

Merged
merged 24 commits into from
Nov 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4612225
First cut at replacing our task-specific fields with SpotlessTaskServ…
nedtwigg Nov 6, 2021
23ed7c4
Refactor check and apply to be subclass of SpotlessTaskService.Client…
nedtwigg Nov 6, 2021
c6f8e84
Fix FormatExtension::createIndependentApplyTask to work with the stri…
nedtwigg Nov 6, 2021
e9ad708
Better names for SpotlessTaskService.
nedtwigg Nov 6, 2021
3c762bb
Fix tests which needed to set the SpotlessTaskService manually.
nedtwigg Nov 6, 2021
e393951
SpotlessTaskService.Client now includes `Property<File> getSpotlessOu…
nedtwigg Nov 6, 2021
3bb79c8
Oops, spotlessCheck cares about getSourceDidWork(), not apply.
nedtwigg Nov 6, 2021
bcd40d5
Make RegisterDependenciesTask more focused.
nedtwigg Nov 6, 2021
84101b9
FileSignature now supports `.equals` and `.hashCode` without serializ…
nedtwigg Nov 6, 2021
dbad659
SpotlessTaskSerivce now caches error messages from run to run.
nedtwigg Nov 6, 2021
93e3102
Fix validatePlugins errors.
nedtwigg Nov 6, 2021
13f70f1
Refactor DiffMessageFormatter to prepare for formatting from a folder…
nedtwigg Nov 6, 2021
a3cad7b
Add a DiffMessageFormatter which works on a folder of clean files.
nedtwigg Nov 6, 2021
36947e6
Refactor SpotlessCheck to use that formatter so that we can ditch the…
nedtwigg Nov 6, 2021
88e6298
SpotlessCheck now pipes the actual encoding to the error message rath…
nedtwigg Nov 6, 2021
d059972
Replace `getProject()` invocations with ObjectFactory and FileSystemO…
nedtwigg Nov 7, 2021
e0b850e
Use SpotlessTaskService.init to consolidate configuration-avoidance f…
nedtwigg Nov 7, 2021
ff9bb5f
Add SpotlessTaskImpl.init to simplify that task as well.
nedtwigg Nov 7, 2021
cf4bdd1
We should definitely remove unused imports before yelling about inter…
nedtwigg Nov 7, 2021
998f188
Convert GitRatchetGradle to be File-based, which allows us to remove …
nedtwigg Nov 7, 2021
c8d13b1
MIscellaneous cleanup.
nedtwigg Nov 7, 2021
4af94ec
Another small fix.
nedtwigg Nov 7, 2021
9596881
(Unneeded change) Revert "FileSignature now supports `.equals` and `.…
nedtwigg Nov 7, 2021
eb8db28
Update the lib changelog.
nedtwigg Nov 9, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ This document is intended for Spotless developers.
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).

## [Unreleased]
### Added
* `DiffMessageFormatter` can now generate messages based on a folder of cleaned files, as an alternative to a `Formatter` ([#982](https://github.com/diffplug/spotless/pull/982)).

## [2.19.2] - 2021-10-26
### Changed
Expand Down
2 changes: 1 addition & 1 deletion gradle/spotless.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ spotless {
// the rootProject doesn't have any java
java {
ratchetFrom 'origin/main'
custom 'noInternalDeps', noInternalDepsClosure
bumpThisNumberIfACustomStepChanges(1)
licenseHeaderFile rootProject.file('gradle/spotless.license')
importOrderFile rootProject.file('gradle/spotless.importorder')
eclipse().configFile rootProject.file('gradle/spotless.eclipseformat.xml')
trimTrailingWhitespace()
removeUnusedImports()
custom 'noInternalDeps', noInternalDepsClosure
}
}
groovyGradle {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2020 DiffPlug
* Copyright 2016-2021 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,8 +18,10 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
Expand All @@ -44,11 +46,74 @@ public static Builder builder() {
return new Builder();
}

interface CleanProvider {

Path getRootDir();

Charset getEncoding();

String getFormatted(File file, String rawUnix);
}

private static class CleanProviderFormatter implements CleanProvider {
private final Formatter formatter;

CleanProviderFormatter(Formatter formatter) {
this.formatter = Objects.requireNonNull(formatter);
}

@Override
public Path getRootDir() {
return formatter.getRootDir();
}

@Override
public Charset getEncoding() {
return formatter.getEncoding();
}

@Override
public String getFormatted(File file, String rawUnix) {
String unix = PaddedCell.check(formatter, file, rawUnix).canonical();
return formatter.computeLineEndings(unix, file);
}
}

private static class CleanProviderFolder implements CleanProvider {
private final Path rootDir;
private final Path cleanDir;
private final Charset encoding;

CleanProviderFolder(Path rootDir, Path cleanDir, String encoding) {
this.rootDir = rootDir;
this.cleanDir = cleanDir;
this.encoding = Charset.forName(encoding);
}

@Override
public Path getRootDir() {
return rootDir;
}

@Override
public Charset getEncoding() {
return encoding;
}

@Override
public String getFormatted(File file, String rawUnix) {
Path relative = rootDir.relativize(file.toPath());
Path clean = cleanDir.resolve(rootDir.relativize(file.toPath()));
byte[] content = Errors.rethrow().get(() -> Files.readAllBytes(clean));
return new String(content, encoding);
}
}

public static class Builder {
private Builder() {}

private String runToFix;
private Formatter formatter;
private CleanProvider formatter;
private List<File> problemFiles;

/** "Run 'gradlew spotlessApply' to fix these violations." */
Expand All @@ -58,7 +123,12 @@ public Builder runToFix(String runToFix) {
}

public Builder formatter(Formatter formatter) {
this.formatter = Objects.requireNonNull(formatter);
this.formatter = new CleanProviderFormatter(formatter);
return this;
}

public Builder formatterFolder(Path rootDir, Path cleanDir, String encoding) {
this.formatter = new CleanProviderFolder(rootDir, cleanDir, encoding);
return this;
}

Expand Down Expand Up @@ -164,12 +234,11 @@ private void addIntendedLine(String indent, String line) {
private static String diff(Builder builder, File file) throws IOException {
String raw = new String(Files.readAllBytes(file.toPath()), builder.formatter.getEncoding());
String rawUnix = LineEnding.toUnix(raw);
String formattedUnix;
formattedUnix = PaddedCell.check(builder.formatter, file, rawUnix).canonical();
String formatted = builder.formatter.getFormatted(file, rawUnix);
String formattedUnix = LineEnding.toUnix(formatted);

if (rawUnix.equals(formattedUnix)) {
// the formatting is fine, so it's a line-ending issue
String formatted = builder.formatter.computeLineEndings(formattedUnix, file);
return diffWhitespaceLineEndings(raw, formatted, false, true);
} else {
return diffWhitespaceLineEndings(rawUnix, formattedUnix, true, false);
Expand Down
1 change: 1 addition & 0 deletions plugin-gradle/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
## [Unreleased]
### Changed
* **BREAKING** Previously, many projects required `buildscript { repositories { mavenCentral() }}` at the top of their root project, because Spotless resolved its dependencies using the buildscript repositories. Spotless now resolves its dependencies from the normal project repositories of the root project, which means that you can remove the `buildscript {}` block, but you still need `repositories { mavenCentral() }` (or similar) in the root project.
* **BREAKING** `createIndepentApplyTask(String taskName)` now requires that `taskName` does not end with `Apply`
* Bump minimum required Gradle from `6.1` to `6.1.1`.

## [5.17.1] - 2021-10-26
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.gradle.api.file.FileCollection;
import org.gradle.api.plugins.BasePlugin;

import com.diffplug.common.base.Preconditions;
import com.diffplug.spotless.FormatExceptionPolicyStrict;
import com.diffplug.spotless.FormatterFunc;
import com.diffplug.spotless.FormatterStep;
Expand Down Expand Up @@ -754,19 +755,22 @@ protected Project getProject() {
*
* The returned task will not be hooked up to the global {@code spotlessApply}, and there will be no corresponding {@code check} task.
*
* The task name must not end with `Apply`.
*
* NOTE: does not respect the rarely-used <a href="https://github.com/diffplug/spotless/blob/b7f8c551a97dcb92cc4b0ee665448da5013b30a3/plugin-gradle/README.md#can-i-apply-spotless-to-specific-files">{@code spotlessFiles} property</a>.
*/
public SpotlessApply createIndependentApplyTask(String taskName) {
Preconditions.checkArgument(!taskName.endsWith(SpotlessExtension.APPLY), "Task name must not end with " + SpotlessExtension.APPLY);
// create and setup the task
SpotlessTask spotlessTask = spotless.project.getTasks().create(taskName + "Helper", SpotlessTaskImpl.class);
SpotlessTaskImpl spotlessTask = spotless.project.getTasks().create(taskName + SpotlessTaskService.INDEPENDENT_HELPER, SpotlessTaskImpl.class);
spotlessTask.init(spotless.getTaskService());
setupTask(spotlessTask);
// enforce the clean ordering
Task clean = spotless.project.getTasks().getByName(BasePlugin.CLEAN_TASK_NAME);
spotlessTask.mustRunAfter(clean);
// create the apply task
SpotlessApply applyTask = spotless.project.getTasks().create(taskName, SpotlessApply.class);
applyTask.setSpotlessOutDirectory(spotlessTask.getOutputDirectory());
applyTask.linkSource(spotlessTask);
applyTask.init(spotlessTask);
applyTask.dependsOn(spotlessTask);

return applyTask;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import javax.annotation.Nullable;

import org.gradle.api.Project;
import org.gradle.api.services.BuildService;
import org.gradle.api.services.BuildServiceParameters;
import org.gradle.tooling.events.FinishEvent;
Expand All @@ -28,15 +27,15 @@
import com.diffplug.spotless.extra.GitRatchet;

/** Gradle implementation of GitRatchet. */
public abstract class GitRatchetGradle extends GitRatchet<Project> implements BuildService<BuildServiceParameters.None>, OperationCompletionListener {
public abstract class GitRatchetGradle extends GitRatchet<File> implements BuildService<BuildServiceParameters.None>, OperationCompletionListener {
@Override
protected File getDir(Project project) {
return project.getProjectDir();
protected File getDir(File project) {
return project;
}

@Override
protected @Nullable Project getParent(Project project) {
return project.getParent();
protected @Nullable File getParent(File project) {
return project.getParentFile();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016-2020 DiffPlug
* Copyright 2016-2021 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -33,7 +33,7 @@ private static void dumpIsClean() {
System.err.println("IS CLEAN");
}

static void performHook(SpotlessTask spotlessTask) {
static void performHook(SpotlessTaskImpl spotlessTask) {
String path = (String) spotlessTask.getProject().property(PROPERTY);
File file = new File(path);
if (!file.isAbsolute()) {
Expand All @@ -43,7 +43,7 @@ static void performHook(SpotlessTask spotlessTask) {
if (spotlessTask.getTarget().contains(file)) {
try (Formatter formatter = spotlessTask.buildFormatter()) {
if (spotlessTask.ratchet != null) {
if (spotlessTask.ratchet.isClean(spotlessTask.getProject(), spotlessTask.rootTreeSha, file)) {
if (spotlessTask.ratchet.isClean(spotlessTask.getProjectDir().get().getAsFile(), spotlessTask.rootTreeSha, file)) {
dumpIsClean();
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2016 DiffPlug
* Copyright 2016-2021 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -39,7 +39,7 @@ static void toFile(Serializable obj, File file) {
}
}

static <T extends Serializable> T fromFile(Class<T> clazz, File file) {
static <T> T fromFile(Class<T> clazz, File file) {
try (InputStream input = Files.asByteSource(file).openBufferedStream()) {
return fromStream(clazz, input);
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,18 @@
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;

import org.gradle.api.DefaultTask;
import org.gradle.api.file.ConfigurableFileTree;
import org.gradle.api.file.FileVisitDetails;
import org.gradle.api.file.FileVisitor;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.TaskAction;

public class SpotlessApply extends DefaultTask {
private SpotlessTask source;

/** Bidirectional link between Apply and Spotless allows check to know if Apply ran or not. */
void linkSource(SpotlessTask source) {
this.source = source;
source.applyTask = this;
}

private File spotlessOutDirectory;

@Internal
public File getSpotlessOutDirectory() {
return spotlessOutDirectory;
}

public void setSpotlessOutDirectory(File spotlessOutDirectory) {
this.spotlessOutDirectory = spotlessOutDirectory;
}

public abstract class SpotlessApply extends SpotlessTaskService.ClientTask {
@TaskAction
public void performAction() {
ConfigurableFileTree files = getProject().fileTree(spotlessOutDirectory);
getTaskService().get().registerApplyAlreadyRan(this);
ConfigurableFileTree files = getConfigCacheWorkaround().fileTree().from(getSpotlessOutDirectory().get());
if (files.isEmpty()) {
getState().setDidWork(source.getDidWork());
getState().setDidWork(sourceDidWork());
} else {
files.visit(new FileVisitor() {
@Override
Expand All @@ -62,7 +42,7 @@ public void visitDir(FileVisitDetails fileVisitDetails) {
@Override
public void visitFile(FileVisitDetails fileVisitDetails) {
String path = fileVisitDetails.getPath();
File originalSource = new File(getProject().getProjectDir(), path);
File originalSource = new File(getProjectDir().get().getAsFile(), path);
try {
getLogger().debug("Copying " + fileVisitDetails.getFile() + " to " + originalSource);
Files.copy(fileVisitDetails.getFile().toPath(), originalSource.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
Expand Down
Loading