Skip to content

Commit 3cf0eb7

Browse files
committed
GH-1382 - Add Kotlin support for Change-Aware Test Execution
Signed-off-by: Lukas Dohmen <[email protected]>
1 parent 68557b5 commit 3cf0eb7

File tree

3 files changed

+58
-16
lines changed

3 files changed

+58
-16
lines changed

spring-modulith-junit/src/main/java/org/springframework/modulith/junit/Changes.java

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -161,46 +161,60 @@ sealed interface Change permits SourceChange, OtherFileChange {
161161
boolean hasOrigin(String nameOrPath);
162162

163163
/**
164-
* creates a new
165-
*
166-
* @param file
167-
* @return
164+
* Creates a change from a modified file
168165
*/
169166
static Change of(ModifiedFile file) {
167+
boolean isJavaSource = file.isJavaSource();
170168

171-
if (!file.isJavaSource()) {
169+
if (!isJavaSource && !file.isKotlinSource()) {
172170
return new OtherFileChange(file.path());
173171
}
174172

173+
var languageConfig = isJavaSource ? LanguageConfig.JAVA : LanguageConfig.KOTLIN;
174+
return toSourceChange(file, languageConfig);
175+
}
176+
177+
private static Change toSourceChange(ModifiedFile file, LanguageConfig config) {
175178
var withoutExtension = StringUtils.stripFilenameExtension(file.path());
176-
var startOfMainDir = withoutExtension.indexOf(JavaSourceChange.STANDARD_SOURCE_DIRECTORY);
177-
var startOfTestDir = withoutExtension.indexOf(JavaSourceChange.STANDARD_TEST_SOURCE_DIRECTORY);
179+
var startOfMainDir = withoutExtension.indexOf(config.mainDir());
180+
var startOfTestDir = withoutExtension.indexOf(config.testDir());
178181

179182
if (startOfTestDir > -1 && (startOfMainDir < 0 || startOfTestDir < startOfMainDir)) {
180183

181-
var fullyQualifiedClassName = ClassUtils.convertResourcePathToClassName(
182-
withoutExtension.substring(startOfTestDir + JavaSourceChange.STANDARD_TEST_SOURCE_DIRECTORY.length() + 1));
184+
var fullyQualifiedClassName = ClassUtils
185+
.convertResourcePathToClassName(withoutExtension.substring(startOfTestDir + config.testDir().length() + 1));
183186

184-
return new JavaTestSourceChange(fullyQualifiedClassName);
187+
return config.testFactory().apply(fullyQualifiedClassName);
185188
}
186189

187190
if (startOfMainDir > -1 && (startOfTestDir < 0 || startOfMainDir < startOfTestDir)) {
188191

189-
var fullyQualifiedClassName = ClassUtils.convertResourcePathToClassName(
190-
withoutExtension.substring(startOfMainDir + JavaSourceChange.STANDARD_SOURCE_DIRECTORY.length() + 1));
192+
var fullyQualifiedClassName = ClassUtils
193+
.convertResourcePathToClassName(withoutExtension.substring(startOfMainDir + config.mainDir().length() + 1));
191194

192-
return new JavaSourceChange(fullyQualifiedClassName);
195+
return config.mainFactory().apply(fullyQualifiedClassName);
193196
}
194197

195-
return new JavaSourceChange(ClassUtils.convertResourcePathToClassName(withoutExtension));
198+
return config.mainFactory().apply(ClassUtils.convertResourcePathToClassName(withoutExtension));
199+
}
200+
201+
record LanguageConfig(String mainDir, String testDir, Function<String, ? extends SourceChange> mainFactory,
202+
Function<String, ? extends SourceChange> testFactory) {
203+
204+
static final LanguageConfig JAVA = new LanguageConfig(JavaSourceChange.STANDARD_SOURCE_DIRECTORY,
205+
JavaSourceChange.STANDARD_TEST_SOURCE_DIRECTORY, JavaSourceChange::new, JavaTestSourceChange::new);
206+
207+
static final LanguageConfig KOTLIN = new LanguageConfig(KotlinSourceChange.STANDARD_SOURCE_DIRECTORY,
208+
KotlinSourceChange.STANDARD_TEST_SOURCE_DIRECTORY, KotlinSourceChange::new, KotlinTestSourceChange::new);
196209
}
197210

198211
/**
199212
* A change to a source file.
200213
*
201214
* @author Oliver Drotbohm
202215
*/
203-
sealed interface SourceChange extends Change permits JavaSourceChange, JavaTestSourceChange {
216+
sealed interface SourceChange extends Change
217+
permits KotlinSourceChange, KotlinTestSourceChange, JavaSourceChange, JavaTestSourceChange {
204218

205219
String fullyQualifiedClassName();
206220

@@ -243,7 +257,22 @@ public final String toString() {
243257
* @author David Bilge
244258
* @author Oliver Drotbohm
245259
*/
246-
record JavaTestSourceChange(String fullyQualifiedClassName) implements SourceChange {}
260+
record JavaTestSourceChange(String fullyQualifiedClassName) implements SourceChange {
261+
}
262+
263+
/**
264+
* A change in a Kotlin source file.
265+
*/
266+
record KotlinSourceChange(String fullyQualifiedClassName) implements SourceChange {
267+
private static final String STANDARD_SOURCE_DIRECTORY = "src/main/kotlin";
268+
private static final String STANDARD_TEST_SOURCE_DIRECTORY = "src/test/kotlin";
269+
}
270+
271+
/**
272+
* A change in a Kotlin test source file.
273+
*/
274+
record KotlinTestSourceChange(String fullyQualifiedClassName) implements SourceChange {
275+
}
247276

248277
/**
249278
* Some arbitrary file change.

spring-modulith-junit/src/main/java/org/springframework/modulith/junit/diff/ModifiedFile.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ public boolean isJavaSource() {
3737
return "java".equalsIgnoreCase(StringUtils.getFilenameExtension(path));
3838
}
3939

40+
/**
41+
* Returns whether the modified file is Kotlin source file.
42+
*/
43+
public boolean isKotlinSource() {
44+
return "kt".equalsIgnoreCase(StringUtils.getFilenameExtension(path));
45+
}
46+
4047
public static Stream<ModifiedFile> of(String... paths) {
4148
return Arrays.stream(paths).map(ModifiedFile::new);
4249
}

spring-modulith-junit/src/test/java/org/springframework/modulith/junit/ChangesUnitTests.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import org.junit.jupiter.api.TestFactory;
2525
import org.springframework.modulith.junit.Changes.Change.JavaSourceChange;
2626
import org.springframework.modulith.junit.Changes.Change.JavaTestSourceChange;
27+
import org.springframework.modulith.junit.Changes.Change.KotlinSourceChange;
28+
import org.springframework.modulith.junit.Changes.Change.KotlinTestSourceChange;
2729
import org.springframework.modulith.junit.Changes.Change.OtherFileChange;
2830
import org.springframework.modulith.junit.diff.ModifiedFile;
2931

@@ -73,6 +75,8 @@ void shouldInterpredModifiedFilePathsCorrectly() {
7375
var modifiedFilePaths = Stream.of(
7476
"src/main/java/org/springframework/modulith/junit/Changes.java",
7577
"src/test/java/org/springframework/modulith/ChangesTest.java",
78+
"src/test/kotlin/org/springframework/modulith/KotlinServiceTest.kt",
79+
"src/main/kotlin/org/springframework/modulith/KotlinService.kt",
7680
"src/main/resources/META-INF/additional-spring-configuration-metadata.json")
7781
.map(ModifiedFile::new);
7882

@@ -84,6 +88,8 @@ void shouldInterpredModifiedFilePathsCorrectly() {
8488
assertThat(result).containsExactlyInAnyOrder(
8589
new JavaSourceChange("org.springframework.modulith.junit.Changes"),
8690
new JavaTestSourceChange("org.springframework.modulith.ChangesTest"),
91+
new KotlinTestSourceChange("org.springframework.modulith.KotlinServiceTest"),
92+
new KotlinSourceChange("org.springframework.modulith.KotlinService"),
8793
new OtherFileChange("src/main/resources/META-INF/additional-spring-configuration-metadata.json"));
8894
}
8995
}

0 commit comments

Comments
 (0)