Skip to content

Commit 08566a7

Browse files
committed
Code formatters should be easily pluggable
1 parent ac49450 commit 08566a7

File tree

63 files changed

+1218
-431
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1218
-431
lines changed

.github/workflows/ci.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: CI
22

3-
on: [push]
3+
on: [ push ]
44

55
jobs:
66
build:
@@ -12,6 +12,6 @@ jobs:
1212
uses: actions/setup-java@v2
1313
with:
1414
java-version: '17'
15-
distribution: 'adopt'
15+
distribution: 'temurin'
1616
- name: Build with Maven
17-
run: mvn --batch-mode verify
17+
run: ./mvnw --batch-mode clean verify

.mvn/wrapper/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
maven-wrapper.jar

.mvn/wrapper/maven-wrapper.properties

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
18+
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar

README.md

+88-22
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,20 @@
33

44
# Git Code Format Maven Plugin
55

6-
A maven plugin that automatically deploys [google-java-format](https://github.com/google/google-java-format) code formatter as a `pre-commit` git hook.
6+
A maven plugin that automatically deploys code formatters as `pre-commit` git hook.
77
On commit, the hook will automatically format staged java files.
88

9-
### Breaking changes between 2.x and 3.x
9+
# Breaking changes between 3.x and 4.x
10+
11+
* `Google Java Format` is not enabled by default anymore. `com.cosium.code:google-java-format` must be added as a dependency to the plugin to keep using it.
12+
* `Google Java Format` options declaration structure has changed. You will need to migrate any eventual existing declaration to the new structure described by [the google-java-format-options chapter](#google-java-format-options) .
13+
14+
# Breaking changes between 2.x and 3.x
1015

1116
* [#64](https://github.com/Cosium/git-code-format-maven-plugin/issues/64) `google-java-format 1.8` [dropped support for java 8](https://github.com/google/google-java-format/releases/tag/google-java-format-1.8).
1217
The minimum supported runtime version for the plugin is JDK 11. i.e. Maven must run on JDK 11+ while the target project can still be built and run using JDK 8.
1318

14-
### Breaking changes between 1.x and 2.x
19+
# Breaking changes between 1.x and 2.x
1520

1621
* [#37](https://github.com/Cosium/git-code-format-maven-plugin/issues/37) To prevent conflicts with other plugins all keys are now
1722
prefixed with `gcf`. e.g. `-DglobPattern=**/*` becomes `-Dgcf.globPattern=**/*`
@@ -21,7 +26,7 @@ the plugin was renamed to `git-code-format-maven-plugin`. Its new coordinates ar
2126

2227
`1.x` documentation can be found [here](https://github.com/Cosium/git-code-format-maven-plugin/blob/1.39/README.md)
2328

24-
### Automatic code format and validation activation
29+
# Automatic code format and validation activation
2530

2631
Add this to your maven project **root** pom.xml :
2732

@@ -49,24 +54,34 @@ Add this to your maven project **root** pom.xml :
4954
</goals>
5055
</execution>
5156
</executions>
57+
<dependencies>
58+
<!-- Enable https://github.com/google/google-java-format -->
59+
<dependency>
60+
<groupId>com.cosium.code</groupId>
61+
<artifactId>google-java-format</artifactId>
62+
<version>${git-code-format-maven-plugin.version}</version>
63+
</dependency>
64+
</dependencies>
5265
</plugin>
5366
</plugins>
5467
</build>
5568
```
5669

57-
### Manual code formatting
70+
# Manual code formatting
5871

5972
```console
6073
mvn git-code-format:format-code -Dgcf.globPattern=**/*
6174
```
6275

63-
### Manual code format validation
76+
# Manual code format validation
6477

6578
```console
6679
mvn git-code-format:validate-code-format -Dgcf.globPattern=**/*
6780
```
6881

69-
### Google Java Format options
82+
# Google Java Format
83+
84+
## Google Java Format options
7085

7186
The plugin allows you to tweak Google Java Format options :
7287

@@ -80,13 +95,16 @@ The plugin allows you to tweak Google Java Format options :
8095
<executions>
8196
<!-- ... -->
8297
</executions>
98+
<dependencies>
99+
<!-- ... -->
100+
</dependencies>
83101
<configuration>
84-
<googleJavaFormatOptions>
85-
<aosp>false</aosp>
86-
<fixImportsOnly>false</fixImportsOnly>
87-
<skipSortingImports>false</skipSortingImports>
88-
<skipRemovingUnusedImports>false</skipRemovingUnusedImports>
89-
</googleJavaFormatOptions>
102+
<formatterOptions>
103+
<googleJavaFormat.aosp>false</googleJavaFormat.aosp>
104+
<googleJavaFormat.fixImportsOnly>false</googleJavaFormat.fixImportsOnly>
105+
<googleJavaFormat.skipSortingImports>false</googleJavaFormat.skipSortingImports>
106+
<googleJavaFormat.skipRemovingUnusedImports>false</googleJavaFormat.skipRemovingUnusedImports>
107+
</formatterOptions>
90108
</configuration>
91109
</plugin>
92110
</plugins>
@@ -106,7 +124,7 @@ Documentation from the google-java-format CLI tool :
106124
Do not remove unused imports. Imports will still be sorted.
107125
```
108126

109-
### JDK 16+ peculiarities
127+
## JDK 16+ peculiarities
110128

111129
Since google-java-format uses JDK internal apis, if you need to run the plugin with JDK 16+, you must pass some additional arguments to the JVM.
112130
Those are described at https://github.com/google/google-java-format/releases/tag/v1.10.0.
@@ -117,23 +135,71 @@ Thanks to https://maven.apache.org/configure.html#mvn-jvm-config-file, you shoul
117135
--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
118136
```
119137

120-
### Frequently asked questions
138+
# Custom code formatter
139+
140+
Thanks to its code formatter SPI, this plugin can execute any code formatter.
141+
142+
## How to
143+
144+
Note that you can take inspiration from the `google-java-format` module of this project.
145+
146+
1. Implement `com.cosium.code.format_spi.CodeFormatterFactory`. This interface is provided by `com.cosium.code:git-code-format-maven-plugin-spi`.
147+
2. Add your `com.cosium.code.format_spi.CodeFormatterFactory` implementation canonical name in `META-INF/services/com.cosium.code.format_spi.CodeFormatterFactory`.
148+
3. Pack this in a jar that you declare as a dependency in this plugin declaration.
149+
150+
## Example of usage
151+
152+
Suppose:
153+
- the chosen `configurationId` (declared by `com.cosium.code.format_spi.CodeFormatterFactory#configurationId()`) is `aqme`
154+
- the formatter dependency is `com.aqme.formatter:formatter:1.0`
155+
156+
A plugin declaration making use of this custom code formatter would look like this:
157+
158+
```xml
159+
<build>
160+
<plugins>
161+
<plugin>
162+
<groupId>com.cosium.code</groupId>
163+
<artifactId>git-code-format-maven-plugin</artifactId>
164+
<version>${git-code-format-maven-plugin.version}</version>
165+
<executions>
166+
<!-- ... -->
167+
</executions>
168+
<dependencies>
169+
<dependency>
170+
<groupId>com.aqme.formatter</groupId>
171+
<artifactId>formatter</artifactId>
172+
<version>1.0</version>
173+
</dependency>
174+
</dependencies>
175+
<configuration>
176+
<formatterOptions>
177+
<aqme.option1>false</aqme.option1>
178+
<aqme.option2>foo</aqme.option2>
179+
</formatterOptions>
180+
</configuration>
181+
</plugin>
182+
</plugins>
183+
</build>
184+
```
185+
186+
# Frequently asked questions
121187

122-
#### If I have a multi-module project, do I need to install anything in the sub-projects?
188+
## If I have a multi-module project, do I need to install anything in the sub-projects?
123189
You only need to put the plugin in your *root* project pom.xml. By default all submodules will be handled.
124190

125-
#### Do I need to run mvn initialize or is that a stage that happens automatically when I run mvn compile or mvn test?
191+
## Do I need to run mvn initialize or is that a stage that happens automatically when I run mvn compile or mvn test?
126192
`initialize` is the first phase of the Maven lifecycle. Any goal that you perform (e.g. `compile` or `test`) will automatically trigger `initialize` and thus trigger the git pre-commit hook installation.
127193

128-
#### I'm not noticing anything happening.
194+
## I'm not noticing anything happening.
129195
If after setting up the plugin in your pom, you just executed a maven goal, the only expected output is a pre-commit hook installed in your `.git/hooks` directory. To trigger the automatic formatting, you have to perform a commit of a modified java file.
130196
You can also manually [format](#manual-code-formatting) or [validate](#manual-code-format-validation) any file.
131197

132-
#### I'd like to skip code formatting in a child project
198+
## I'd like to skip code formatting in a child project
133199
I inherit an enterprise parent pom, which I cannot modify, with formatting plugin specified, and I need to turn off formatting for my group's project.
134200
Either use add a ```<skip>true</skip>``` configuration in the inheriting project or set the ```gcf.skip``` property to true.
135201

136-
### How the hook works
202+
# How the hook works
137203

138204
On the `initialize` maven phase, `git-code-format:install-hooks` installs a git `pre-commit` hook that looks like this :
139205
```bash
@@ -147,9 +213,9 @@ set -e
147213
"${env.M2_HOME}/bin/mvn" -f "${project.basedir}/pom.xml" git-code-format:on-pre-commit
148214
```
149215

150-
On `pre-commit` git phase, the hook triggers the `git-code-format:on-pre-commit` which formats the code of the modified java files using `google-java-format`.
216+
On `pre-commit` git phase, the hook triggers the `git-code-format:on-pre-commit` which formats the code of the modified java files.
151217

152-
### Advanced pre-commit pipeline hook
218+
# Advanced pre-commit pipeline hook
153219
If you wish to modify the output of the pre-commit hook, you can set the `preCommitHookPipeline` configuration.
154220

155221
To completely ignore the hook output, you could use the following configuration:

core/.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
target
1+
/target

core/pom.xml

+20-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>com.cosium.code</groupId>
77
<artifactId>git-code-format-maven-plugin-parent</artifactId>
8-
<version>3.6-SNAPSHOT</version>
8+
<version>4.0-SNAPSHOT</version>
99
</parent>
1010

1111
<artifactId>git-code-format-maven-plugin</artifactId>
@@ -14,6 +14,12 @@
1414
<name>Git Code Format Maven Plugin</name>
1515

1616
<dependencies>
17+
<dependency>
18+
<groupId>${project.groupId}</groupId>
19+
<artifactId>git-code-format-maven-plugin-spi</artifactId>
20+
<version>${project.version}</version>
21+
</dependency>
22+
1723
<dependency>
1824
<groupId>commons-io</groupId>
1925
<artifactId>commons-io</artifactId>
@@ -92,8 +98,20 @@
9298
<version>2.22.2</version>
9399
<configuration>
94100
<trimStackTrace>false</trimStackTrace>
95-
<argLine>@{argLine} --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</argLine>
101+
<argLine>@{argLine} --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports
102+
jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED --add-exports
103+
jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED --add-exports
104+
jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-exports
105+
jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
106+
</argLine>
96107
</configuration>
108+
<dependencies>
109+
<dependency>
110+
<groupId>${project.groupId}</groupId>
111+
<artifactId>google-java-format</artifactId>
112+
<version>${project.version}</version>
113+
</dependency>
114+
</dependencies>
97115
</plugin>
98116
<plugin>
99117
<groupId>org.apache.maven.plugins</groupId>

core/src/main/java/com/cosium/code/format/AbstractFormatMojo.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
import org.apache.maven.plugins.annotations.Parameter;
1414

1515
/**
16-
* Created on 16/01/18.
17-
*
18-
* @author Reda.Housni-Alaoui
16+
* @author Réda Housni Alaoui
1917
*/
2018
public abstract class AbstractFormatMojo extends AbstractModuleMavenGitCodeFormatMojo {
2119

core/src/main/java/com/cosium/code/format/AbstractMavenGitCodeFormatMojo.java

+26-24
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
package com.cosium.code.format;
22

3-
import static java.util.Optional.ofNullable;
4-
5-
import com.cosium.code.format.formatter.CodeFormatter;
3+
import com.cosium.code.format.formatter.CodeFormatterConfigurationFactory;
64
import com.cosium.code.format.formatter.CodeFormatters;
7-
import com.cosium.code.format.formatter.GoogleJavaFormatter;
5+
import com.cosium.code.format_spi.CodeFormatter;
6+
import com.cosium.code.format_spi.CodeFormatterFactory;
87
import java.io.File;
98
import java.io.IOException;
109
import java.nio.file.Files;
1110
import java.nio.file.Path;
1211
import java.nio.file.Paths;
12+
import java.util.ArrayList;
1313
import java.util.Collection;
14-
import java.util.Collections;
1514
import java.util.List;
16-
import java.util.function.Supplier;
15+
import java.util.Map;
16+
import java.util.ServiceLoader;
1717
import java.util.stream.Collectors;
1818
import java.util.stream.Stream;
1919
import org.apache.commons.lang3.StringUtils;
@@ -24,34 +24,19 @@
2424
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
2525

2626
/**
27-
* Created on 01/11/17.
28-
*
29-
* @author Reda.Housni-Alaoui
27+
* @author Réda Housni Alaoui
3028
*/
3129
public abstract class AbstractMavenGitCodeFormatMojo extends AbstractMojo {
3230

3331
protected static final String HOOKS_DIR = "hooks";
3432

35-
private final Supplier<List<CodeFormatter>> codeFormatters;
36-
3733
@Parameter(readonly = true, defaultValue = "${project}")
3834
private MavenProject currentProject;
3935

40-
@Parameter private MavenGoogleJavaFormatOptions googleJavaFormatOptions;
41-
4236
@Parameter(defaultValue = "${project.build.sourceEncoding}")
4337
private String sourceEncoding;
4438

45-
public AbstractMavenGitCodeFormatMojo() {
46-
codeFormatters =
47-
() ->
48-
Collections.singletonList(
49-
new GoogleJavaFormatter(
50-
ofNullable(googleJavaFormatOptions)
51-
.orElseGet(MavenGoogleJavaFormatOptions::new)
52-
.toFormatterOptions(),
53-
sourceEncoding));
54-
}
39+
@Parameter private Map<String, String> formatterOptions;
5540

5641
protected final Repository gitRepository() {
5742
Repository gitRepository;
@@ -91,7 +76,24 @@ protected final String artifactId() {
9176
}
9277

9378
protected final CodeFormatters codeFormatters() {
94-
return new CodeFormatters(codeFormatters.get());
79+
return new CodeFormatters(createCodeFormatters());
80+
}
81+
82+
private List<CodeFormatter> createCodeFormatters() {
83+
84+
List<CodeFormatterFactory> formatterFactories = new ArrayList<>();
85+
ServiceLoader.load(CodeFormatterFactory.class).forEach(formatterFactories::add);
86+
87+
CodeFormatterConfigurationFactory formatterConfigurationFactory =
88+
new CodeFormatterConfigurationFactory(formatterOptions);
89+
90+
return formatterFactories.stream()
91+
.map(
92+
codeFormatterFactory ->
93+
codeFormatterFactory.build(
94+
formatterConfigurationFactory.build(codeFormatterFactory.configurationId()),
95+
sourceEncoding))
96+
.collect(Collectors.toList());
9597
}
9698

9799
protected final boolean isExecutionRoot() {

0 commit comments

Comments
 (0)