Skip to content

Commit

Permalink
Work around build dependency issue.
Browse files Browse the repository at this point in the history
The problem was not that Gradle runs any spotlessLinguaFranca tasks as
part of its other operations, but that it configures the task before
starting any other operation (including clean). The solution is to start
the formatter lazily -- to wait until spotlessLinguaFranca actually
operates on a file before trying to start up the formatter process.
  • Loading branch information
petervdonovan committed May 27, 2023
1 parent 433b9e6 commit fe8dfb9
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 37 deletions.
12 changes: 6 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ spotless {
endWithNewline()
}

// format 'linguaFranca', {
// addStep(LfFormatStep.create(project.projectDir))
// target 'test/*/src/**/*.lf' // you have to set the target manually
// targetExclude 'test/**/failing/**'
// }
format 'linguaFranca', {
addStep(LfFormatStep.create())
target 'test/*/src/**/*.lf' // you have to set the target manually
targetExclude 'test/**/failing/**'
}

}

//spotlessLinguaFranca.dependsOn(":org.lflang:cli:lff:installDist")
spotlessLinguaFranca.dependsOn(":org.lflang:cli:lff:installDist")


distributions {
Expand Down
60 changes: 29 additions & 31 deletions buildSrc/src/main/java/lfformat/LfFormatStep.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,8 @@
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;

/**
* {@code LfFormatStep} is used by the Spotless Gradle plugin as a custom formatting step for
Expand All @@ -23,57 +19,37 @@ public final class LfFormatStep {
private LfFormatStep() {}

/** Return a {@code FormatterStep} for LF code. */
public static FormatterStep create(File projectRoot) throws IOException {
Step.projectRoot = projectRoot.toPath();
return Step.getInstance();
public static FormatterStep create() throws IOException, InterruptedException {
return new Step();
}

/** Implement LF-specific formatting functionality. */
private static class Step implements FormatterStep {
// The use of the static keyword here is a workaround for serialization difficulties.
/** The path to the lingua-franca repository. */
private static Path projectRoot;

private static Step instance;

private static Process formatter;
private static Writer writer;

private static BufferedReader reader;
private static BufferedReader error;

public static Step getInstance() throws IOException {
if (instance == null) instance = new Step();
return instance;
}

private Step() throws IOException {
initializeFormatter();
Runtime.getRuntime()
.addShutdownHook(
new Thread(
() -> {
try {
writer.close();
formatter.waitFor();
reader.close();
error.close();
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}));
private Step() throws IOException, InterruptedException {
terminateFormatter();
}

@Override
public String format(@SuppressWarnings("NullableProblems") String rawUnix, File file)
throws IOException, InterruptedException {
initializeFormatter();
StringBuilder output = new StringBuilder();
try {
writer.write(file.getAbsoluteFile().toString().strip() + "\n");
writer.flush();
} catch (IOException e) {
formatter.waitFor();
error.lines().forEach(System.out::println);
formatter = null;
initializeFormatter();
throw new RuntimeException("Failed to format " + file + ".\nPlease ensure that this file passes validator checks.");
}
Expand All @@ -86,7 +62,9 @@ public String format(@SuppressWarnings("NullableProblems") String rawUnix, File
return output.toString();
}

private void initializeFormatter() throws IOException {
/** Idempotently initialize the formatter. */
private static void initializeFormatter() throws IOException {
if (formatter != null) return;
final Path lffPath =
Path.of(
"org.lflang",
Expand All @@ -106,6 +84,26 @@ private void initializeFormatter() throws IOException {
writer = new BufferedWriter(new OutputStreamWriter(formatter.getOutputStream()));
reader = new BufferedReader(new InputStreamReader(formatter.getInputStream()));
error = new BufferedReader(new InputStreamReader(formatter.getErrorStream()));
Runtime.getRuntime()
.addShutdownHook(
new Thread(
() -> {
try {
terminateFormatter();
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}));
}

/** Idempotently trigger a graceful termination of the formatter. */
private static void terminateFormatter() throws IOException, InterruptedException {
if (formatter == null) return;
writer.close();
formatter.waitFor();
reader.close();
error.close();
formatter = null;
}

@SuppressWarnings("NullableProblems")
Expand Down

0 comments on commit fe8dfb9

Please sign in to comment.