Skip to content

Commit

Permalink
Gradle Kotlin DSL (#5122)
Browse files Browse the repository at this point in the history
* Initial import of rewrite-kotlin

* Fix package name discovery given Groovy and Kotlin both use optional semicolons

* Add KotlinParser for build and settings scripts

* remove local rewrite-kotlin

* Add base KotlinParser to the GradleParser

---------

Co-authored-by: Knut Wannheden <[email protected]>
  • Loading branch information
shanman190 and knutwannheden authored Mar 7, 2025
1 parent bd9c7df commit 2b1ab68
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 12 deletions.
1 change: 1 addition & 0 deletions rewrite-gradle/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ dependencies {
api(project(":rewrite-groovy")) {
exclude("org.codehaus.groovy", "groovy")
}
api(project(":rewrite-kotlin"))
api(project(":rewrite-maven"))
api("org.jetbrains:annotations:latest.release")
compileOnly(project(":rewrite-test"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.openrewrite.SourceFile;
import org.openrewrite.groovy.GroovyParser;
import org.openrewrite.groovy.tree.G;
import org.openrewrite.kotlin.tree.K;
import org.openrewrite.test.SourceSpec;
import org.openrewrite.test.SourceSpecs;
import org.openrewrite.test.UncheckedConsumer;
Expand Down Expand Up @@ -101,6 +102,31 @@ public static SourceSpecs buildGradle(@Language("groovy") @Nullable String befor
return gradle;
}

public static SourceSpecs buildGradleKts(@Language("kotlin") @Nullable String before) {
return buildGradleKts(before, s -> {
});
}

public static SourceSpecs buildGradleKts(@Language("kotlin") @Nullable String before, Consumer<SourceSpec<K.CompilationUnit>> spec) {
SourceSpec<K.CompilationUnit> gradle = new SourceSpec<>(K.CompilationUnit.class, "gradle", gradleParser, before, null);
gradle.path(Paths.get("build.gradle.kts"));
spec.accept(gradle);
return gradle;
}

public static SourceSpecs buildGradleKts(@Language("kotlin") @Nullable String before, @Language("kotlin") @Nullable String after) {
return buildGradleKts(before, after, s -> {
});
}

public static SourceSpecs buildGradleKts(@Language("kotlin") @Nullable String before, @Language("kotlin") @Nullable String after,
Consumer<SourceSpec<K.CompilationUnit>> spec) {
SourceSpec<K.CompilationUnit> gradle = new SourceSpec<>(K.CompilationUnit.class, "gradle", gradleParser, before, s -> after);
gradle.path("build.gradle.kts");
spec.accept(gradle);
return gradle;
}

public static SourceSpecs settingsGradle(@Language("groovy") @Nullable String before) {
return settingsGradle(before, s -> {
});
Expand All @@ -125,4 +151,29 @@ public static SourceSpecs settingsGradle(@Language("groovy") @Nullable String be
spec.accept(gradle);
return gradle;
}

public static SourceSpecs settingsGradleKts(@Language("kotlin") @Nullable String before) {
return settingsGradleKts(before, s -> {
});
}

public static SourceSpecs settingsGradleKts(@Language("kotlin") @Nullable String before, Consumer<SourceSpec<K.CompilationUnit>> spec) {
SourceSpec<K.CompilationUnit> gradle = new SourceSpec<>(K.CompilationUnit.class, "gradle", gradleParser, before, null);
gradle.path(Paths.get("settings.gradle.kts"));
spec.accept(gradle);
return gradle;
}

public static SourceSpecs settingsGradleKts(@Language("kotlin") @Nullable String before, @Language("kotlin") @Nullable String after) {
return settingsGradleKts(before, after, s -> {
});
}

public static SourceSpecs settingsGradleKts(@Language("kotlin") @Nullable String before, @Language("kotlin") @Nullable String after,
Consumer<SourceSpec<K.CompilationUnit>> spec) {
SourceSpec<K.CompilationUnit> gradle = new SourceSpec<>(K.CompilationUnit.class, "gradle", gradleParser, before, s -> after);
gradle.path("settings.gradle.kts");
spec.accept(gradle);
return gradle;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.openrewrite.groovy.GroovyParser;
import org.openrewrite.groovy.tree.G;
import org.openrewrite.java.JavaParser;
import org.openrewrite.kotlin.KotlinParser;

import java.nio.file.Path;
import java.util.Collection;
Expand All @@ -38,56 +39,87 @@ public class GradleParser implements Parser {
private final GradleParser.Builder base;

private Collection<Path> defaultClasspath;
private GroovyParser buildParser;
private GroovyParser settingsParser;
private GroovyParser groovyBuildParser;
private GroovyParser groovySettingsParser;
private KotlinParser kotlinBuildParser;
private KotlinParser kotlinSettingsParser;

@Override
public Stream<SourceFile> parseInputs(Iterable<Input> sources, @Nullable Path relativeTo, ExecutionContext ctx) {
if (buildParser == null) {
if (groovyBuildParser == null) {
Collection<Path> buildscriptClasspath = base.buildscriptClasspath;
if (buildscriptClasspath == null) {
if (defaultClasspath == null) {
defaultClasspath = loadDefaultClasspath();
}
buildscriptClasspath = defaultClasspath;
}
buildParser = GroovyParser.builder(base.groovyParser)
groovyBuildParser = GroovyParser.builder(base.groovyParser)
.classpath(buildscriptClasspath)
.compilerCustomizers(
new DefaultImportsCustomizer(),
config -> config.setScriptBaseClass("RewriteGradleProject")
)
.build();
}
if (settingsParser == null) {
if (kotlinBuildParser == null) {
Collection<Path> buildscriptClasspath = base.buildscriptClasspath;
if (buildscriptClasspath == null) {
if (defaultClasspath == null) {
defaultClasspath = loadDefaultClasspath();
}
buildscriptClasspath = defaultClasspath;
}
kotlinBuildParser = KotlinParser.builder(base.kotlinParser)
.classpath(buildscriptClasspath)
.build();
}
if (groovySettingsParser == null) {
Collection<Path> settingsClasspath = base.settingsClasspath;
if (settingsClasspath == null) {
if (defaultClasspath == null) {
defaultClasspath = loadDefaultClasspath();
}
settingsClasspath = defaultClasspath;
}
settingsParser = GroovyParser.builder(base.groovyParser)
groovySettingsParser = GroovyParser.builder(base.groovyParser)
.classpath(settingsClasspath)
.compilerCustomizers(
new DefaultImportsCustomizer(),
config -> config.setScriptBaseClass("RewriteSettings")
)
.build();
}
if (kotlinSettingsParser == null) {
Collection<Path> settingsClasspath = base.settingsClasspath;
if (settingsClasspath == null) {
if (defaultClasspath == null) {
loadDefaultClasspath();
}
settingsClasspath = defaultClasspath;
}
kotlinSettingsParser = KotlinParser.builder(base.kotlinParser)
.classpath(settingsClasspath)
.build();
}

return StreamSupport.stream(sources.spliterator(), false)
.flatMap(source -> {
if (source.getPath().endsWith("settings.gradle")) {
return settingsParser.parseInputs(Collections.singletonList(source), relativeTo, ctx);
Path sourcePath = source.getPath();
if (sourcePath.endsWith("settings.gradle.kts")) {
return kotlinSettingsParser.parseInputs(Collections.singletonList(source), relativeTo, ctx);
} else if (sourcePath.endsWith("settings.gradle")) {
return groovySettingsParser.parseInputs(Collections.singletonList(source), relativeTo, ctx);
} else if (sourcePath.toString().endsWith(".gradle.kts")) {
return kotlinBuildParser.parseInputs(Collections.singletonList(source), relativeTo, ctx);
}
return buildParser.parseInputs(Collections.singletonList(source), relativeTo, ctx);
return groovyBuildParser.parseInputs(Collections.singletonList(source), relativeTo, ctx);
});
}

@Override
public boolean accept(Path path) {
return path.toString().endsWith(".gradle");
return path.toString().endsWith(".gradle") || path.toString().endsWith(".gradle.kts");
}

@Override
Expand All @@ -101,6 +133,7 @@ public static Builder builder() {

public static class Builder extends Parser.Builder {
protected GroovyParser.Builder groovyParser = GroovyParser.builder();
protected KotlinParser.Builder kotlinParser = KotlinParser.builder();

@Nullable
private Collection<Path> buildscriptClasspath;
Expand All @@ -117,6 +150,11 @@ public Builder groovyParser(GroovyParser.Builder groovyParser) {
return this;
}

public Builder kotlinParser(KotlinParser.Builder kotlinParser) {
this.kotlinParser = kotlinParser;
return this;
}

public Builder buildscriptClasspath(Collection<Path> classpath) {
this.buildscriptClasspath = classpath;
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
import org.openrewrite.test.RewriteTest;

import static org.assertj.core.api.Assertions.assertThat;
import static org.openrewrite.gradle.Assertions.buildGradle;
import static org.openrewrite.gradle.Assertions.settingsGradle;
import static org.openrewrite.gradle.Assertions.*;

class GradleParserTest implements RewriteTest {

Expand Down Expand Up @@ -188,4 +187,21 @@ void handleImportsThatArentTheFirstStatement() {
)
);
}

@Test
void kotlinDsl() {
rewriteRun(
buildGradleKts(
"""
plugins {
`java-library`
}
repositories {
mavenCentral()
}
"""
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,10 @@ public static Builder builder() {
return new Builder();
}

public static Builder builder(Builder base) {
return new Builder(base);
}

@SuppressWarnings("unused")
public static class Builder extends Parser.Builder {
@Nullable
Expand All @@ -270,6 +274,15 @@ public Builder() {
super(K.CompilationUnit.class);
}

public Builder(Builder base) {
super(K.CompilationUnit.class);
this.classpath = base.classpath;
this.artifactNames = base.artifactNames;
this.typeCache = base.typeCache;
this.logCompilationWarningsAndErrors = base.logCompilationWarningsAndErrors;
this.styles.addAll(base.styles);
}

public Builder logCompilationWarningsAndErrors(boolean logCompilationWarningsAndErrors) {
this.logCompilationWarningsAndErrors = logCompilationWarningsAndErrors;
return this;
Expand Down

0 comments on commit 2b1ab68

Please sign in to comment.