Skip to content

Commit cf434f2

Browse files
committed
Start with Cleanthat Java refactorer
1 parent 5302984 commit cf434f2

File tree

2 files changed

+196
-0
lines changed

2 files changed

+196
-0
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2021-2023 Solven
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless.glue.java;
17+
18+
import com.diffplug.spotless.FormatterFunc;
19+
import eu.solven.cleanthat.config.pojo.CleanthatEngineProperties;
20+
import eu.solven.cleanthat.engine.java.refactorer.JavaRefactorer;
21+
import eu.solven.cleanthat.engine.java.refactorer.JavaRefactorerProperties;
22+
import eu.solven.cleanthat.formatter.LineEnding;
23+
import eu.solven.cleanthat.formatter.PathAndContent;
24+
import java.nio.file.Paths;
25+
import java.util.Arrays;
26+
import java.util.Collections;
27+
import java.util.List;
28+
29+
public class JavaCleanthatRefactorerFunc implements FormatterFunc {
30+
private List<String> included;
31+
private List<String> excluded;
32+
33+
public JavaCleanthatRefactorerFunc(List<String> included, List<String> excluded) {
34+
this.included = included == null ? Collections.emptyList() : included;
35+
this.excluded = excluded == null ? Collections.emptyList() : excluded;
36+
}
37+
38+
public JavaCleanthatRefactorerFunc() {
39+
this(Arrays.asList(JavaRefactorerProperties.WILDCARD), Arrays.asList());
40+
}
41+
42+
@Override
43+
public String apply(String input) throws Exception {
44+
JavaRefactorerProperties refactorerProperties = new JavaRefactorerProperties();
45+
46+
refactorerProperties.setIncluded(included);
47+
refactorerProperties.setExcluded(excluded);
48+
49+
JavaRefactorer refactorer =
50+
new JavaRefactorer(CleanthatEngineProperties.builder().build(), refactorerProperties);
51+
52+
// Spotless calls steps always with LF eol.
53+
return refactorer.doFormat(new PathAndContent(Paths.get("fake"), input), LineEnding.LF);
54+
}
55+
56+
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* Copyright 2016-2023 Solven
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.diffplug.spotless.java;
17+
18+
import com.diffplug.spotless.FormatterFunc;
19+
import com.diffplug.spotless.FormatterStep;
20+
import com.diffplug.spotless.JarState;
21+
import com.diffplug.spotless.Jvm;
22+
import com.diffplug.spotless.Provisioner;
23+
import java.io.IOException;
24+
import java.io.Serializable;
25+
import java.lang.reflect.Constructor;
26+
import java.lang.reflect.Method;
27+
import java.util.List;
28+
import java.util.Objects;
29+
30+
/**
31+
* Enables CleanThat as a SpotLess step. This may be moved to Spotless own repo
32+
* (https://github.com/diffplug/spotless/tree/main/lib)
33+
*
34+
* @author Benoit Lacelle
35+
*/
36+
// https://github.com/diffplug/spotless/blob/main/CONTRIBUTING.md#how-to-add-a-new-formatterstep
37+
public final class CleanthatStepFactory {
38+
39+
private static final String NAME = "cleanthat";
40+
private static final String MAVEN_COORDINATE = "io.github.solven-eu.cleanthat:java:";
41+
42+
private static final Jvm.Support<String> JVM_SUPPORT = Jvm.<String>support(NAME).add(8, "2.0");
43+
44+
// prevent direct instantiation
45+
private CleanthatStepFactory() {
46+
}
47+
48+
/** Creates a step which formats everything - code, import order, and unused imports. */
49+
public static FormatterStep create(Provisioner provisioner) {
50+
return create(defaultVersion(), provisioner);
51+
}
52+
53+
/** Creates a step which formats everything - code, import order, and unused imports. */
54+
public static FormatterStep create(String version, Provisioner provisioner) {
55+
return create(MAVEN_COORDINATE, version, defaultExcluded(), defaultIncluded(), provisioner);
56+
}
57+
58+
private static List<String> defaultExcluded() {
59+
return List.of();
60+
}
61+
62+
private static List<String> defaultIncluded() {
63+
return List.of("*");
64+
}
65+
66+
/** Creates a step which formats everything - groupArtifact, code, import order, and unused imports. */
67+
public static FormatterStep create(String groupArtifact,
68+
String version,
69+
List<String> excluded,
70+
List<String> included,
71+
Provisioner provisioner) {
72+
Objects.requireNonNull(groupArtifact, "groupArtifact");
73+
if (groupArtifact.chars().filter(ch -> ch == ':').count() != 1) {
74+
throw new IllegalArgumentException("groupArtifact must be in the form 'groupId:artifactId'");
75+
}
76+
Objects.requireNonNull(version, "version");
77+
Objects.requireNonNull(provisioner, "provisioner");
78+
return FormatterStep.createLazy(NAME,
79+
() -> new JavaRulesState(NAME, groupArtifact, version, excluded, included, provisioner),
80+
JavaRulesState::createFormat);
81+
}
82+
83+
/** Get default formatter version */
84+
public static String defaultVersion() {
85+
return JVM_SUPPORT.getRecommendedFormatterVersion();
86+
}
87+
88+
static final class JavaRulesState implements Serializable {
89+
private static final long serialVersionUID = 1L;
90+
91+
final JarState jarState;
92+
final String stepName;
93+
final String version;
94+
95+
final List<String> included;
96+
final List<String> excluded;
97+
98+
JavaRulesState(String stepName, String version, Provisioner provisioner) throws IOException {
99+
this(stepName, MAVEN_COORDINATE, version, defaultExcluded(), defaultIncluded(), provisioner);
100+
}
101+
102+
JavaRulesState(String stepName,
103+
String groupArtifact,
104+
String version,
105+
List<String> included,
106+
List<String> excluded,
107+
Provisioner provisioner) throws IOException {
108+
JVM_SUPPORT.assertFormatterSupported(version);
109+
// ModuleHelper.doOpenInternalPackagesIfRequired();
110+
this.jarState = JarState.from(groupArtifact + ":" + version, provisioner);
111+
this.stepName = stepName;
112+
this.version = version;
113+
114+
this.included = included;
115+
this.excluded = excluded;
116+
}
117+
118+
@SuppressWarnings("PMD.UseProperClassLoader")
119+
FormatterFunc createFormat() {
120+
ClassLoader classLoader = jarState.getClassLoader();
121+
122+
Object formatter;
123+
Method formatterMethod;
124+
try {
125+
Class<?> formatterClazz =
126+
classLoader.loadClass("com.diffplug.spotless.glue.java.JavaCleanthatRefactoringFunc");
127+
Constructor<?> formatterConstructor = formatterClazz.getConstructor(List.class, List.class);
128+
129+
formatter = formatterConstructor.newInstance(included, excluded);
130+
formatterMethod = formatterClazz.getMethod("apply", String.class);
131+
} catch (ReflectiveOperationException e) {
132+
throw new IllegalStateException("Issue executing the formatter", e);
133+
}
134+
return JVM_SUPPORT.suggestLaterVersionOnError(version, input -> {
135+
return (String) formatterMethod.invoke(formatter, input);
136+
});
137+
}
138+
139+
}
140+
}

0 commit comments

Comments
 (0)