Skip to content

Commit 0d34fa7

Browse files
committed
Switch from new File() to a Sentinel reference
1 parent a8c0bb8 commit 0d34fa7

File tree

4 files changed

+45
-14
lines changed

4 files changed

+45
-14
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
public final class Formatter implements Serializable, AutoCloseable {
4040
private static final long serialVersionUID = 1L;
4141

42+
// This Sentinel reference may be used where Formatter requires a File, while there is no actual File to format
43+
public static final File SENTINEL_NO_FILE_ON_DISK = new File("NO_FILE_ON_DISK.sentinel");
44+
4245
private LineEnding.Policy lineEndingsPolicy;
4346
private Charset encoding;
4447
private Path rootDir;
@@ -237,8 +240,7 @@ public String compute(String unix, File file) {
237240
unix = LineEnding.toUnix(formatted);
238241
}
239242
} catch (Throwable e) {
240-
if (file.getPath().isEmpty()) {
241-
// Path.relativize would fail if rootDir is an absolute path
243+
if (file == SENTINEL_NO_FILE_ON_DISK) {
242244
exceptionPolicy.handleError(e, step, "");
243245
} else {
244246
// Path may be forged from a different FileSystem than Filesystem.default

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2021 DiffPlug
2+
* Copyright 2016-2023 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.
@@ -37,8 +37,8 @@ public interface FormatterStep extends Serializable {
3737
* @param rawUnix
3838
* the content to format, guaranteed to have unix-style newlines ('\n'); never null
3939
* @param file
40-
* the file which {@code rawUnix} was obtained from; never null. Pass an empty file using
41-
* {@code new File("")} if and only if no file is actually associated with {@code rawUnix}
40+
* the file which {@code rawUnix} was obtained from; never null. Pass the reference
41+
* {@code Formatter#SENTINEL_NO_FILE_ON_DISK} if and only if no file is actually associated with {@code rawUnix}
4242
* @return the formatted content, guaranteed to only have unix-style newlines; may return null
4343
* if the formatter step doesn't have any changes to make
4444
* @throws Exception if the formatter step experiences a problem

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2022 DiffPlug
2+
* Copyright 2016-2023 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.
@@ -109,18 +109,15 @@ protected String format(Integer state, String rawUnix, File file) throws Excepti
109109
if (formatter == null) {
110110
formatter = formatterSupplier.get();
111111
if (formatter instanceof FormatterFunc.Closeable) {
112-
throw new AssertionError("NeverUpToDate does not support FormatterFunc.Closeable. See https://github.com/diffplug/spotless/pull/284");
112+
throw new AssertionError("NeverUpToDate does not support FormatterFunc.Closeable. See https://github.com/diffplug/spotless/pull/284");
113113
}
114114
}
115115
return formatter.apply(rawUnix, file);
116116
}
117117
}
118118

119-
/** A dummy SENTINEL file. */
120-
static final File SENTINEL = new File("");
121-
122119
static void checkNotSentinel(File file) {
123-
if (file == SENTINEL) {
120+
if (file == Formatter.SENTINEL_NO_FILE_ON_DISK) {
124121
throw new IllegalArgumentException("This step requires the underlying file. If this is a test, use StepHarnessWithFile");
125122
}
126123
}

testlib/src/test/java/com/diffplug/spotless/FormatterTest.java

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.io.File;
1919
import java.nio.charset.Charset;
2020
import java.nio.charset.StandardCharsets;
21+
import java.nio.file.FileSystem;
2122
import java.nio.file.FileSystems;
2223
import java.nio.file.Path;
2324
import java.nio.file.Paths;
@@ -94,7 +95,7 @@ protected Formatter create() {
9495
}.testEquals();
9596
}
9697

97-
// new File("") can be used if there is no File representing this content. It should not conflict with rootDir.relativize(...)
98+
// new File("") as filePath is known to fail
9899
@Test
99100
public void testExceptionWithEmptyPath() throws Exception {
100101
LineEnding.Policy lineEndingsPolicy = LineEnding.UNIX.createPolicy();
@@ -116,7 +117,32 @@ public void testExceptionWithEmptyPath() throws Exception {
116117
.exceptionPolicy(exceptionPolicy)
117118
.build();
118119

119-
formatter.compute("someFileContent", new File(""));
120+
Assertions.assertThrows(IllegalArgumentException.class, () -> formatter.compute("someFileContent", new File("")));
121+
}
122+
123+
// If there is no File actually holding the content, one may rely on Formatter.NO_FILE_ON_DISK
124+
@Test
125+
public void testExceptionWithSentinelNoFileOnDisk() throws Exception {
126+
LineEnding.Policy lineEndingsPolicy = LineEnding.UNIX.createPolicy();
127+
Charset encoding = StandardCharsets.UTF_8;
128+
FormatExceptionPolicy exceptionPolicy = FormatExceptionPolicy.failOnlyOnError();
129+
130+
Path rootDir = Paths.get(StandardSystemProperty.USER_DIR.value());
131+
132+
FormatterStep step = Mockito.mock(FormatterStep.class);
133+
Mockito.when(step.getName()).thenReturn("someFailingStep");
134+
Mockito.when(step.format(Mockito.anyString(), Mockito.any(File.class))).thenThrow(new IllegalArgumentException("someReason"));
135+
List<FormatterStep> steps = Collections.singletonList(step);
136+
137+
Formatter formatter = Formatter.builder()
138+
.lineEndingsPolicy(lineEndingsPolicy)
139+
.encoding(encoding)
140+
.rootDir(rootDir)
141+
.steps(steps)
142+
.exceptionPolicy(exceptionPolicy)
143+
.build();
144+
145+
formatter.compute("someFileContent", Formatter.SENTINEL_NO_FILE_ON_DISK);
120146
}
121147

122148
// rootDir may be a path not from the default FileSystem
@@ -127,6 +153,12 @@ public void testExceptionWithRootDirIsNotFileSystem() throws Exception {
127153
FormatExceptionPolicy exceptionPolicy = FormatExceptionPolicy.failOnlyOnError();
128154

129155
Path rootDir = Mockito.mock(Path.class);
156+
FileSystem customFileSystem = Mockito.mock(FileSystem.class);
157+
Mockito.when(rootDir.getFileSystem()).thenReturn(customFileSystem);
158+
159+
Path pathFromFile = Mockito.mock(Path.class);
160+
Mockito.when(customFileSystem.getPath(Mockito.anyString())).thenReturn(pathFromFile);
161+
130162
Path relativized = Mockito.mock(Path.class);
131163
Mockito.when(rootDir.relativize(Mockito.any(Path.class))).then(invok -> {
132164
Path filePath = invok.getArgument(0);
@@ -150,7 +182,7 @@ public void testExceptionWithRootDirIsNotFileSystem() throws Exception {
150182
.exceptionPolicy(exceptionPolicy)
151183
.build();
152184

153-
formatter.compute("someFileContent", new File(""));
185+
formatter.compute("someFileContent", new File("/some/folder/some.file"));
154186
}
155187

156188
}

0 commit comments

Comments
 (0)