Skip to content

Commit 2e33d3b

Browse files
authored
Serializable foreign exe (#1955)
2 parents f5bfb34 + adbe14e commit 2e33d3b

File tree

5 files changed

+76
-21
lines changed

5 files changed

+76
-21
lines changed

lib/src/main/java/com/diffplug/spotless/ForeignExe.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2023 DiffPlug
2+
* Copyright 2020-2024 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
1616
package com.diffplug.spotless;
1717

1818
import java.io.IOException;
19+
import java.io.Serializable;
1920
import java.nio.charset.Charset;
2021
import java.util.Objects;
2122
import java.util.regex.Matcher;
@@ -31,7 +32,8 @@
3132
* Usage: {@code ForeignExe.nameAndVersion("grep", "2.5.7").confirmVersionAndGetAbsolutePath()}
3233
* will find grep, confirm that it is version 2.5.7, and then return.
3334
*/
34-
public class ForeignExe {
35+
public class ForeignExe implements Serializable {
36+
private static final long serialVersionUID = 1L;
3537
private @Nullable String pathToExe;
3638
private String versionFlag = "--version";
3739
private Pattern versionRegex = Pattern.compile("version (\\S*)");

lib/src/main/java/com/diffplug/spotless/cpp/ClangFormatStep.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2022 DiffPlug
2+
* Copyright 2020-2024 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -64,10 +64,10 @@ public ClangFormatStep withPathToExe(String pathToExe) {
6464
}
6565

6666
public FormatterStep create() {
67-
return FormatterStep.createLazy(name(), this::createState, State::toFunc);
67+
return FormatterStep.createLazy(name(), this::createState, RoundtripState::state, State::toFunc);
6868
}
6969

70-
private State createState() throws IOException, InterruptedException {
70+
private RoundtripState createState() throws IOException, InterruptedException {
7171
String howToInstall = "" +
7272
"You can download clang-format from https://releases.llvm.org and " +
7373
"then point Spotless to it with {@code pathToExe('/path/to/clang-format')} " +
@@ -82,7 +82,25 @@ private State createState() throws IOException, InterruptedException {
8282
.fixWrongVersion(
8383
"You can tell Spotless to use the version you already have with {@code clangFormat('{versionFound}')}" +
8484
"or you can download the currently specified version, {version}.\n" + howToInstall);
85-
return new State(this, exe);
85+
return new RoundtripState(this, exe);
86+
}
87+
88+
static class RoundtripState implements Serializable {
89+
private static final long serialVersionUID = 1L;
90+
91+
final String version;
92+
final @Nullable String style;
93+
final ForeignExe exe;
94+
95+
RoundtripState(ClangFormatStep step, ForeignExe exe) {
96+
this.version = step.version;
97+
this.style = step.style;
98+
this.exe = exe;
99+
}
100+
101+
private State state() {
102+
return new State(version, style, exe);
103+
}
86104
}
87105

88106
@SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED")
@@ -95,9 +113,9 @@ static class State implements Serializable {
95113
// used for executing
96114
private transient @Nullable List<String> args;
97115

98-
State(ClangFormatStep step, ForeignExe pathToExe) {
99-
this.version = step.version;
100-
this.style = step.style;
116+
State(String version, @Nullable String style, ForeignExe pathToExe) {
117+
this.version = version;
118+
this.style = style;
101119
this.exe = Objects.requireNonNull(pathToExe);
102120
}
103121

lib/src/main/java/com/diffplug/spotless/protobuf/BufStep.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,32 @@ public BufStep withPathToExe(String pathToExe) {
5858
}
5959

6060
public FormatterStep create() {
61-
return FormatterStep.createLazy(name(), this::createState, State::toFunc);
61+
return FormatterStep.createLazy(name(), this::createRoundtrip, RoundtripState::state, State::toFunc);
6262
}
6363

64-
private State createState() {
64+
private RoundtripState createRoundtrip() {
6565
String instructions = "https://docs.buf.build/installation";
6666
ForeignExe exe = ForeignExe.nameAndVersion("buf", version)
6767
.pathToExe(pathToExe)
6868
.versionRegex(Pattern.compile("(\\S*)"))
6969
.fixCantFind("Try following the instructions at " + instructions + ", or else tell Spotless where it is with {@code buf().pathToExe('path/to/executable')}");
70-
return new State(this, exe);
70+
return new RoundtripState(version, exe);
71+
}
72+
73+
private static class RoundtripState implements Serializable {
74+
private static final long serialVersionUID = 1L;
75+
76+
final String version;
77+
final ForeignExe exe;
78+
79+
RoundtripState(String version, ForeignExe exe) {
80+
this.version = version;
81+
this.exe = exe;
82+
}
83+
84+
private State state() {
85+
return new State(version, exe);
86+
}
7187
}
7288

7389
@SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED")
@@ -80,9 +96,9 @@ static class State implements Serializable {
8096
private final transient ForeignExe exe;
8197
private transient String exeAbsPath;
8298

83-
State(BufStep step, ForeignExe exe) {
84-
this.version = step.version;
85-
this.exe = Objects.requireNonNull(exe);
99+
State(String version, ForeignExe exeAbsPath) {
100+
this.version = version;
101+
this.exe = Objects.requireNonNull(exeAbsPath);
86102
}
87103

88104
String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException {

lib/src/main/java/com/diffplug/spotless/python/BlackStep.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2022 DiffPlug
2+
* Copyright 2020-2024 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -56,17 +56,33 @@ public BlackStep withPathToExe(String pathToExe) {
5656
}
5757

5858
public FormatterStep create() {
59-
return FormatterStep.createLazy(name(), this::createState, State::toFunc);
59+
return FormatterStep.createLazy(name(), this::createState, RoundtripState::state, State::toFunc);
6060
}
6161

62-
private State createState() throws IOException, InterruptedException {
62+
private RoundtripState createState() {
6363
String trackingIssue = "\n github issue to handle this better: https://github.com/diffplug/spotless/issues/674";
6464
ForeignExe exeAbsPath = ForeignExe.nameAndVersion("black", version)
6565
.pathToExe(pathToExe)
6666
.versionRegex(Pattern.compile("(?:black, version|black,|version) (\\S*)"))
6767
.fixCantFind("Try running {@code pip install black=={version}}, or else tell Spotless where it is with {@code black().pathToExe('path/to/executable')}" + trackingIssue)
6868
.fixWrongVersion("Try running {@code pip install --force-reinstall black=={version}}, or else specify {@code black('{versionFound}')} to Spotless" + trackingIssue);
69-
return new State(this, exeAbsPath);
69+
return new RoundtripState(version, exeAbsPath);
70+
}
71+
72+
static class RoundtripState implements Serializable {
73+
private static final long serialVersionUID = 1L;
74+
75+
final String version;
76+
final ForeignExe exe;
77+
78+
RoundtripState(String version, ForeignExe exe) {
79+
this.version = version;
80+
this.exe = exe;
81+
}
82+
83+
private State state() {
84+
return new State(version, exe);
85+
}
7086
}
7187

7288
@SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED")
@@ -78,8 +94,8 @@ static class State implements Serializable {
7894
// used for executing
7995
private transient @Nullable String[] args;
8096

81-
State(BlackStep step, ForeignExe exeAbsPath) {
82-
this.version = step.version;
97+
State(String version, ForeignExe exeAbsPath) {
98+
this.version = version;
8399
this.exe = Objects.requireNonNull(exeAbsPath);
84100
}
85101

testlib/src/main/java/com/diffplug/spotless/StepHarnessBase.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.util.Locale;
1919
import java.util.Objects;
20+
import java.util.Set;
2021

2122
import org.assertj.core.api.Assertions;
2223

@@ -48,6 +49,8 @@ protected StepHarnessBase(Formatter formatter) {
4849
supportsRoundTrip = true;
4950
} else if (onlyStepName.equals("fence")) {
5051
supportsRoundTrip = true;
52+
} else if (Set.of("black", "buf", "clang").contains(onlyStepName)) {
53+
supportsRoundTrip = true;
5154
}
5255
}
5356
}

0 commit comments

Comments
 (0)