Skip to content

Commit c00d1cc

Browse files
authored
CPP extension (#295)
C/CPP extension for Gradle and Maven plugin.
1 parent f6d2055 commit c00d1cc

File tree

21 files changed

+559
-3
lines changed

21 files changed

+559
-3
lines changed

CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ You might be looking for:
77

88
### Version 1.15.0-SNAPSHOT - TBD (javadoc [lib](https://diffplug.github.io/spotless/javadoc/spotless-lib/snapshot/) [lib-extra](https://diffplug.github.io/spotless/javadoc/spotless-lib-extra/snapshot/), [snapshot repo](https://oss.sonatype.org/content/repositories/snapshots/com/diffplug/spotless/))
99

10+
* Added C/C++ support ([#232](https://github.com/diffplug/spotless/issues/232)).
11+
* Integrated Eclipse CDT formatter ([#274](https://github.com/diffplug/spotless/pull/274))
1012
* Extended dependency provisioner to exclude transitives on request ([#297](https://github.com/diffplug/spotless/pull/297)).This prevents unnecessary downloads of unused transitive dependencies for Eclipse based formatter steps.
1113
* Updated default groovy-eclipse from 4.8.0 to 4.8.1 ([#288](https://github.com/diffplug/spotless/pull/288)). New version is based on [Groovy-Eclipse 3.0.0](https://github.com/groovy/groovy-eclipse/wiki/3.0.0-Release-Notes).
1214
* Integrated Eclipse WTP formatter ([#290](https://github.com/diffplug/spotless/pull/290))

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ lib('generic.LicenseHeaderStep') +'{{yes}} | {{yes}}
3838
lib('generic.ReplaceRegexStep') +'{{yes}} | {{yes}} | {{no}} |',
3939
lib('generic.ReplaceStep') +'{{yes}} | {{yes}} | {{no}} |',
4040
lib('generic.TrimTrailingWhitespaceStep') +'{{yes}} | {{yes}} | {{no}} |',
41+
extra('cpp.EclipseFormatterStep') +'{{yes}} | {{yes}} | {{no}} |',
4142
extra('groovy.GrEclipseFormatterStep') +'{{yes}} | {{no}} | {{no}} |',
4243
lib('java.GoogleJavaFormatStep') +'{{yes}} | {{yes}} | {{no}} |',
4344
lib('java.ImportOrderStep') +'{{yes}} | {{yes}} | {{no}} |',
@@ -61,6 +62,7 @@ lib('sql.DBeaverSQLFormatterStep') +'{{yes}} | {{no}}
6162
| [`generic.ReplaceRegexStep`](lib/src/main/java/com/diffplug/spotless/generic/ReplaceRegexStep.java) | :+1: | :+1: | :white_large_square: |
6263
| [`generic.ReplaceStep`](lib/src/main/java/com/diffplug/spotless/generic/ReplaceStep.java) | :+1: | :+1: | :white_large_square: |
6364
| [`generic.TrimTrailingWhitespaceStep`](lib/src/main/java/com/diffplug/spotless/generic/TrimTrailingWhitespaceStep.java) | :+1: | :+1: | :white_large_square: |
65+
| [`cpp.EclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/cpp/EclipseFormatterStep.java) | :+1: | :+1: | :white_large_square: |
6466
| [`groovy.GrEclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/groovy/GrEclipseFormatterStep.java) | :+1: | :white_large_square: | :white_large_square: |
6567
| [`java.GoogleJavaFormatStep`](lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java) | :+1: | :+1: | :white_large_square: |
6668
| [`java.ImportOrderStep`](lib/src/main/java/com/diffplug/spotless/java/ImportOrderStep.java) | :+1: | :+1: | :white_large_square: |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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.cpp;
17+
18+
import java.lang.reflect.Method;
19+
import java.util.Properties;
20+
21+
import com.diffplug.spotless.FormatterFunc;
22+
import com.diffplug.spotless.Provisioner;
23+
import com.diffplug.spotless.extra.EclipseBasedStepBuilder;
24+
import com.diffplug.spotless.extra.EclipseBasedStepBuilder.State;
25+
26+
/** Formatter step which calls out to the Eclipse CDT formatter. */
27+
public final class EclipseCdtFormatterStep {
28+
// prevent direct instantiation
29+
private EclipseCdtFormatterStep() {}
30+
31+
private static final String NAME = "eclipse cdt formatter";
32+
private static final String FORMATTER_CLASS = "com.diffplug.spotless.extra.eclipse.cdt.EclipseCdtFormatterStepImpl";
33+
private static final String DEFAULT_VERSION = "4.7.3a";
34+
private static final String FORMATTER_METHOD = "format";
35+
36+
public static String defaultVersion() {
37+
return DEFAULT_VERSION;
38+
}
39+
40+
/** Provides default configuration */
41+
public static EclipseBasedStepBuilder createBuilder(Provisioner provisioner) {
42+
return new EclipseBasedStepBuilder(NAME, provisioner, EclipseCdtFormatterStep::apply);
43+
}
44+
45+
private static FormatterFunc apply(State state) throws Exception {
46+
Class<?> formatterClazz = state.loadClass(FORMATTER_CLASS);
47+
Object formatter = formatterClazz.getConstructor(Properties.class).newInstance(state.getPreferences());
48+
Method method = formatterClazz.getMethod(FORMATTER_METHOD, String.class);
49+
return input -> (String) method.invoke(formatter, input);
50+
}
51+
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@ParametersAreNonnullByDefault
2+
@ReturnValuesAreNonnullByDefault
3+
package com.diffplug.spotless.extra.cpp;
4+
5+
import javax.annotation.ParametersAreNonnullByDefault;
6+
7+
import com.diffplug.spotless.annotations.ReturnValuesAreNonnullByDefault;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Spotless formatter based on CDT version 9.4.3 (see https://www.eclipse.org/cdt/)
2+
com.diffplug.spotless:spotless-eclipse-cdt:9.4.4
3+
com.diffplug.spotless:spotless-eclipse-base:3.0.0
4+
com.google.code.findbugs:annotations:3.0.0
5+
com.google.code.findbugs:jsr305:3.0.0
6+
com.ibm.icu:icu4j:61.1
7+
org.eclipse.platform:org.eclipse.core.commands:3.9.100
8+
org.eclipse.platform:org.eclipse.core.contenttype:3.7.0
9+
org.eclipse.platform:org.eclipse.core.filebuffers:3.6.200
10+
org.eclipse.platform:org.eclipse.core.filesystem:1.7.100
11+
org.eclipse.platform:org.eclipse.core.jobs:3.10.0
12+
org.eclipse.platform:org.eclipse.core.resources:3.13.0
13+
org.eclipse.platform:org.eclipse.core.runtime:3.14.0
14+
org.eclipse.platform:org.eclipse.equinox.app:1.3.500
15+
org.eclipse.platform:org.eclipse.equinox.common:3.10.0
16+
org.eclipse.platform:org.eclipse.equinox.preferences:3.7.100
17+
org.eclipse.platform:org.eclipse.equinox.registry:3.8.0
18+
org.eclipse.platform:org.eclipse.jface.text:3.13.0
19+
org.eclipse.platform:org.eclipse.jface:3.14.0
20+
org.eclipse.platform:org.eclipse.osgi:3.13.0
21+
org.eclipse.platform:org.eclipse.text:3.6.300
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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.cpp;
17+
18+
import com.diffplug.spotless.FormatterStep;
19+
import com.diffplug.spotless.TestProvisioner;
20+
import com.diffplug.spotless.extra.EclipseBasedStepBuilder;
21+
import com.diffplug.spotless.extra.eclipse.EclipseCommonTests;
22+
23+
public class EclipseCdtFormatterStepTest extends EclipseCommonTests {
24+
25+
@Override
26+
protected String[] getSupportedVersions() {
27+
return new String[]{"4.7.3a"};
28+
}
29+
30+
@Override
31+
protected String getTestInput(String version) {
32+
return "#include <a.h>;\nint main(int argc, \nchar *argv[]) {}";
33+
}
34+
35+
@Override
36+
protected String getTestExpectation(String version) {
37+
return "#include <a.h>;\nint main(int argc, char *argv[]) {\n}\n";
38+
}
39+
40+
@Override
41+
protected FormatterStep createStep(String version) {
42+
EclipseBasedStepBuilder builder = EclipseCdtFormatterStep.createBuilder(TestProvisioner.mavenCentral());
43+
builder.setVersion(version);
44+
return builder.build();
45+
}
46+
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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.cpp;
17+
18+
import java.util.Arrays;
19+
import java.util.Collections;
20+
import java.util.List;
21+
import java.util.stream.Collectors;
22+
23+
/** Common utilities for C/C++ */
24+
public class CppDefaults {
25+
//Prevent instantiation
26+
private CppDefaults() {};
27+
28+
public static final List<String> FILE_FILTER = Collections.unmodifiableList(
29+
Arrays.asList("c", "h", "C", "cpp", "cxx", "cc", "c++", "h", "hpp", "hh", "hxx", "inc")
30+
.stream().map(s -> {
31+
return "**/*." + s;
32+
}).collect(Collectors.toList()));
33+
34+
/**
35+
* Default delimiter expression shall cover most valid and common starts of C/C++ declarations and definitions.
36+
* Furthermore it shall not conflict with terms commonly used within license headers.
37+
* Note that the longest match is selected. Hence "using namespace foo" is preferred over "namespace foo".
38+
*/
39+
public static final String DELIMITER_EXPR = Arrays.asList(
40+
"#define", "#error", "#if", "#ifdef", "#ifndef", "#include", "#pragma", "#undef",
41+
"asm", "class", "namespace", "struct", "typedef", "using namespace",
42+
"const", "extern", "mutable", "signed", "unsigned", "volatile",
43+
"auto", "char", "double", "float", "int", "long", "void",
44+
"char16_t", "char32_t", "char64_t",
45+
"int8_t", "int16_t", "int32_t", "int64_t",
46+
"__int8_t", "__int16_t", "__int32_t", "__int64_t",
47+
"uint8_t", "uint16_t", "uint32_t", "uint64_t")
48+
.stream().map(s -> {
49+
return "(?<![0-9a-zA-Z]+)" + s.replaceAll("#", "\\\\#").replaceAll(" ", "[\\\\n\\\\s]+") + "[\\*\\s\\n]+";
50+
}).collect(Collectors.joining("|"));
51+
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@ParametersAreNonnullByDefault
2+
@ReturnValuesAreNonnullByDefault
3+
package com.diffplug.spotless.cpp;
4+
5+
import javax.annotation.ParametersAreNonnullByDefault;
6+
7+
import com.diffplug.spotless.annotations.ReturnValuesAreNonnullByDefault;

plugin-gradle/CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
### Version 3.15.0-SNAPSHOT - TBD ([javadoc](https://diffplug.github.io/spotless/javadoc/snapshot/), [snapshot](https://oss.sonatype.org/content/repositories/snapshots/com/diffplug/spotless/spotless-plugin-gradle/))
44

5+
* Added C/C++ support using formatter of Eclipse CDT 9.4.3 ([#232](https://github.com/diffplug/spotless/issues/232)).
56
* Updated default groovy-eclipse from 4.8.0 to 4.8.1 ([#288](https://github.com/diffplug/spotless/pull/288)). New version is based on [Groovy-Eclipse 3.0.0](https://github.com/groovy/groovy-eclipse/wiki/3.0.0-Release-Notes).
67
* LicenseHeaderStep now wont attempt to add license to `module-info.java` ([#272](https://github.com/diffplug/spotless/pull/272)).
78
* Updated JSR305 annotation from 3.0.0 to 3.0.2 ([#274](https://github.com/diffplug/spotless/pull/274))

plugin-gradle/README.md

+28-2
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,10 @@ spotless {
7777

7878
Spotless can check and apply formatting to any plain-text file, using simple rules ([javadoc](https://diffplug.github.io/spotless/javadoc/spotless-plugin-gradle/3.14.0/com/diffplug/gradle/spotless/FormatExtension.html)) like those above. It also supports more powerful formatters:
7979

80+
* Eclipse's [CDT](#eclipse-cdt) C/C++ code formatter
8081
* Eclipse's java code formatter (including style and import ordering)
8182
* Google's [google-java-format](https://github.com/google/google-java-format)
82-
* [Groovy Eclipse](https://github.com/groovy/groovy-eclipse/wiki)'s groovy code formatter
83+
* [Groovy Eclipse](#groovy-eclipse)'s groovy code formatter
8384
* [FreshMark](https://github.com/diffplug/freshmark) (markdown with variables)
8485
* [ktlint](https://github.com/shyiko/ktlint)
8586
* [scalafmt](https://github.com/olafurpg/scalafmt)
@@ -190,8 +191,9 @@ spotless {
190191
}
191192
}
192193
```
194+
<a name="groovy-eclipse"></a>
193195

194-
### [Groovy-Eclipse](https://github.com/groovy/groovy-eclipse) XML formatter
196+
### [Groovy-Eclipse](https://github.com/groovy/groovy-eclipse) formatter
195197

196198
The formatter is based on the Eclipse Java formatter as used by `eclipseFormatFile`. It uses the same configuration parameters plus a few additional ones.
197199
These parameters can be configured within a single file, like the Java properties file [greclipse.properties](../lib-extra/src/test/resources/groovy/greclipse/format/greclipse.properties) in the previous example. The formatter step can also load the [exported Eclipse properties](../ECLIPSE_SCREENSHOTS.md) and augment it with the `org.codehaus.groovy.eclipse.ui.prefs` from the Eclipse workspace as shown below.
@@ -291,6 +293,30 @@ spotless {
291293
}
292294
```
293295

296+
<a name="cpp"></a>
297+
298+
## Applying to C/C++ sources
299+
300+
```gradle
301+
spotless {
302+
cpp {
303+
target '**/*.CPP' // Change file filter. By default files with 'c', 'h', 'C', 'cpp', 'cxx', 'cc', 'c++', 'h', 'hpp', 'hh', 'hxx' and 'inc' extension are supported
304+
eclipse().configFile 'spotless.eclipseformat.xml' // XML file dumped out by the Eclipse formatter
305+
// If you have Eclipse preference or property files, you can use them too.
306+
// eclipse('4.7.1') to specify a specific version of Eclipse,
307+
// available versions are: https://github.com/diffplug/spotless/tree/master/lib-extra/src/main/resources/com/diffplug/spotless/extra/config/eclipse_cdt_formatter
308+
licenseHeader '// Licensed under Apache' // License header
309+
licenseHeaderFile './license.txt' // License header file
310+
}
311+
}
312+
```
313+
314+
<a name="eclipse-cdt"></a>
315+
316+
### Eclipse [CDT](https://www.eclipse.org/cdt/) formatter
317+
318+
Use the Eclipse to define the *Code Style preferences* (see [Eclipse documentation](https://www.eclipse.org/documentation/)). Within the preferences *Edit...* dialog, you can export your configuration as XML file, which can be used as a `configFile`. If no `configFile` is provided, the CDT default configuration is used.
319+
294320
<a name="license-header"></a>
295321

296322
## License header options
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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.gradle.spotless;
17+
18+
import static com.diffplug.gradle.spotless.PluginGradlePreconditions.requireElementsNonNull;
19+
20+
import org.gradle.api.Project;
21+
22+
import com.diffplug.spotless.cpp.CppDefaults;
23+
import com.diffplug.spotless.extra.EclipseBasedStepBuilder;
24+
import com.diffplug.spotless.extra.cpp.EclipseCdtFormatterStep;
25+
26+
public class CppExtension extends FormatExtension implements HasBuiltinDelimiterForLicense {
27+
static final String NAME = "cpp";
28+
29+
public CppExtension(SpotlessExtension rootExtension) {
30+
super(rootExtension);
31+
}
32+
33+
public EclipseConfig eclipse() {
34+
return new EclipseConfig(EclipseCdtFormatterStep.defaultVersion());
35+
}
36+
37+
public EclipseConfig eclipse(String version) {
38+
return new EclipseConfig(version);
39+
}
40+
41+
public class EclipseConfig {
42+
private final EclipseBasedStepBuilder builder;
43+
44+
EclipseConfig(String version) {
45+
builder = EclipseCdtFormatterStep.createBuilder(GradleProvisioner.fromProject(getProject()));
46+
builder.setVersion(version);
47+
addStep(builder.build());
48+
}
49+
50+
public void configFile(Object... configFiles) {
51+
requireElementsNonNull(configFiles);
52+
Project project = getProject();
53+
builder.setPreferences(project.files(configFiles).getFiles());
54+
replaceStep(builder.build());
55+
}
56+
57+
}
58+
59+
/** If the user hasn't specified the files yet, we'll assume he/she means all of the C/C++ files. */
60+
@Override
61+
protected void setupTask(SpotlessTask task) {
62+
if (target == null) {
63+
/*
64+
* The org.gradle.language.c and org.gradle.language.cpp source sets are seldom used.
65+
* Most Gradle C/C++ use external CMake builds (so the source location is unknown to Gradle).
66+
* Hence file extension based filtering is used in line with the org.eclipse.core.contenttype.contentTypes
67+
* defined by the CDT plugin.
68+
*/
69+
target(CppDefaults.FILE_FILTER.toArray());
70+
}
71+
super.setupTask(task);
72+
}
73+
74+
@Override
75+
public LicenseHeaderConfig licenseHeader(String licenseHeader) {
76+
return licenseHeader(licenseHeader, CppDefaults.DELIMITER_EXPR);
77+
}
78+
79+
@Override
80+
public LicenseHeaderConfig licenseHeaderFile(Object licenseHeaderFile) {
81+
return licenseHeaderFile(licenseHeaderFile, CppDefaults.DELIMITER_EXPR);
82+
}
83+
}

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

+5
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ public void sql(Action<SqlExtension> closure) {
118118
configure(SqlExtension.NAME, SqlExtension.class, closure);
119119
}
120120

121+
/** Configures the special C/C++-specific extension. */
122+
public void cpp(Action<CppExtension> closure) {
123+
configure(CppExtension.NAME, CppExtension.class, closure);
124+
}
125+
121126
/** Configures a custom extension. */
122127
public void format(String name, Action<FormatExtension> closure) {
123128
requireNonNull(name, "name");

plugin-maven/CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
### Version 1.15.0-SNAPSHOT - TBD ([javadoc](https://diffplug.github.io/spotless/javadoc/spotless-maven-plugin/snapshot/), [snapshot](https://oss.sonatype.org/content/repositories/snapshots/com/diffplug/spotless/spotless-maven-plugin/))
44

5+
* Added C/C++ support using formatter of Eclipse CDT 9.4.3 ([#232](https://github.com/diffplug/spotless/issues/232)).
56
* Skip `package-info.java` and `module-info.java` files from license header formatting. ([#273](https://github.com/diffplug/spotless/pull/273))
67
* Updated JSR305 annotation from 3.0.0 to 3.0.2 ([#274](https://github.com/diffplug/spotless/pull/274))
78
* Migrated from FindBugs annotations 3.0.0 to SpotBugs annotations 3.1.6 ([#274](https://github.com/diffplug/spotless/pull/274))

0 commit comments

Comments
 (0)