Skip to content

Commit

Permalink
Add FindRepository and AddSettingsPluginRepository recipes for Gradle (
Browse files Browse the repository at this point in the history
  • Loading branch information
shanman190 authored Apr 25, 2023
1 parent 712b5d3 commit d0f2b78
Show file tree
Hide file tree
Showing 7 changed files with 705 additions and 14 deletions.
28 changes: 28 additions & 0 deletions rewrite-gradle/src/main/groovy/RepositoryHandler.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2023 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.IvyArtifactRepository
import org.gradle.api.artifacts.repositories.MavenArtifactRepository

interface RepositoryHandlerSpec extends RepositoryHandler {
MavenArtifactRepository maven(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=MavenArtifactRepositorySpec) Closure closure)

IvyArtifactRepository ivy(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=IvyArtifactRepository) Closure closure)
}

interface MavenArtifactRepositorySpec extends MavenArtifactRepository {
void url(Object url)
}
21 changes: 7 additions & 14 deletions rewrite-gradle/src/main/groovy/RewriteGradleProject.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,10 @@ import org.gradle.api.Task
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.artifacts.dsl.DependencyHandler
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.IvyArtifactRepository
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
import org.gradle.api.file.FileCollection
import org.gradle.api.file.FileTree
import org.gradle.api.file.FileTreeElement
import org.gradle.api.initialization.dsl.ScriptHandler
import org.gradle.api.specs.Spec
import org.gradle.api.tasks.testing.TestFilter
import org.gradle.api.tasks.testing.TestFrameworkOptions
Expand All @@ -37,8 +35,6 @@ import org.gradle.api.tasks.testing.testng.TestNGOptions
import org.gradle.process.JavaForkOptions
import org.gradle.process.ProcessForkOptions



interface DependencyHandlerSpec extends DependencyHandler {
Dependency annotationProcessor(String dependencyNotation)
Dependency annotationProcessor(String dependencyNotation, @DelegatesTo(strategy=Closure.DELEGATE_ONLY, value= ModuleDependency) Closure closure)
Expand Down Expand Up @@ -94,15 +90,6 @@ interface DependencyHandlerSpec extends DependencyHandler {
Dependency testRuntimeOnly(Map<String, String> dependencyNotation, @DelegatesTo(strategy=Closure.DELEGATE_ONLY, value= ModuleDependency) Closure closure)
}

interface RepositoryHandlerSpec extends RepositoryHandler {
MavenArtifactRepository maven(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=MavenArtifactRepositorySpec) Closure closure)
IvyArtifactRepository ivy(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=IvyArtifactRepository) Closure closure)
}

interface MavenArtifactRepositorySpec extends MavenArtifactRepository {
void url(Object url)
}

interface RewriteTestSpec {
File getWorkingDir()
void setWorkingDir(File dir)
Expand Down Expand Up @@ -183,10 +170,16 @@ interface RewriteTestSpec {
void filter(Action<TestFilter> action)
}

interface ScriptHandlerSpec extends ScriptHandler {
void repositories(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=RepositoryHandlerSpec) Closure cl)
void dependencies(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=DependencyHandlerSpec) Closure cl)
}

abstract class RewriteGradleProject extends groovy.lang.Script implements Project {
Map ext;

// It would be more correct for ext to delegate to ExtraPropertiesExtension, but StaticTypeCheckingVisitor has problems with that
abstract void buildscript(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=ScriptHandlerSpec) Closure cl)
abstract void ext(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=Map) Closure cl)
abstract void dependencies(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=DependencyHandlerSpec) Closure cl)
abstract void plugins(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=PluginSpec) Closure cl)
Expand Down
5 changes: 5 additions & 0 deletions rewrite-gradle/src/main/groovy/RewriteSettings.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,16 @@ import com.gradle.enterprise.gradleplugin.GradleEnterpriseExtension
import com.gradle.scan.plugin.BuildScanExtension
import org.gradle.api.initialization.Settings

interface PluginManagementSpec extends org.gradle.plugin.management.PluginManagementSpec {
void repositories(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=RepositoryHandlerSpec) Closure cl)
}

interface GradleEnterpriseSpec extends GradleEnterpriseExtension {
void buildScan(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=BuildScanExtension) Closure cl);
}

abstract class RewriteSettings extends groovy.lang.Script implements Settings {
abstract void pluginManagement(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=PluginManagementSpec) Closure cl)
abstract void plugins(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=PluginSpec) Closure cl)
abstract void gradleEnterprise(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=GradleEnterpriseSpec) Closure cl)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* Copyright 2023 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openrewrite.gradle.plugins;

import lombok.EqualsAndHashCode;
import lombok.Value;
import org.openrewrite.*;
import org.openrewrite.gradle.GradleParser;
import org.openrewrite.gradle.IsSettingsGradle;
import org.openrewrite.gradle.search.FindRepository;
import org.openrewrite.groovy.GroovyIsoVisitor;
import org.openrewrite.groovy.tree.G;
import org.openrewrite.internal.ListUtils;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.Space;
import org.openrewrite.java.tree.Statement;

import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Value
@EqualsAndHashCode(callSuper = true)
public class AddSettingsPluginRepository extends Recipe {
private static final GradleParser GRADLE_PARSER = GradleParser.builder().build();

@Option(displayName = "Type",
description = "The type of the artifact repository",
example = "maven")
String type;

@Option(displayName = "URL",
description = "The url of the artifact repository",
example = "https://repo.spring.io")
String url;

@Override
public String getDisplayName() {
return "Add a Gradle settings repository";
}

@Override
public String getDescription() {
return "Add a Gradle settings repository to `settings.gradle(.kts)`.";
}

@Override
protected TreeVisitor<?, ExecutionContext> getSingleSourceApplicableTest() {
return new IsSettingsGradle<>();
}

@Override
protected TreeVisitor<?, ExecutionContext> getVisitor() {
return new GroovyIsoVisitor<ExecutionContext>() {
@Override
public G.CompilationUnit visitCompilationUnit(G.CompilationUnit cu, ExecutionContext ctx) {
if (cu == new FindRepository(type, url, FindRepository.Purpose.Plugin).getVisitor().visit(cu, ctx)) {
G.CompilationUnit g = super.visitCompilationUnit(cu, ctx);

J.MethodInvocation pluginManagement = generatePluginManagementBlock(ctx);

List<Statement> statements = new ArrayList<>(g.getStatements());
if (statements.isEmpty()) {
statements.add(pluginManagement);
} else {
Statement statement = statements.get(0);
if (statement instanceof J.MethodInvocation
&& ((J.MethodInvocation) statement).getSimpleName().equals("pluginManagement")) {
J.MethodInvocation m = (J.MethodInvocation) statement;
m = m.withArguments(ListUtils.mapFirst(m.getArguments(), arg -> {
if (arg instanceof J.Lambda && ((J.Lambda) arg).getBody() instanceof J.Block) {
J.Lambda lambda = (J.Lambda) arg;
J.Block block = (J.Block) lambda.getBody();
return lambda.withBody(block.withStatements(ListUtils.map(block.getStatements(), statement2 -> {
if ((statement2 instanceof J.MethodInvocation && ((J.MethodInvocation) statement2).getSimpleName().equals("repositories"))
|| (statement2 instanceof J.Return && ((J.Return) statement2).getExpression() instanceof J.MethodInvocation && ((J.MethodInvocation) ((J.Return) statement2).getExpression()).getSimpleName().equals("repositories"))) {
J.MethodInvocation m2 = (J.MethodInvocation) (statement2 instanceof J.Return ? ((J.Return) statement2).getExpression() : statement2);
return m2.withArguments(ListUtils.mapFirst(m2.getArguments(), arg2 -> {
if (arg2 instanceof J.Lambda && ((J.Lambda) arg2).getBody() instanceof J.Block) {
J.Lambda lambda2 = (J.Lambda) arg2;
J.Block block2 = (J.Block) lambda2.getBody();
return lambda2.withBody(block2.withStatements(ListUtils.concat(block2.getStatements(), extractRepository(pluginManagement))));
}
return arg2;
}));
}
return statement2;
})));
}
return arg;
}));
statements.set(0, m);
} else {
statements.add(0, pluginManagement);
statements.set(1, statements.get(1).withPrefix(Space.format("\n\n")));
}
}

return autoFormat(g.withStatements(statements), ctx);
}

return cu;
}

private J.MethodInvocation generatePluginManagementBlock(ExecutionContext ctx) {
String code;
if (url == null) {
code = "pluginManagement {" +
" repositories {" +
" " + type + "()" +
" }" +
"}";
} else {
code = "pluginManagement {" +
" repositories {" +
" " + type + " {" +
" url = \"" + url + "\"" +
" }" +
" }" +
"}";
}

return (J.MethodInvocation) GRADLE_PARSER.parseInputs(Collections.singletonList(Parser.Input.fromString(Paths.get("settings.gradle"), code)), null, ctx)
.get(0).getStatements().get(0);
}

private J.MethodInvocation extractRepository(J.MethodInvocation pluginManagement) {
J.MethodInvocation repositories = (J.MethodInvocation) ((J.Return) ((J.Block) ((J.Lambda) pluginManagement.getArguments().get(0)).getBody()).getStatements().get(0)).getExpression();
return (J.MethodInvocation) ((J.Return) ((J.Block) ((J.Lambda) repositories.getArguments().get(0)).getBody()).getStatements().get(0)).getExpression();
}
};
}
}
Loading

0 comments on commit d0f2b78

Please sign in to comment.