Skip to content

Commit bf8423e

Browse files
committed
Add withPosition instance method to allow reuse of resolved canonical file
See #4630
1 parent 91a5f71 commit bf8423e

File tree

2 files changed

+41
-13
lines changed

2 files changed

+41
-13
lines changed

junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FileSource.java

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
package org.junit.platform.engine.support.descriptor;
1212

13+
import static org.apiguardian.api.API.Status.EXPERIMENTAL;
1314
import static org.apiguardian.api.API.Status.STABLE;
1415

1516
import java.io.File;
@@ -44,7 +45,7 @@ public class FileSource implements FileSystemSource {
4445
* @param file the source file; must not be {@code null}
4546
*/
4647
public static FileSource from(File file) {
47-
return new FileSource(file);
48+
return from(file, null);
4849
}
4950

5051
/**
@@ -55,25 +56,22 @@ public static FileSource from(File file) {
5556
* @param filePosition the position in the source file; may be {@code null}
5657
*/
5758
public static FileSource from(File file, @Nullable FilePosition filePosition) {
58-
return new FileSource(file, filePosition);
59+
Preconditions.notNull(file, "file must not be null");
60+
try {
61+
File canonicalFile = file.getCanonicalFile();
62+
return new FileSource(canonicalFile, filePosition);
63+
}
64+
catch (IOException ex) {
65+
throw new JUnitException("Failed to retrieve canonical path for file: " + file, ex);
66+
}
5967
}
6068

6169
private final File file;
6270

6371
private final @Nullable FilePosition filePosition;
6472

65-
private FileSource(File file) {
66-
this(file, null);
67-
}
68-
6973
private FileSource(File file, @Nullable FilePosition filePosition) {
70-
Preconditions.notNull(file, "file must not be null");
71-
try {
72-
this.file = file.getCanonicalFile();
73-
}
74-
catch (IOException ex) {
75-
throw new JUnitException("Failed to retrieve canonical path for file: " + file, ex);
76-
}
74+
this.file = file;
7775
this.filePosition = filePosition;
7876
}
7977

@@ -104,6 +102,20 @@ public final Optional<FilePosition> getPosition() {
104102
return Optional.ofNullable(this.filePosition);
105103
}
106104

105+
/**
106+
* Return a new {@code FileSource} based on this instance but with a different
107+
* {@link FilePosition}. This avoids redundant canonical path resolution
108+
* by reusing the already-canonical file.
109+
*
110+
* @param filePosition the new {@code FilePosition}; must not be {@code null}
111+
* @return a new {@code FileSource} with the same file and updated position
112+
*/
113+
@API(status = EXPERIMENTAL, since = "6.0")
114+
public FileSource withPosition(FilePosition filePosition) {
115+
Preconditions.notNull(filePosition, "filePosition must not be null");
116+
return new FileSource(this.file, filePosition);
117+
}
118+
107119
@Override
108120
public boolean equals(Object o) {
109121
if (this == o) {

platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/FileSystemSourceTests.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,22 @@ void fileWithPosition() {
7676
assertThat(source.getPosition()).hasValue(position);
7777
}
7878

79+
@Test
80+
void fileReuseWithPosition() {
81+
var file = new File("test.txt");
82+
var position = FilePosition.from(42, 23);
83+
var source = FileSource.from(file);
84+
var sourceWithPosition = source.withPosition(position);
85+
86+
assertThat(source.getUri()).isEqualTo(file.getAbsoluteFile().toURI());
87+
assertThat(source.getFile()).isEqualTo(file.getAbsoluteFile());
88+
assertThat(source.getPosition()).isEmpty();
89+
90+
assertThat(source).isNotSameAs(sourceWithPosition);
91+
assertThat(source.getFile()).isSameAs(sourceWithPosition.getFile());
92+
assertThat(sourceWithPosition.getPosition()).hasValue(position);
93+
}
94+
7995
@Test
8096
void equalsAndHashCodeForFileSource() {
8197
var file1 = new File("foo.txt");

0 commit comments

Comments
 (0)