Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Gradle support for Maven POM sorting/formatting #2082

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ lib('markdown.FlexmarkStep') +'{{yes}} | {{yes}}
lib('npm.EslintFormatterStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
lib('npm.PrettierFormatterStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
lib('npm.TsFmtFormatterStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
lib('pom.SortPomStepStep') +'{{no}} | {{yes}} | {{no}} | {{no}} |',
lib('pom.SortPomStep') +'{{yes}} | {{yes}} | {{no}} | {{no}} |',
lib('protobuf.BufStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |',
lib('python.BlackStep') +'{{yes}} | {{no}} | {{no}} | {{no}} |',
lib('scala.ScalaFmtStep') +'{{yes}} | {{yes}} | {{yes}} | {{no}} |',
Expand Down Expand Up @@ -154,7 +154,7 @@ lib('yaml.JacksonYamlStep') +'{{yes}} | {{yes}}
| [`npm.EslintFormatterStep`](lib/src/main/java/com/diffplug/spotless/npm/EslintFormatterStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
| [`npm.PrettierFormatterStep`](lib/src/main/java/com/diffplug/spotless/npm/PrettierFormatterStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
| [`npm.TsFmtFormatterStep`](lib/src/main/java/com/diffplug/spotless/npm/TsFmtFormatterStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
| [`pom.SortPomStepStep`](lib/src/main/java/com/diffplug/spotless/pom/SortPomStepStep.java) | :white_large_square: | :+1: | :white_large_square: | :white_large_square: |
| [`pom.SortPomStep`](lib/src/main/java/com/diffplug/spotless/pom/SortPomStep.java) | :+1: | :+1: | :white_large_square: | :white_large_square: |
| [`protobuf.BufStep`](lib/src/main/java/com/diffplug/spotless/protobuf/BufStep.java) | :+1: | :white_large_square: | :white_large_square: | :white_large_square: |
| [`python.BlackStep`](lib/src/main/java/com/diffplug/spotless/python/BlackStep.java) | :+1: | :white_large_square: | :white_large_square: | :white_large_square: |
| [`scala.ScalaFmtStep`](lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java) | :+1: | :+1: | :+1: | :white_large_square: |
Expand Down
1 change: 1 addition & 0 deletions plugin-gradle/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
* Bump default `shfmt` version to latest `3.7.0` -> `3.8.0`. ([#2050](https://github.com/diffplug/spotless/pull/2050))
### Added
* Respect `.editorconfig` settings for formatting shell via `shfmt` ([#2031](https://github.com/diffplug/spotless/pull/2031))
* Add support for formatting and sorting Maven POMs ([#2081](https://github.com/diffplug/spotless/issues/2081))
mches marked this conversation as resolved.
Show resolved Hide resolved

## [6.25.0] - 2024-01-23
### Added
Expand Down
47 changes: 47 additions & 0 deletions plugin-gradle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ Spotless supports all of Gradle's built-in performance features (incremental bui
- [Flexmark](#flexmark) aka markdown
- [Antlr4](#antlr4) ([antlr4formatter](#antlr4formatter))
- [SQL](#sql) ([dbeaver](#dbeaver), [prettier](#prettier))
- [Maven POM](#maven-pom) ([sortPom](#sortpom))
- [Typescript](#typescript) ([tsfmt](#tsfmt), [prettier](#prettier), [ESLint](#eslint-typescript), [Biome](#biome))
- [Javascript](#javascript) ([prettier](#prettier), [ESLint](#eslint-javascript), [Biome](#biome))
- [JSON](#json) ([simple](#simple), [gson](#gson), [jackson](#jackson), [Biome](#biome), [jsonPatch](#jsonPatch))
Expand Down Expand Up @@ -676,6 +677,52 @@ sql.formatter.indent.type=space
sql.formatter.indent.size=4
```

## Maven POM

`com.diffplug.gradle.spotless.PomExtension` [javadoc](https://javadoc.io/doc/com.diffplug.spotless/spotless-plugin-gradle/6.25.0/com/diffplug/gradle/spotless/PomExtension.html), [code](https://github.com/diffplug/spotless/blob/main/plugin-gradle/src/main/java/com/diffplug/gradle/spotless/PomExtension.java)

```gradle
spotless {
pom {
target('pom.xml') // default value, you can change if you want

sortPom() // has its own section below
}
}
```

### sortPom

[homepage](https://github.com/Ekryd/sortpom).

All configuration settings are optional, they are described in detail [here](https://github.com/Ekryd/sortpom/wiki/Parameters).

```gradle
spotless {
pom {
sortPom('3.4.0')
.encoding('UTF-8') // The encoding of the pom files
.lineSeparator(System.getProperty('line.separator')) // line separator to use
.expandEmptyElements(true) // Should empty elements be expanded
.spaceBeforeCloseEmptyElement(false) // Should a space be added inside self-closing elements
.keepBlankLines(true) // Keep empty lines
.endWithNewline(true) // Whether sorted pom ends with a newline
.nrOfIndentSpace(2) // Indentation
.indentBlankLines(false) // Should empty lines be indented
.indentSchemaLocation(false) // Should schema locations be indented
.predefinedSortOrder('recommended_2008_06') // Sort order of elements: https://github.com/Ekryd/sortpom/wiki/PredefinedSortOrderProfiles
.sortOrderFile(null) // Custom sort order of elements: https://raw.githubusercontent.com/Ekryd/sortpom/master/sorter/src/main/resources/custom_1.xml
.sortDependencies(null) // Sort dependencies: https://github.com/Ekryd/sortpom/wiki/SortDependencies
.sortDependencyManagement(null) // Sort dependency management: https://github.com/Ekryd/sortpom/wiki/SortDependencies
.sortDependencyExclusions(null) // Sort dependency exclusions: https://github.com/Ekryd/sortpom/wiki/SortDependencies
.sortPlugins(null) // Sort plugins: https://github.com/Ekryd/sortpom/wiki/SortPlugins
.sortProperties(false) // Sort properties
.sortModules(false) // Sort modules
.sortExecutions(false) // Sort plugin executions
}
}
```

<a name="applying-to-typescript-source"></a>

## Typescript
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* Copyright 2024 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.diffplug.gradle.spotless;

import java.util.Objects;

import javax.inject.Inject;

import com.diffplug.spotless.FormatterStep;
import com.diffplug.spotless.pom.SortPomCfg;
import com.diffplug.spotless.pom.SortPomStep;

public class PomExtension extends FormatExtension {
private static final String POM_FILE = "pom.xml";

static final String NAME = "pom";

@Inject
public PomExtension(SpotlessExtension spotless) {
super(spotless);
}

@Override
protected void setupTask(SpotlessTask task) {
if (target == null) {
target = parseTarget(POM_FILE);
}
super.setupTask(task);
}

public SortPomGradleConfig sortPom() {
return new SortPomGradleConfig();
}

public SortPomGradleConfig sortPom(String version) {
Objects.requireNonNull(version);
return new SortPomGradleConfig(version);
}

public class SortPomGradleConfig {
final SortPomCfg cfg = new SortPomCfg();
mches marked this conversation as resolved.
Show resolved Hide resolved

SortPomGradleConfig() {
addStep(createStep());
}

SortPomGradleConfig(String version) {
this();
cfg.version = Objects.requireNonNull(version);
}

public SortPomGradleConfig encoding(String encoding) {
cfg.encoding = encoding;
return this;
}

public SortPomGradleConfig lineSeparator(String lineSeparator) {
cfg.lineSeparator = lineSeparator;
return this;
}

public SortPomGradleConfig expandEmptyElements(boolean expandEmptyElements) {
cfg.expandEmptyElements = expandEmptyElements;
return this;
}

public SortPomGradleConfig spaceBeforeCloseEmptyElement(boolean spaceBeforeCloseEmptyElement) {
cfg.spaceBeforeCloseEmptyElement = spaceBeforeCloseEmptyElement;
return this;
}

public SortPomGradleConfig keepBlankLines(boolean keepBlankLines) {
cfg.keepBlankLines = keepBlankLines;
return this;
}

public SortPomGradleConfig endWithNewline(boolean endWithNewline) {
cfg.endWithNewline = endWithNewline;
return this;
}

public SortPomGradleConfig nrOfIndentSpace(int nrOfIndentSpace) {
cfg.nrOfIndentSpace = nrOfIndentSpace;
return this;
}

public SortPomGradleConfig indentBlankLines(boolean indentBlankLines) {
cfg.indentBlankLines = indentBlankLines;
return this;
}

public SortPomGradleConfig indentSchemaLocation(boolean indentSchemaLocation) {
cfg.indentSchemaLocation = indentSchemaLocation;
return this;
}

public SortPomGradleConfig predefinedSortOrder(String predefinedSortOrder) {
cfg.predefinedSortOrder = predefinedSortOrder;
return this;
}

public SortPomGradleConfig sortOrderFile(String sortOrderFile) {
cfg.sortOrderFile = sortOrderFile;
return this;
}

public SortPomGradleConfig sortDependencies(String sortDependencies) {
cfg.sortDependencies = sortDependencies;
return this;
}

public SortPomGradleConfig sortDependencyManagement(String sortDependencyManagement) {
cfg.sortDependencyManagement = sortDependencyManagement;
return this;
}

public SortPomGradleConfig sortDependencyExclusions(String sortDependencyExclusions) {
cfg.sortDependencyExclusions = sortDependencyExclusions;
return this;
}

public SortPomGradleConfig sortPlugins(String sortPlugins) {
cfg.sortPlugins = sortPlugins;
return this;
}

public SortPomGradleConfig sortProperties(boolean sortProperties) {
cfg.sortProperties = sortProperties;
return this;
}

public SortPomGradleConfig sortModules(boolean sortModules) {
cfg.sortModules = sortModules;
return this;
}

public SortPomGradleConfig sortExecutions(boolean sortExecutions) {
cfg.sortExecutions = sortExecutions;
return this;
}

private FormatterStep createStep() {
return SortPomStep.create(cfg, provisioner());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,12 @@ public void go(Action<GoExtension> closure) {
format(GoExtension.NAME, GoExtension.class, closure);
}

/** Configures the special POM-specific extension. */
public void pom(Action<PomExtension> closure) {
requireNonNull(closure);
format(PomExtension.NAME, PomExtension.class, closure);
}

/** Configures a custom extension. */
public void format(String name, Action<FormatExtension> closure) {
requireNonNull(name, "name");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright 2024 DiffPlug
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.diffplug.gradle.spotless;

import org.junit.jupiter.api.Test;

class SortPomGradleTest extends GradleIntegrationHarness {
@Test
void sortPom() throws Exception {
// given
setFile("build.gradle").toLines(
"plugins {",
" id 'com.diffplug.spotless'",
"}",
"repositories { mavenCentral() }",
"spotless {",
" pom {",
" sortPom()",
" }",
"}");
setFile("pom.xml").toResource("pom/pom_dirty.xml");

// when
gradleRunner().withArguments("spotlessApply").build();

// then
assertFile("pom.xml").sameAsResource("pom/pom_clean_default.xml");
}

@Test
void sortPomWithTarget() throws Exception {
// given
setFile("build.gradle").toLines(
"plugins {",
" id 'com.diffplug.spotless'",
"}",
"repositories { mavenCentral() }",
"spotless {",
" pom {",
" target('test.xml')",
" sortPom()",
" }",
"}");
setFile("test.xml").toResource("pom/pom_dirty.xml");

// when
gradleRunner().withArguments("spotlessApply").build();

// then
assertFile("test.xml").sameAsResource("pom/pom_clean_default.xml");
}

@Test
void sortPomWithVersion() throws Exception {
// given
setFile("build.gradle").toLines(
"plugins {",
" id 'com.diffplug.spotless'",
"}",
"repositories { mavenCentral() }",
"spotless {",
" pom {",
" sortPom '3.4.0'",
" }",
"}");
setFile("pom.xml").toResource("pom/pom_dirty.xml");

// when
gradleRunner().withArguments("spotlessApply").build();

// then
assertFile("pom.xml").sameAsResource("pom/pom_clean_default.xml");
}

@Test
void sortPomWithParameters() throws Exception {
// given
setFile("build.gradle").toLines(
"plugins {",
" id 'com.diffplug.spotless'",
"}",
"repositories { mavenCentral() }",
"spotless {",
" pom {",
" sortPom()",
" .encoding('UTF-8')",
" .lineSeparator(System.getProperty('line.separator'))",
" .expandEmptyElements(true)",
" .spaceBeforeCloseEmptyElement(false)",
" .keepBlankLines(true)",
" .endWithNewline(true)",
" .nrOfIndentSpace(2)",
" .indentBlankLines(false)",
" .indentSchemaLocation(false)",
" .predefinedSortOrder('recommended_2008_06')",
" .sortOrderFile(null)",
" .sortDependencies(null)",
" .sortDependencyManagement(null)",
" .sortDependencyExclusions(null)",
" .sortPlugins(null)",
" .sortProperties(false)",
" .sortModules(false)",
" .sortExecutions(false)",
" }",
"}");
setFile("pom.xml").toResource("pom/pom_dirty.xml");

// when
gradleRunner().withArguments("spotlessApply").build();

// then
assertFile("pom.xml").sameAsResource("pom/pom_clean_default.xml");
}
}
Loading
Loading