Skip to content

Commit

Permalink
Serializable foreign exe (#1955)
Browse files Browse the repository at this point in the history
  • Loading branch information
nedtwigg committed Feb 12, 2024
2 parents f5bfb34 + adbe14e commit 2e33d3b
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 21 deletions.
6 changes: 4 additions & 2 deletions lib/src/main/java/com/diffplug/spotless/ForeignExe.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2023 DiffPlug
* Copyright 2020-2024 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 @@ -16,6 +16,7 @@
package com.diffplug.spotless;

import java.io.IOException;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.Objects;
import java.util.regex.Matcher;
Expand All @@ -31,7 +32,8 @@
* Usage: {@code ForeignExe.nameAndVersion("grep", "2.5.7").confirmVersionAndGetAbsolutePath()}
* will find grep, confirm that it is version 2.5.7, and then return.
*/
public class ForeignExe {
public class ForeignExe implements Serializable {
private static final long serialVersionUID = 1L;
private @Nullable String pathToExe;
private String versionFlag = "--version";
private Pattern versionRegex = Pattern.compile("version (\\S*)");
Expand Down
32 changes: 25 additions & 7 deletions lib/src/main/java/com/diffplug/spotless/cpp/ClangFormatStep.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2022 DiffPlug
* Copyright 2020-2024 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 @@ -64,10 +64,10 @@ public ClangFormatStep withPathToExe(String pathToExe) {
}

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

private State createState() throws IOException, InterruptedException {
private RoundtripState createState() 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')} " +
Expand All @@ -82,7 +82,25 @@ private State createState() throws IOException, InterruptedException {
.fixWrongVersion(
"You can tell Spotless to use the version you already have with {@code clangFormat('{versionFound}')}" +
"or you can download the currently specified version, {version}.\n" + howToInstall);
return new State(this, exe);
return new RoundtripState(this, exe);
}

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

final String version;
final @Nullable String style;
final ForeignExe exe;

RoundtripState(ClangFormatStep step, ForeignExe exe) {
this.version = step.version;
this.style = step.style;
this.exe = exe;
}

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

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

State(ClangFormatStep step, ForeignExe pathToExe) {
this.version = step.version;
this.style = step.style;
State(String version, @Nullable String style, ForeignExe pathToExe) {
this.version = version;
this.style = style;
this.exe = Objects.requireNonNull(pathToExe);
}

Expand Down
28 changes: 22 additions & 6 deletions lib/src/main/java/com/diffplug/spotless/protobuf/BufStep.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,32 @@ public BufStep withPathToExe(String pathToExe) {
}

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

private State createState() {
private RoundtripState createRoundtrip() {
String instructions = "https://docs.buf.build/installation";
ForeignExe exe = ForeignExe.nameAndVersion("buf", version)
.pathToExe(pathToExe)
.versionRegex(Pattern.compile("(\\S*)"))
.fixCantFind("Try following the instructions at " + instructions + ", or else tell Spotless where it is with {@code buf().pathToExe('path/to/executable')}");
return new State(this, exe);
return new RoundtripState(version, exe);
}

private 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 State state() {
return new State(version, exe);
}
}

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

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

String format(ProcessRunner runner, String input, File file) throws IOException, InterruptedException {
Expand Down
28 changes: 22 additions & 6 deletions lib/src/main/java/com/diffplug/spotless/python/BlackStep.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2022 DiffPlug
* Copyright 2020-2024 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 @@ -56,17 +56,33 @@ public BlackStep withPathToExe(String pathToExe) {
}

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

private State createState() throws IOException, InterruptedException {
private RoundtripState createState() {
String trackingIssue = "\n github issue to handle this better: https://github.com/diffplug/spotless/issues/674";
ForeignExe exeAbsPath = ForeignExe.nameAndVersion("black", version)
.pathToExe(pathToExe)
.versionRegex(Pattern.compile("(?:black, version|black,|version) (\\S*)"))
.fixCantFind("Try running {@code pip install black=={version}}, or else tell Spotless where it is with {@code black().pathToExe('path/to/executable')}" + trackingIssue)
.fixWrongVersion("Try running {@code pip install --force-reinstall black=={version}}, or else specify {@code black('{versionFound}')} to Spotless" + trackingIssue);
return new State(this, exeAbsPath);
return new RoundtripState(version, exeAbsPath);
}

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 State state() {
return new State(version, exe);
}
}

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

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.util.Locale;
import java.util.Objects;
import java.util.Set;

import org.assertj.core.api.Assertions;

Expand Down Expand Up @@ -48,6 +49,8 @@ protected StepHarnessBase(Formatter formatter) {
supportsRoundTrip = true;
} else if (onlyStepName.equals("fence")) {
supportsRoundTrip = true;
} else if (Set.of("black", "buf", "clang").contains(onlyStepName)) {
supportsRoundTrip = true;
}
}
}
Expand Down

0 comments on commit 2e33d3b

Please sign in to comment.