diff --git a/spring-modulith-junit/src/main/java/org/springframework/modulith/junit/Changes.java b/spring-modulith-junit/src/main/java/org/springframework/modulith/junit/Changes.java index bdbf15799..20e8f76b2 100644 --- a/spring-modulith-junit/src/main/java/org/springframework/modulith/junit/Changes.java +++ b/spring-modulith-junit/src/main/java/org/springframework/modulith/junit/Changes.java @@ -161,38 +161,51 @@ sealed interface Change permits SourceChange, OtherFileChange { boolean hasOrigin(String nameOrPath); /** - * creates a new - * - * @param file - * @return + * Creates a change from a modified file */ static Change of(ModifiedFile file) { + boolean isJavaSource = file.isJavaSource(); - if (!file.isJavaSource()) { + if (!isJavaSource && !file.isKotlinSource()) { return new OtherFileChange(file.path()); } + var languageConfig = isJavaSource ? LanguageConfig.JAVA : LanguageConfig.KOTLIN; + return toSourceChange(file, languageConfig); + } + + private static Change toSourceChange(ModifiedFile file, LanguageConfig config) { var withoutExtension = StringUtils.stripFilenameExtension(file.path()); - var startOfMainDir = withoutExtension.indexOf(JavaSourceChange.STANDARD_SOURCE_DIRECTORY); - var startOfTestDir = withoutExtension.indexOf(JavaSourceChange.STANDARD_TEST_SOURCE_DIRECTORY); + var startOfMainDir = withoutExtension.indexOf(config.mainDir()); + var startOfTestDir = withoutExtension.indexOf(config.testDir()); if (startOfTestDir > -1 && (startOfMainDir < 0 || startOfTestDir < startOfMainDir)) { - var fullyQualifiedClassName = ClassUtils.convertResourcePathToClassName( - withoutExtension.substring(startOfTestDir + JavaSourceChange.STANDARD_TEST_SOURCE_DIRECTORY.length() + 1)); + var fullyQualifiedClassName = ClassUtils + .convertResourcePathToClassName(withoutExtension.substring(startOfTestDir + config.testDir().length() + 1)); - return new JavaTestSourceChange(fullyQualifiedClassName); + return config.testFactory().apply(fullyQualifiedClassName); } if (startOfMainDir > -1 && (startOfTestDir < 0 || startOfMainDir < startOfTestDir)) { - var fullyQualifiedClassName = ClassUtils.convertResourcePathToClassName( - withoutExtension.substring(startOfMainDir + JavaSourceChange.STANDARD_SOURCE_DIRECTORY.length() + 1)); + var fullyQualifiedClassName = ClassUtils + .convertResourcePathToClassName(withoutExtension.substring(startOfMainDir + config.mainDir().length() + 1)); - return new JavaSourceChange(fullyQualifiedClassName); + return config.mainFactory().apply(fullyQualifiedClassName); } - return new JavaSourceChange(ClassUtils.convertResourcePathToClassName(withoutExtension)); + return config.mainFactory().apply(ClassUtils.convertResourcePathToClassName(withoutExtension)); + } + + record LanguageConfig(String mainDir, String testDir, Function mainFactory, + Function testFactory) { + + static final LanguageConfig JAVA = new LanguageConfig(JavaSourceChange.STANDARD_SOURCE_DIRECTORY, + JavaSourceChange.STANDARD_TEST_SOURCE_DIRECTORY, JavaSourceChange::new, JavaTestSourceChange::new); + + static final LanguageConfig KOTLIN = new LanguageConfig(KotlinSourceChange.STANDARD_SOURCE_DIRECTORY, + KotlinSourceChange.STANDARD_TEST_SOURCE_DIRECTORY, KotlinSourceChange::new, KotlinTestSourceChange::new); } /** @@ -200,7 +213,8 @@ static Change of(ModifiedFile file) { * * @author Oliver Drotbohm */ - sealed interface SourceChange extends Change permits JavaSourceChange, JavaTestSourceChange { + sealed interface SourceChange extends Change + permits KotlinSourceChange, KotlinTestSourceChange, JavaSourceChange, JavaTestSourceChange { String fullyQualifiedClassName(); @@ -243,7 +257,22 @@ public final String toString() { * @author David Bilge * @author Oliver Drotbohm */ - record JavaTestSourceChange(String fullyQualifiedClassName) implements SourceChange {} + record JavaTestSourceChange(String fullyQualifiedClassName) implements SourceChange { + } + + /** + * A change in a Kotlin source file. + */ + record KotlinSourceChange(String fullyQualifiedClassName) implements SourceChange { + private static final String STANDARD_SOURCE_DIRECTORY = "src/main/kotlin"; + private static final String STANDARD_TEST_SOURCE_DIRECTORY = "src/test/kotlin"; + } + + /** + * A change in a Kotlin test source file. + */ + record KotlinTestSourceChange(String fullyQualifiedClassName) implements SourceChange { + } /** * Some arbitrary file change. diff --git a/spring-modulith-junit/src/main/java/org/springframework/modulith/junit/diff/ModifiedFile.java b/spring-modulith-junit/src/main/java/org/springframework/modulith/junit/diff/ModifiedFile.java index 73a0689be..ef45988bd 100644 --- a/spring-modulith-junit/src/main/java/org/springframework/modulith/junit/diff/ModifiedFile.java +++ b/spring-modulith-junit/src/main/java/org/springframework/modulith/junit/diff/ModifiedFile.java @@ -37,6 +37,13 @@ public boolean isJavaSource() { return "java".equalsIgnoreCase(StringUtils.getFilenameExtension(path)); } + /** + * Returns whether the modified file is Kotlin source file. + */ + public boolean isKotlinSource() { + return "kt".equalsIgnoreCase(StringUtils.getFilenameExtension(path)); + } + public static Stream of(String... paths) { return Arrays.stream(paths).map(ModifiedFile::new); } diff --git a/spring-modulith-junit/src/test/java/org/springframework/modulith/junit/ChangesUnitTests.java b/spring-modulith-junit/src/test/java/org/springframework/modulith/junit/ChangesUnitTests.java index b42f8df9e..d7a6d7e57 100644 --- a/spring-modulith-junit/src/test/java/org/springframework/modulith/junit/ChangesUnitTests.java +++ b/spring-modulith-junit/src/test/java/org/springframework/modulith/junit/ChangesUnitTests.java @@ -24,6 +24,8 @@ import org.junit.jupiter.api.TestFactory; import org.springframework.modulith.junit.Changes.Change.JavaSourceChange; import org.springframework.modulith.junit.Changes.Change.JavaTestSourceChange; +import org.springframework.modulith.junit.Changes.Change.KotlinSourceChange; +import org.springframework.modulith.junit.Changes.Change.KotlinTestSourceChange; import org.springframework.modulith.junit.Changes.Change.OtherFileChange; import org.springframework.modulith.junit.diff.ModifiedFile; @@ -73,6 +75,8 @@ void shouldInterpredModifiedFilePathsCorrectly() { var modifiedFilePaths = Stream.of( "src/main/java/org/springframework/modulith/junit/Changes.java", "src/test/java/org/springframework/modulith/ChangesTest.java", + "src/test/kotlin/org/springframework/modulith/KotlinServiceTest.kt", + "src/main/kotlin/org/springframework/modulith/KotlinService.kt", "src/main/resources/META-INF/additional-spring-configuration-metadata.json") .map(ModifiedFile::new); @@ -84,6 +88,8 @@ void shouldInterpredModifiedFilePathsCorrectly() { assertThat(result).containsExactlyInAnyOrder( new JavaSourceChange("org.springframework.modulith.junit.Changes"), new JavaTestSourceChange("org.springframework.modulith.ChangesTest"), + new KotlinTestSourceChange("org.springframework.modulith.KotlinServiceTest"), + new KotlinSourceChange("org.springframework.modulith.KotlinService"), new OtherFileChange("src/main/resources/META-INF/additional-spring-configuration-metadata.json")); } }