Skip to content

Fixup the last of the stragglers #2146

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

Merged
merged 8 commits into from
May 29, 2024
6 changes: 6 additions & 0 deletions lib/src/main/java/com/diffplug/spotless/Formatter.java
Original file line number Diff line number Diff line change
@@ -312,4 +312,10 @@ public void close() {

/** This Sentinel reference may be used to pass string content to a Formatter or FormatterStep when there is no actual File to format */
public static final File NO_FILE_SENTINEL = new File("NO_FILE_SENTINEL");

static void checkNotSentinel(File file) {
if (file == Formatter.NO_FILE_SENTINEL) {
throw new IllegalArgumentException("This step requires the underlying file. If this is a test, use StepHarnessWithFile");
}
}
}
4 changes: 2 additions & 2 deletions lib/src/main/java/com/diffplug/spotless/FormatterFunc.java
Original file line number Diff line number Diff line change
@@ -115,7 +115,7 @@ public void close() {

@Override
public String apply(String unix, File file) throws Exception {
FormatterStepImpl.checkNotSentinel(file);
Formatter.checkNotSentinel(file);
return function.apply(resource, unix, file);
}

@@ -144,7 +144,7 @@ interface NeedsFile extends FormatterFunc {

@Override
default String apply(String unix, File file) throws Exception {
FormatterStepImpl.checkNotSentinel(file);
Formatter.checkNotSentinel(file);
return applyWithFile(unix, file);
}

28 changes: 3 additions & 25 deletions lib/src/main/java/com/diffplug/spotless/FormatterStep.java
Original file line number Diff line number Diff line change
@@ -70,28 +70,6 @@ default FormatterStep filterByFile(SerializableFileFilter filter) {
return new FilterByFileFormatterStep(this, filter);
}

/**
* Implements a FormatterStep in a strict way which guarantees correct and lazy implementation
* of up-to-date checks. This maximizes performance for cases where the FormatterStep is not
* actually needed (e.g. don't load eclipse setting file unless this step is actually running)
* while also ensuring that Gradle can detect changes in a step's settings to determine that
* it needs to rerun a format.
*/
abstract class Strict<State extends Serializable> extends LazyForwardingEquality<State> implements FormatterStep {
private static final long serialVersionUID = 1L;

/**
* Implements the formatting function strictly in terms
* of the input data and the result of {@link #calculateState()}.
*/
protected abstract String format(State state, String rawUnix, File file) throws Exception;

@Override
public final String format(String rawUnix, File file) throws Exception {
return format(state(), rawUnix, file);
}
}

/**
* @param name
* The name of the formatter step.
@@ -151,8 +129,8 @@ static <RoundtripState extends Serializable, EqualityState extends Serializable>
static <State extends Serializable> FormatterStep createLazy(
String name,
ThrowingEx.Supplier<State> stateSupplier,
ThrowingEx.Function<State, FormatterFunc> stateToFormatter) {
return new FormatterStepImpl.Standard<>(name, stateSupplier, stateToFormatter);
SerializedFunction<State, FormatterFunc> stateToFormatter) {
return createLazy(name, stateSupplier, SerializedFunction.identity(), stateToFormatter);
}

/**
@@ -168,7 +146,7 @@ static <State extends Serializable> FormatterStep createLazy(
static <State extends Serializable> FormatterStep create(
String name,
State state,
ThrowingEx.Function<State, FormatterFunc> stateToFormatter) {
SerializedFunction<State, FormatterFunc> stateToFormatter) {
Objects.requireNonNull(state, "state");
return createLazy(name, () -> state, stateToFormatter);
}
133 changes: 0 additions & 133 deletions lib/src/main/java/com/diffplug/spotless/FormatterStepImpl.java

This file was deleted.

12 changes: 6 additions & 6 deletions lib/src/main/java/com/diffplug/spotless/cpp/ClangFormatStep.java
Original file line number Diff line number Diff line change
@@ -64,10 +64,10 @@ public ClangFormatStep withPathToExe(String pathToExe) {
}

public FormatterStep create() {
return FormatterStep.createLazy(name(), this::createState, RoundtripState::state, State::toFunc);
return FormatterStep.createLazy(name(), this::createRoundtrip, RoundtripState::toEquality, EqualityState::toFunc);
}

private RoundtripState createState() throws IOException, InterruptedException {
private RoundtripState createRoundtrip() throws IOException, InterruptedException {
String howToInstall = "" +
"You can download clang-format from https://releases.llvm.org and " +
"then point Spotless to it with {@code pathToExe('/path/to/clang-format')} " +
@@ -98,13 +98,13 @@ static class RoundtripState implements Serializable {
this.exe = exe;
}

private State state() {
return new State(version, style, exe);
private EqualityState toEquality() {
return new EqualityState(version, style, exe);
}
}

@SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED")
static class State implements Serializable {
static class EqualityState implements Serializable {
private static final long serialVersionUID = -1825662356883926318L;
// used for up-to-date checks and caching
final String version;
@@ -113,7 +113,7 @@ static class State implements Serializable {
// used for executing
private transient @Nullable List<String> args;

State(String version, @Nullable String style, ForeignExe pathToExe) {
EqualityState(String version, @Nullable String style, ForeignExe pathToExe) {
this.version = version;
this.style = style;
this.exe = Objects.requireNonNull(pathToExe);
25 changes: 19 additions & 6 deletions lib/src/main/java/com/diffplug/spotless/generic/NativeCmdStep.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021 DiffPlug
* Copyright 2021-2024 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,24 +35,37 @@ private NativeCmdStep() {}
public static FormatterStep create(String name, File pathToExe, List<String> arguments) {
Objects.requireNonNull(name, "name");
Objects.requireNonNull(pathToExe, "pathToExe");
return FormatterStep.createLazy(name, () -> new State(FileSignature.signAsList(pathToExe), arguments), State::toFunc);
return FormatterStep.createLazy(name, () -> new State(FileSignature.promise(pathToExe), arguments), State::toRuntime, Runtime::toFunc);
}

static class State implements Serializable {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 2L;
final FileSignature.Promised pathToExe;
final List<String> arguments;

final FileSignature pathToExe;
State(FileSignature.Promised pathToExe, List<String> arguments) {
this.pathToExe = pathToExe;
this.arguments = arguments;
}

Runtime toRuntime() {
return new Runtime(pathToExe.get().getOnlyFile(), arguments);
}
}

static class Runtime implements Serializable {
private static final long serialVersionUID = 2L;
final File pathToExe;
final List<String> arguments;

State(FileSignature pathToExe, List<String> arguments) {
Runtime(File pathToExe, List<String> arguments) {
this.pathToExe = pathToExe;
this.arguments = arguments;
}

String format(ProcessRunner runner, String input) throws IOException, InterruptedException {
List<String> argumentsWithPathToExe = new ArrayList<>();
argumentsWithPathToExe.add(pathToExe.getOnlyFile().getAbsolutePath());
argumentsWithPathToExe.add(pathToExe.getAbsolutePath());
if (arguments != null) {
argumentsWithPathToExe.addAll(arguments);
}
28 changes: 22 additions & 6 deletions lib/src/main/java/com/diffplug/spotless/go/GofmtFormatStep.java
Original file line number Diff line number Diff line change
@@ -63,10 +63,10 @@ public GofmtFormatStep withGoExecutable(String pathToExe) {
}

public FormatterStep create() {
return FormatterStep.createLazy(name(), this::createState, GofmtFormatStep.State::toFunc);
return FormatterStep.createLazy(name(), this::createRountrip, RoundtripState::toEquality, EqualityState::toFunc);
}

private State createState() throws IOException, InterruptedException {
private RoundtripState createRountrip() throws IOException, InterruptedException {
String howToInstall = "gofmt is a part of standard go distribution. If spotless can't discover it automatically, " +
"you can point Spotless to the go binary with {@code pathToExe('/path/to/go')}";
final ForeignExe exe = ForeignExe.nameAndVersion("go", version)
@@ -76,18 +76,34 @@ private State createState() throws IOException, InterruptedException {
.fixWrongVersion(
"You can tell Spotless to use the version you already have with {@code gofmt('{versionFound}')}" +
"or you can install the currently specified Go version, {version}.\n" + howToInstall);
return new State(this, exe);
return new RoundtripState(version, exe);
}

static class RoundtripState implements Serializable {
private static final long serialVersionUID = 1L;

final String version;
final ForeignExe exe;

RoundtripState(String version, ForeignExe exe) {
this.version = version;
this.exe = exe;
}

private EqualityState toEquality() {
return new EqualityState(version, exe);
}
}

@SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED")
static class State implements Serializable {
static class EqualityState implements Serializable {
private static final long serialVersionUID = -1825662355363926318L;
// used for up-to-date checks and caching
final String version;
final transient ForeignExe exe;

public State(GofmtFormatStep step, ForeignExe goExecutable) {
this.version = step.version;
public EqualityState(String version, ForeignExe goExecutable) {
this.version = version;
this.exe = Objects.requireNonNull(goExecutable);
}

12 changes: 6 additions & 6 deletions lib/src/main/java/com/diffplug/spotless/python/BlackStep.java
Original file line number Diff line number Diff line change
@@ -56,10 +56,10 @@ public BlackStep withPathToExe(String pathToExe) {
}

public FormatterStep create() {
return FormatterStep.createLazy(name(), this::createState, RoundtripState::state, State::toFunc);
return FormatterStep.createLazy(name(), this::createRoundtrip, RoundtripState::toEquality, EqualityState::toFunc);
}

private RoundtripState createState() {
private RoundtripState createRoundtrip() {
String trackingIssue = "\n github issue to handle this better: https://github.com/diffplug/spotless/issues/674";
ForeignExe exeAbsPath = ForeignExe.nameAndVersion("black", version)
.pathToExe(pathToExe)
@@ -80,21 +80,21 @@ static class RoundtripState implements Serializable {
this.exe = exe;
}

private State state() {
return new State(version, exe);
private EqualityState toEquality() {
return new EqualityState(version, exe);
}
}

@SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED")
static class State implements Serializable {
static class EqualityState implements Serializable {
private static final long serialVersionUID = -1825662356883926318L;
// used for up-to-date checks and caching
final String version;
final transient ForeignExe exe;
// used for executing
private transient @Nullable String[] args;

State(String version, ForeignExe exeAbsPath) {
EqualityState(String version, ForeignExe exeAbsPath) {
this.version = version;
this.exe = Objects.requireNonNull(exeAbsPath);
}
Loading