Skip to content

Commit 5070536

Browse files
authored
Merge pull request #328 from matthiasbalke/issue-326-antlr4
[WIP] Add ANTLR4 support
2 parents f8198b5 + 60b9805 commit 5070536

File tree

16 files changed

+459
-1
lines changed

16 files changed

+459
-1
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
1515
### Added
1616
* `prettier` will now autodetect the parser (and formatter) to use based on the filename, unless you override this using `config` or `configFile` with the option `parser` or `filepath`. ([#620](https://github.com/diffplug/spotless/pull/620))
1717
* `GitRatchet` now lives in `lib-extra`, and is shared across `plugin-gradle` and `plugin-maven` ([#626](https://github.com/diffplug/spotless/pull/626)).
18+
* Added ANTLR4 support ([#326](https://github.com/diffplug/spotless/issues/326)).
1819
### Changed
1920
* **BREAKING** `FileSignature` can no longer sign folders, only files. Signatures are now based only on filename (not path), size, and a content hash. It throws an error if a signature is attempted on a folder or on multiple files with different paths but the same filename - it never breaks silently. This change does not break any of Spotless' internal logic, so it is unlikely to affect any of Spotless' consumers either. ([#571](https://github.com/diffplug/spotless/pull/571))
2021
* This change allows the maven plugin to cache classloaders across subprojects when loading config resources from the classpath (fixes [#559](https://github.com/diffplug/spotless/issues/559)).
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2016-2020 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.antlr4;
17+
18+
public class Antlr4Defaults {
19+
private static final String LICENSE_HEADER_DELIMITER = "(grammar|lexer grammar|parser grammar)";
20+
private static final String INCLUDES = "src/*/antlr4/**/*.g4";
21+
22+
private Antlr4Defaults() {}
23+
24+
public static String licenseHeaderDelimiter() {
25+
return LICENSE_HEADER_DELIMITER;
26+
}
27+
28+
public static String includes() {
29+
return INCLUDES;
30+
}
31+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright 2016-2020 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.antlr4;
17+
18+
import java.io.IOException;
19+
import java.io.Serializable;
20+
import java.lang.reflect.InvocationTargetException;
21+
import java.lang.reflect.Method;
22+
23+
import com.diffplug.spotless.*;
24+
25+
public class Antlr4FormatterStep {
26+
27+
public static final String NAME = "antlr4Formatter";
28+
29+
private Antlr4FormatterStep() {}
30+
31+
private static final String MAVEN_COORDINATE = "com.khubla.antlr4formatter:antlr4-formatter:";
32+
private static final String DEFAULT_VERSION = "1.2.1";
33+
34+
public static FormatterStep create(Provisioner provisioner) {
35+
return create(defaultVersion(), provisioner);
36+
}
37+
38+
public static FormatterStep create(String version, Provisioner provisioner) {
39+
return FormatterStep.createLazy(NAME, () -> new State(version, provisioner), State::createFormat);
40+
}
41+
42+
public static String defaultVersion() {
43+
return DEFAULT_VERSION;
44+
}
45+
46+
static final class State implements Serializable {
47+
private static final long serialVersionUID = 1L;
48+
49+
/**
50+
* The jar that contains the formatter.
51+
*/
52+
final JarState jarState;
53+
54+
State(String version, Provisioner provisioner) throws IOException {
55+
this.jarState = JarState.from(MAVEN_COORDINATE + version, provisioner);
56+
}
57+
58+
FormatterFunc createFormat() throws ClassNotFoundException, NoSuchMethodException {
59+
ClassLoader classLoader = jarState.getClassLoader();
60+
61+
// String Antlr4Formatter::format(String input)
62+
Class<?> formatter = classLoader.loadClass("com.khubla.antlr4formatter.Antlr4Formatter");
63+
Method formatterMethod = formatter.getMethod("format", String.class);
64+
65+
return input -> {
66+
try {
67+
return (String) formatterMethod.invoke(null, input);
68+
} catch (InvocationTargetException e) {
69+
throw ThrowingEx.unwrapCause(e);
70+
}
71+
};
72+
}
73+
}
74+
}

plugin-gradle/CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
99
* Full support for the Gradle buildcache - previously only supported local, now supports remote too. Fixes [#566](https://github.com/diffplug/spotless/issues/566) and [#280](https://github.com/diffplug/spotless/issues/280), via changes in [#621](https://github.com/diffplug/spotless/pull/621) and [#571](https://github.com/diffplug/spotless/pull/571).
1010
* `prettier` will now autodetect the parser (and formatter) to use based on the filename, unless you override this using `config()` or `configFile()` with the option `parser` or `filepath`. ([#620](https://github.com/diffplug/spotless/pull/620))
1111
* (user-invisible) moved the deprecated lib code which was only being used in deprecated parts of `plugin-gradle` into the `.libdeprecated` package. ([#630](https://github.com/diffplug/spotless/pull/630))
12+
* Added ANTLR4 support ([#326](https://github.com/diffplug/spotless/issues/326)).
1213
### Fixed
1314
* LineEndings.GIT_ATTRIBUTES is now a bit more efficient, and paves the way for remote build cache support in Gradle. ([#621](https://github.com/diffplug/spotless/pull/621))
1415
* `ratchetFrom` now ratchets from the merge base of `HEAD` and the specified branch. This fixes the surprising behavior when a remote branch advanced ([#631](https://github.com/diffplug/spotless/pull/631) fixes [#627](https://github.com/diffplug/spotless/issues/627)).
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2016-2020 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.gradle.spotless;
17+
18+
import java.util.Objects;
19+
20+
import com.diffplug.spotless.FormatterStep;
21+
import com.diffplug.spotless.antlr4.Antlr4Defaults;
22+
import com.diffplug.spotless.antlr4.Antlr4FormatterStep;
23+
24+
public class Antlr4Extension extends FormatExtension implements HasBuiltinDelimiterForLicense {
25+
static final String NAME = "antlr4";
26+
27+
public Antlr4Extension(SpotlessExtensionBase rootExtension) {
28+
super(rootExtension);
29+
}
30+
31+
public Antlr4FormatterConfig antlr4Formatter() {
32+
return antlr4Formatter(Antlr4FormatterStep.defaultVersion());
33+
}
34+
35+
public Antlr4FormatterConfig antlr4Formatter(String version) {
36+
return new Antlr4FormatterConfig(version);
37+
}
38+
39+
public class Antlr4FormatterConfig {
40+
41+
private final String version;
42+
43+
Antlr4FormatterConfig(String version) {
44+
this.version = Objects.requireNonNull(version);
45+
addStep(createStep());
46+
}
47+
48+
private FormatterStep createStep() {
49+
return Antlr4FormatterStep.create(this.version, provisioner());
50+
}
51+
}
52+
53+
@Override
54+
protected void setupTask(SpotlessTask task) {
55+
if (target == null) {
56+
target = parseTarget(Antlr4Defaults.includes());
57+
}
58+
super.setupTask(task);
59+
}
60+
61+
@Override
62+
public LicenseHeaderConfig licenseHeader(String licenseHeader) {
63+
return licenseHeader(licenseHeader, Antlr4Defaults.licenseHeaderDelimiter());
64+
}
65+
66+
@Override
67+
public LicenseHeaderConfig licenseHeaderFile(Object licenseHeaderFile) {
68+
return licenseHeaderFile(licenseHeaderFile, Antlr4Defaults.licenseHeaderDelimiter());
69+
}
70+
}

plugin-gradle/src/main/java/com/diffplug/gradle/spotless/SpotlessExtensionBase.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,11 @@ public void typescript(Action<TypescriptExtension> closure) {
161161
format(TypescriptExtension.NAME, TypescriptExtension.class, closure);
162162
}
163163

164+
/** Configures the special antlr4-specific extension for antlr4 files. */
165+
public void antlr4(Action<Antlr4Extension> closure) {
166+
format(Antlr4Extension.NAME, Antlr4Extension.class, closure);
167+
}
168+
164169
/** Configures a custom extension. */
165170
public void format(String name, Action<FormatExtension> closure) {
166171
requireNonNull(name, "name");
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2016-2020 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.gradle.spotless;
17+
18+
import java.io.IOException;
19+
20+
import org.junit.Test;
21+
22+
public class Antlr4ExtensionTest extends GradleIntegrationHarness {
23+
24+
@Test
25+
public void applyUsingDefaultVersion() throws IOException {
26+
String[] buildScript = {
27+
"buildscript {",
28+
" repositories {",
29+
" mavenCentral()",
30+
" }",
31+
"}",
32+
"plugins {",
33+
" id 'com.diffplug.gradle.spotless'",
34+
"}",
35+
"spotless {",
36+
" antlr4 {",
37+
" target 'src/main/antlr4/**/*.g4'",
38+
" antlr4Formatter()",
39+
" }",
40+
"}"};
41+
42+
assertAppliedFormat(buildScript);
43+
}
44+
45+
@Test
46+
public void applyUsingCustomVersion() throws IOException {
47+
String[] buildScript = {
48+
"buildscript {",
49+
" repositories {",
50+
" mavenCentral()",
51+
" }",
52+
"}",
53+
"plugins {",
54+
" id 'com.diffplug.gradle.spotless'",
55+
"}",
56+
"spotless {",
57+
" antlr4 {",
58+
" target 'src/main/antlr4/**/*.g4'",
59+
" antlr4Formatter('1.2.1')",
60+
" }",
61+
"}"};
62+
63+
assertAppliedFormat(buildScript);
64+
}
65+
66+
private void assertAppliedFormat(String... buildScript) throws IOException {
67+
String testFile = "src/main/antlr4/Hello.g4";
68+
69+
setFile("build.gradle").toLines(buildScript);
70+
71+
String unformatted = "antlr4/Hello.unformatted.g4";
72+
String formatted = "antlr4/Hello.formatted.g4";
73+
setFile(testFile).toResource(unformatted);
74+
75+
gradleRunner().withArguments("spotlessApply").build();
76+
77+
assertFile(testFile).sameAsResource(formatted);
78+
}
79+
}

plugin-maven/CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
88
* Huge speed improvement for multi-module projects thanks to improved cross-project classloader caching ([#571](https://github.com/diffplug/spotless/pull/571), fixes [#559](https://github.com/diffplug/spotless/issues/559)).
99
* If you specify `-DspotlessSetLicenseHeaderYearsFromGitHistory=true`, Spotless will perform an expensive search through git history to determine the oldest and newest commits for each file, and uses that to determine license header years. ([#626](https://github.com/diffplug/spotless/pull/626))
1010
* `prettier` will now autodetect the parser (and formatter) to use based on the filename, unless you override this using `config` or `configFile` with the option `parser` or `filepath` ([#620](https://github.com/diffplug/spotless/pull/620)).
11+
* Added ANTLR4 support ([#326](https://github.com/diffplug/spotless/issues/326)).
1112
### Removed
1213
* **BREAKING** the long-deprecated `<xml>` and `<css>` formats have been removed, in favor of the long-available [`<eclipseWtp>`](https://github.com/diffplug/spotless/tree/main/plugin-maven#eclipse-wtp) step which is available in every generic format.
1314
* This probably doesn't affect you, but if it does, you just need to change `<xml>...` into `<formats><format><eclipseWtp><type>XML</type>...`

plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import com.diffplug.spotless.LineEnding;
4848
import com.diffplug.spotless.Provisioner;
4949
import com.diffplug.spotless.generic.LicenseHeaderStep;
50+
import com.diffplug.spotless.maven.antlr4.Antlr4;
5051
import com.diffplug.spotless.maven.cpp.Cpp;
5152
import com.diffplug.spotless.maven.generic.Format;
5253
import com.diffplug.spotless.maven.generic.LicenseHeader;
@@ -108,6 +109,9 @@ public abstract class AbstractSpotlessMojo extends AbstractMojo {
108109
@Parameter
109110
private Typescript typescript;
110111

112+
@Parameter
113+
private Antlr4 antlr4;
114+
111115
@Parameter(property = "spotlessFiles")
112116
private String filePatterns;
113117

@@ -194,7 +198,7 @@ private FileLocator getFileLocator() {
194198
}
195199

196200
private List<FormatterFactory> getFormatterFactories() {
197-
return Stream.concat(formats.stream(), Stream.of(java, scala, kotlin, cpp, typescript))
201+
return Stream.concat(formats.stream(), Stream.of(java, scala, kotlin, cpp, typescript, antlr4))
198202
.filter(Objects::nonNull)
199203
.collect(toList());
200204
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2016-2020 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.maven.antlr4;
17+
18+
import java.util.Set;
19+
20+
import com.diffplug.common.collect.ImmutableSet;
21+
import com.diffplug.spotless.antlr4.Antlr4Defaults;
22+
import com.diffplug.spotless.maven.FormatterFactory;
23+
import com.diffplug.spotless.maven.generic.LicenseHeader;
24+
25+
/**
26+
* A {@link FormatterFactory} implementation that corresponds to {@code <antlr4>...</antlr4>} configuration element.
27+
* <p>
28+
* It defines a formatter for ANTLR4 source files that can execute both language agnostic (e.g. {@link LicenseHeader})
29+
* and anltr4-specific (e.g. {@link Antlr4Formatter}) steps.
30+
*/
31+
public class Antlr4 extends FormatterFactory {
32+
@Override
33+
public Set<String> defaultIncludes() {
34+
return ImmutableSet.of(Antlr4Defaults.includes());
35+
}
36+
37+
@Override
38+
public String licenseHeaderDelimiter() {
39+
return Antlr4Defaults.licenseHeaderDelimiter();
40+
}
41+
42+
public void addAntlr4Formatter(Antlr4Formatter antlr4Formatter) {
43+
addStepFactory(antlr4Formatter);
44+
}
45+
46+
}

0 commit comments

Comments
 (0)