Skip to content

Commit 7cdfcb4

Browse files
authored
Applied common Spotless Eclipse framework to JDT (#239)
Applied common Spotless Eclipse framework to JDT (see #234). Updated version and artifact ID as discussed in #226.
1 parent 263a03f commit 7cdfcb4

File tree

6 files changed

+158
-192
lines changed

6 files changed

+158
-192
lines changed

Diff for: _ext/eclipse-jdt/README.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
# spotless-eclipse
1+
# spotless-eclipse-jdt
22

3-
Eclipse is not available in a form which can be easily consumed by maven or gradle. To fix this, we publish Eclipse's formatter and all its dependencies, along with a small amount of glue code, into the `com.diffplug.gradle.spotless:spotless-eclipse` artifact.
3+
Eclipse JDT and its dependencies require a large amount of byte code.
4+
Hence they should not be directly be required by the Spotless, but only be requested in case
5+
they are configured by the Spotless configuration. Hence we publish Eclipse's formatter and all its dependencies, along with a small amount of glue code, into the `com.diffplug.gradle.spotless:spotless-eclipse-jdt` artifact.
46

57
To publish a new version, update the `_ext/eclipse-jdt/gradle.properties` appropriately and run this from the root directory:
68

Diff for: _ext/eclipse-jdt/build.gradle

+13-175
Original file line numberDiff line numberDiff line change
@@ -1,180 +1,18 @@
1-
plugins {
2-
// bintray uploading
3-
id 'com.jfrog.bintray' version '1.3.1'
4-
// p2 dependencies
5-
id 'com.diffplug.gradle.p2.asmaven' version '3.9.0'
6-
}
7-
8-
apply plugin: 'java'
9-
10-
// The dependencies we'd like to pull from Eclipse's p2 repositories
11-
def eclipseDeps = [
12-
// The dependencies we actually use
13-
'org.eclipse.jdt.core',
14-
'org.eclipse.text',
15-
16-
// Their transitives
17-
'org.eclipse.core.contenttype',
18-
'org.eclipse.core.jobs',
19-
'org.eclipse.core.runtime',
20-
'org.eclipse.core.resources',
21-
'org.eclipse.equinox.common',
22-
'org.eclipse.equinox.preferences',
23-
'org.eclipse.osgi'
24-
]
25-
// build a maven repo in our build folder containing these artifacts
26-
p2AsMaven {
27-
group 'p2', {
28-
repoEclipse jdt_VER_ECLIPSE
29-
eclipseDeps.each { p2.addIU(it) }
30-
eclipseDeps.each { p2.addIU(it + '.source') }
31-
}
32-
}
1+
apply from: rootProject.file('../gradle/java-setup.gradle')
2+
apply from: rootProject.file('../gradle/java-publish.gradle')
333

34-
configurations {
35-
embeddedJars // we will embed these into the binary artifact
36-
compile.extendsFrom(embeddedJars)
4+
ext {
5+
developers = [
6+
fvgh: [ name: 'Frank Vennemeyer', email: '[email protected]' ],
7+
nedtwigg: [ name: 'Ned Twigg', email: '[email protected]' ],
8+
]
379
}
3810

3911
dependencies {
40-
// add the eclipse jars to the embedded configuration
41-
eclipseDeps.each { embeddedJars "p2:${it}:+" }
42-
}
43-
44-
jar {
45-
// this embeds the eclipse jars into our "fat jar"
46-
from {
47-
configurations.embeddedJars.collect{ it.isDirectory() ? it : zipTree(it) }
12+
compile "com.diffplug.spotless:spotless-eclipse-base:${VER_SPOTLESS_ECLISPE_BASE}"
13+
compile("org.eclipse.jdt:org.eclipse.jdt.core:${VER_ECLIPSE_JDT_CORE}") {
14+
exclude group: 'org.eclipse.platform', module: 'org.eclipse.ant.core'
15+
exclude group: 'org.eclipse.platform', module: 'org.eclipse.core.expressions'
16+
exclude group: 'org.eclipse.platform', module: 'org.eclipse.core.filesystem'
4817
}
49-
// the eclipse jars are signed, and our fat jar breaks the signatures
50-
// so we've gotta be sure to filter out the signatures
51-
exclude 'META-INF/*.RSA'
52-
exclude 'META-INF/*.SF'
53-
}
54-
55-
apply plugin: 'eclipse'
56-
eclipse {
57-
classpath {
58-
downloadSources true
59-
downloadJavadoc true
60-
}
61-
}
62-
// always create fresh projects
63-
tasks.eclipse.dependsOn(cleanEclipse)
64-
65-
///////////
66-
// MAVEN //
67-
///////////
68-
apply plugin: 'maven-publish'
69-
70-
task sourcesJar(type: Jar) {
71-
classifier = 'sources'
72-
from sourceSets.main.allJava
73-
}
74-
75-
task javadocJar(type: Jar, dependsOn: javadoc) {
76-
classifier = 'javadoc'
77-
from javadoc.destinationDir
78-
}
79-
80-
////////////////
81-
// PUBLISHING //
82-
////////////////
83-
def isSnapshot = project.jdt_version.endsWith('-SNAPSHOT')
84-
// pulls the credentials from either the environment variable or gradle.properties
85-
def cred = {
86-
if (System.env[it] != null) {
87-
return System.env[it]
88-
} else if (project.hasProperty(it)) {
89-
return project[it]
90-
} else {
91-
return 'unknown_' + it
92-
}
93-
}
94-
95-
model {
96-
publishing {
97-
publications {
98-
mavenJava(MavenPublication) {
99-
artifact jar
100-
artifact sourcesJar
101-
artifact javadocJar
102-
103-
groupId project.jdt_group
104-
artifactId project.jdt_artifactId
105-
version project.jdt_version
106-
107-
pom.withXml {
108-
// remove the p2 dependencies because they are embedded
109-
// also remove 'com.diffplug' dependencies so that we can use spotless on its dependencies
110-
asNode().dependencies.'*'.each() {
111-
if (it.groupId.text() == 'p2') {
112-
it.parent().remove(it)
113-
}
114-
}
115-
// add MavenCentral requirements to the POM
116-
asNode().children().last() + {
117-
resolveStrategy = Closure.DELEGATE_FIRST
118-
name project.jdt_artifactId
119-
description project.jdt_description
120-
url "https://github.com/${project.jdt_org}/${project.name}"
121-
scm {
122-
url "https://github.com/${project.jdt_org}/${project.name}"
123-
connection "scm:git:git://github.com/${project.jdt_org}/${project.name}"
124-
developerConnection "scm:git:ssh:[email protected]/${project.jdt_org}/${project.name}"
125-
}
126-
licenses {
127-
license {
128-
name 'Eclipse Public License - v 1.0'
129-
url 'https://www.eclipse.org/legal/epl-v10.html'
130-
distribution 'repo'
131-
}
132-
}
133-
developers {
134-
developer {
135-
id 'nedtwigg'
136-
name 'Ned Twigg'
137-
138-
}
139-
}
140-
}
141-
}
142-
}
143-
}
144-
if (isSnapshot) {
145-
// upload snapshots to oss.sonatype.org
146-
repositories { maven {
147-
url = 'https://oss.sonatype.org/content/repositories/snapshots'
148-
credentials {
149-
username = cred('nexus_user')
150-
password = cred('nexus_pass')
151-
}
152-
} }
153-
}
154-
}
155-
}
156-
157-
if (!isSnapshot) {
158-
// upload releases to bintray and then mavenCentral
159-
bintray {
160-
user = cred('bintray_user')
161-
key = cred('bintray_pass')
162-
publications = ['mavenJava']
163-
publish = true
164-
pkg {
165-
repo = 'opensource'
166-
name = project.jdt_artifactId
167-
userOrg = project.jdt_org
168-
version {
169-
name = project.jdt_version
170-
mavenCentralSync {
171-
user = cred('nexus_user')
172-
password = cred('nexus_pass')
173-
}
174-
}
175-
}
176-
}
177-
178-
publish.dependsOn(bintrayUpload)
179-
bintrayUpload.dependsOn(['generatePomFileForMavenJavaPublication', jar, sourcesJar, javadocJar])
180-
}
18+
}

Diff for: _ext/eclipse-jdt/gradle.properties

+10-8
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
# jdt_ to ensure gradle.properties in project root doesn't clobber
2-
jdt_version=4.7.2
3-
jdt_artifactId=spotless-ext-eclipse-jdt
4-
jdt_description=Eclipse's formatter bundled for Spotless
1+
# Mayor/Minor versions correspond to the minimum Eclipse version supported/tested.
2+
# Patch version is incremented for backward compatible patches of this library.
3+
ext_version=4.8.0
4+
ext_artifactId=spotless-eclipse-jdt
5+
ext_description=Eclipse's JDT formatter bundled for Spotless
56

6-
jdt_org=diffplug
7-
jdt_group=com.diffplug.spotless
7+
ext_org=diffplug
8+
ext_group=com.diffplug.spotless
89

910
# Build requirements
10-
jdt_VER_JAVA=1.8
11+
ext_VER_JAVA=1.8
1112

1213
# Compile
13-
jdt_VER_ECLIPSE=4.7.2
14+
VER_ECLIPSE_JDT_CORE=[3.12.0,4.0.0[
15+
VER_SPOTLESS_ECLISPE_BASE=[3.0.0,4.0.0[

Diff for: _ext/eclipse-jdt/src/main/java/com/diffplug/gradle/spotless/java/eclipse/EclipseFormatterStepImpl.java renamed to _ext/eclipse-jdt/src/main/java/com/diffplug/spotless/extra/eclipse/java/EclipseJdtFormatterStepImpl.java

+14-7
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,35 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package com.diffplug.gradle.spotless.java.eclipse;
16+
package com.diffplug.spotless.extra.eclipse.java;
1717

1818
import java.util.Properties;
1919

20+
import org.eclipse.jdt.core.JavaCore;
2021
import org.eclipse.jdt.core.ToolFactory;
2122
import org.eclipse.jdt.core.formatter.CodeFormatter;
2223
import org.eclipse.jface.text.Document;
2324
import org.eclipse.jface.text.IDocument;
2425
import org.eclipse.text.edits.TextEdit;
2526

26-
/** Formatter step which calls out to the Eclipse formatter. */
27-
public class EclipseFormatterStepImpl {
27+
import com.diffplug.spotless.extra.eclipse.base.SpotlessEclipseFramework;
28+
29+
/** Formatter step which calls out to the Eclipse JDT formatter. */
30+
public class EclipseJdtFormatterStepImpl {
2831

2932
private final CodeFormatter codeFormatter;
3033

31-
public EclipseFormatterStepImpl(Properties settings) {
34+
public EclipseJdtFormatterStepImpl(Properties settings) throws Exception {
35+
SpotlessEclipseFramework.setup(
36+
plugins -> {
37+
plugins.applyDefault();
38+
plugins.add(new JavaCore());
39+
});
3240
this.codeFormatter = ToolFactory.createCodeFormatter(settings, ToolFactory.M_FORMAT_EXISTING);
3341
}
3442

35-
private static final String UNIX = "\n";
36-
3743
public String format(String raw) throws Exception {
38-
TextEdit edit = codeFormatter.format(CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.F_INCLUDE_COMMENTS, raw, 0, raw.length(), 0, UNIX);
44+
TextEdit edit = codeFormatter.format(CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.F_INCLUDE_COMMENTS, raw, 0, raw.length(), 0, SpotlessEclipseFramework.LINE_DELIMITER);
3945
if (edit == null) {
4046
throw new IllegalArgumentException("Invalid java syntax for formatting.");
4147
} else {
@@ -44,4 +50,5 @@ public String format(String raw) throws Exception {
4450
return doc.get();
4551
}
4652
}
53+
4754
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2016 DiffPlug
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+
/** Eclipse JDT based Spotless formatter */
17+
@ParametersAreNonnullByDefault
18+
package com.diffplug.spotless.extra.eclipse.java;
19+
20+
import javax.annotation.ParametersAreNonnullByDefault;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright 2016 DiffPlug
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.extra.eclipse.java;
17+
18+
import static com.diffplug.spotless.extra.eclipse.base.SpotlessEclipseFramework.LINE_DELIMITER;
19+
import static org.junit.Assert.*;
20+
21+
import java.util.Properties;
22+
import java.util.function.Consumer;
23+
24+
import org.eclipse.jdt.core.JavaCore;
25+
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
26+
import org.junit.Test;
27+
28+
/** Eclipse JDT wrapper integration tests */
29+
public class EclipseJdtFormatterStepImplTest {
30+
31+
private final static String UNFORMATTED = "package com.diffplug.gradle.spotless;\n" +
32+
"public class C {\n" +
33+
" static void hello() {" +
34+
" System.out.println(\"Hello World!\");\n" +
35+
" }\n" +
36+
"}".replaceAll("\n", LINE_DELIMITER);
37+
private final static String FORMATTED = "package com.diffplug.gradle.spotless;\n" +
38+
"public class C {\n" +
39+
"\tstatic void hello() {\n" +
40+
"\t\tSystem.out.println(\"Hello World!\");\n" +
41+
"\t}\n" +
42+
"}".replaceAll("\n", LINE_DELIMITER);
43+
44+
private final static String PRE_UNFORMATTED = "/**<pre>void f(){}</pre>*/\n".replaceAll("\n", LINE_DELIMITER);
45+
private final static String PRE_FORMATTED = "/**\n * <pre>\n * void f() {\n * }\n * </pre>\n */\n".replaceAll("\n", LINE_DELIMITER);
46+
47+
private final static String ILLEGAL_CHAR = Character.toString((char) 254);
48+
49+
@Test
50+
public void defaultFormat() throws Throwable {
51+
String output = format(UNFORMATTED, config -> {});
52+
assertEquals("Unexpected formatting with default preferences.",
53+
FORMATTED, output);
54+
}
55+
56+
@Test
57+
public void invalidFormat() throws Throwable {
58+
String output = format(FORMATTED.replace("void hello() {", "void hello() "), config -> {});
59+
assertTrue("Incomplete Java not formatted on best effort basis.", output.contains("void hello() " + LINE_DELIMITER));
60+
}
61+
62+
@Test
63+
public void invalidCharater() throws Throwable {
64+
String output = format(FORMATTED.replace("void hello() {", "void hello()" + ILLEGAL_CHAR + " {"), config -> {});
65+
assertTrue("Invalid charater not formatted on best effort basis.", output.contains("void hello()" + ILLEGAL_CHAR + " {" + LINE_DELIMITER));
66+
}
67+
68+
@Test
69+
public void invalidConfiguration() throws Throwable {
70+
String output = format(FORMATTED, config -> {
71+
config.setProperty(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE);
72+
config.setProperty(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, "noInteger");
73+
});
74+
assertEquals("Invalid indentation configuration not replaced by default value (4 spaces)",
75+
FORMATTED.replace("\t", " "), output);
76+
}
77+
78+
@Test
79+
/** Test that an internal code formatter can be created to format the Java code within HTML pre-tags. (see also Spotless issue #191) */
80+
public void internalCodeFormatter() throws Throwable {
81+
String output = format(PRE_UNFORMATTED + UNFORMATTED, config -> {
82+
config.setProperty(
83+
DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_HEADER,
84+
DefaultCodeFormatterConstants.TRUE);
85+
});
86+
assertEquals("Code within HTML <pre> tag not formatted.",
87+
PRE_FORMATTED + FORMATTED, output);
88+
}
89+
90+
private static String format(final String input, final Consumer<Properties> config) throws Exception {
91+
Properties properties = new Properties();
92+
config.accept(properties);
93+
EclipseJdtFormatterStepImpl formatter = new EclipseJdtFormatterStepImpl(properties);
94+
return formatter.format(input);
95+
}
96+
97+
}

0 commit comments

Comments
 (0)