Skip to content

Commit ac9feda

Browse files
committed
Merge branch 'main' into fix/github-actions
2 parents 7b8ed50 + 1effefb commit ac9feda

File tree

23 files changed

+286
-175
lines changed

23 files changed

+286
-175
lines changed

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ This document is intended for Spotless developers.
1010
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `1.27.0`).
1111

1212
## [Unreleased]
13+
### Added
14+
* Added `skipLinesMatching` option to `licenseHeader` to support formats where license header cannot be immediately added to the top of the file (e.g. xml, sh). ([#1441](https://github.com/diffplug/spotless/pull/1441)).
15+
### Fixed
16+
* Support `ktlint` 0.48+ new rule disabling syntax ([#1456](https://github.com/diffplug/spotless/pull/1456)) fixes ([#1444](https://github.com/diffplug/spotless/issues/1444))
17+
1318
### Changes
1419
* Bump the dev version of Gradle from `7.5.1` to `7.6` ([#1409](https://github.com/diffplug/spotless/pull/1409))
1520
* We also removed the no-longer-required dependency `org.codehaus.groovy:groovy-xml`
@@ -18,6 +23,7 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
1823
* `StepHarness` now operates on `Formatter` rather than a `FormatterStep`
1924
* `StepHarnessWithFile` now takes a `ResourceHarness` in its constructor to handle the file manipulation parts
2025
* Standardized that we test exception *messages*, not types, which will ease the transition to linting later on
26+
* Bump default `ktlint` version to latest `0.47.1` -> `0.48.1` ([#1456](https://github.com/diffplug/spotless/pull/1456))
2127

2228
## [2.31.1] - 2023-01-02
2329
### Fixed

lib/build.gradle

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ dependencies {
4545
compileOnly 'org.slf4j:slf4j-api:2.0.0'
4646
// zero runtime reqs is a hard requirements for spotless-lib
4747
// if you need a dep, put it in lib-extra
48-
testImplementation "org.junit.jupiter:junit-jupiter:$VER_JUNIT"
49-
testImplementation "org.assertj:assertj-core:$VER_ASSERTJ"
50-
testImplementation "com.diffplug.durian:durian-testlib:$VER_DURIAN"
48+
testCommonImplementation "org.junit.jupiter:junit-jupiter:$VER_JUNIT"
49+
testCommonImplementation "org.assertj:assertj-core:$VER_ASSERTJ"
50+
testCommonImplementation "com.diffplug.durian:durian-testlib:$VER_DURIAN"
5151

5252
// used for pom sorting
5353
sortPomCompileOnly 'com.github.ekryd.sortpom:sortpom-sorter:3.0.0'
@@ -91,9 +91,9 @@ dependencies {
9191
compatKtLint0Dot47Dot0CompileOnly 'com.pinterest.ktlint:ktlint-core:0.47.0'
9292
compatKtLint0Dot47Dot0CompileOnly 'com.pinterest.ktlint:ktlint-ruleset-experimental:0.47.0'
9393
compatKtLint0Dot47Dot0CompileOnly 'com.pinterest.ktlint:ktlint-ruleset-standard:0.47.0'
94-
compatKtLint0Dot48Dot0CompileOnly 'com.pinterest.ktlint:ktlint-core:0.48.0'
95-
compatKtLint0Dot48Dot0CompileOnly 'com.pinterest.ktlint:ktlint-ruleset-experimental:0.48.0'
96-
compatKtLint0Dot48Dot0CompileOnly 'com.pinterest.ktlint:ktlint-ruleset-standard:0.48.0'
94+
compatKtLint0Dot48Dot0CompileAndTestOnly 'com.pinterest.ktlint:ktlint-core:0.48.0'
95+
compatKtLint0Dot48Dot0CompileAndTestOnly 'com.pinterest.ktlint:ktlint-ruleset-experimental:0.48.0'
96+
compatKtLint0Dot48Dot0CompileAndTestOnly 'com.pinterest.ktlint:ktlint-ruleset-standard:0.48.0'
9797

9898
String VER_SCALAFMT="3.6.1"
9999
scalafmtCompileOnly "org.scalameta:scalafmt-core_2.13:$VER_SCALAFMT"
@@ -108,7 +108,9 @@ dependencies {
108108
// we'll hold the core lib to a high standard
109109
spotbugs { reportLevel = 'low' } // low|medium|high (low = sensitive to even minor mistakes)
110110

111-
test { useJUnitPlatform() }
111+
tasks.withType(Test).configureEach {
112+
useJUnitPlatform()
113+
}
112114

113115
jar {
114116
for (glue in NEEDS_GLUE) {

lib/src/compatKtLint0Dot48Dot0/java/com/diffplug/spotless/glue/ktlint/compat/KtLintCompat0Dot48Dot0Adapter.java

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package com.diffplug.spotless.glue.ktlint.compat;
1717

18+
import java.util.ArrayList;
19+
import java.util.Collections;
1820
import java.util.LinkedHashSet;
1921
import java.util.List;
2022
import java.util.Map;
@@ -27,11 +29,17 @@
2729
import com.pinterest.ktlint.core.LintError;
2830
import com.pinterest.ktlint.core.Rule;
2931
import com.pinterest.ktlint.core.RuleProvider;
30-
import com.pinterest.ktlint.core.api.DefaultEditorConfigProperties;
3132
import com.pinterest.ktlint.core.api.EditorConfigDefaults;
3233
import com.pinterest.ktlint.core.api.EditorConfigOverride;
3334
import com.pinterest.ktlint.core.api.UsesEditorConfigProperties;
35+
import com.pinterest.ktlint.core.api.editorconfig.CodeStyleEditorConfigPropertyKt;
36+
import com.pinterest.ktlint.core.api.editorconfig.DisabledRulesEditorConfigPropertyKt;
3437
import com.pinterest.ktlint.core.api.editorconfig.EditorConfigProperty;
38+
import com.pinterest.ktlint.core.api.editorconfig.IndentSizeEditorConfigPropertyKt;
39+
import com.pinterest.ktlint.core.api.editorconfig.IndentStyleEditorConfigPropertyKt;
40+
import com.pinterest.ktlint.core.api.editorconfig.InsertFinalNewLineEditorConfigPropertyKt;
41+
import com.pinterest.ktlint.core.api.editorconfig.MaxLineLengthEditorConfigPropertyKt;
42+
import com.pinterest.ktlint.core.api.editorconfig.RuleExecutionEditorConfigPropertyKt;
3543
import com.pinterest.ktlint.ruleset.experimental.ExperimentalRuleSetProvider;
3644
import com.pinterest.ktlint.ruleset.standard.StandardRuleSetProvider;
3745

@@ -41,13 +49,29 @@
4149

4250
public class KtLintCompat0Dot48Dot0Adapter implements KtLintCompatAdapter {
4351

52+
private static final List<EditorConfigProperty<?>> DEFAULT_EDITOR_CONFIG_PROPERTIES;
53+
54+
static {
55+
List<EditorConfigProperty<?>> list = new ArrayList<>();
56+
list.add(CodeStyleEditorConfigPropertyKt.getCODE_STYLE_PROPERTY());
57+
//noinspection deprecation
58+
list.add(DisabledRulesEditorConfigPropertyKt.getDISABLED_RULES_PROPERTY());
59+
//noinspection KotlinInternalInJava,deprecation
60+
list.add(DisabledRulesEditorConfigPropertyKt.getKTLINT_DISABLED_RULES_PROPERTY());
61+
list.add(IndentStyleEditorConfigPropertyKt.getINDENT_STYLE_PROPERTY());
62+
list.add(IndentSizeEditorConfigPropertyKt.getINDENT_SIZE_PROPERTY());
63+
list.add(InsertFinalNewLineEditorConfigPropertyKt.getINSERT_FINAL_NEWLINE_PROPERTY());
64+
list.add(MaxLineLengthEditorConfigPropertyKt.getMAX_LINE_LENGTH_PROPERTY());
65+
DEFAULT_EDITOR_CONFIG_PROPERTIES = Collections.unmodifiableList(list);
66+
}
67+
4468
static class FormatterCallback implements Function2<LintError, Boolean, Unit> {
4569
@Override
4670
public Unit invoke(LintError lint, Boolean corrected) {
4771
if (!corrected) {
4872
KtLintCompatReporting.report(lint.getLine(), lint.getCol(), lint.getRuleId(), lint.getDetail());
4973
}
50-
return null;
74+
return Unit.INSTANCE;
5175
}
5276
}
5377

@@ -66,7 +90,7 @@ public String format(final String text, final String name, final boolean isScrip
6690

6791
EditorConfigOverride editorConfigOverride;
6892
if (editorConfigOverrideMap.isEmpty()) {
69-
editorConfigOverride = EditorConfigOverride.Companion.getEmptyEditorConfigOverride();
93+
editorConfigOverride = EditorConfigOverride.Companion.getEMPTY_EDITOR_CONFIG_OVERRIDE();
7094
} else {
7195
editorConfigOverride = createEditorConfigOverride(allRuleProviders.stream().map(
7296
RuleProvider::createNewRuleInstance).collect(
@@ -82,7 +106,7 @@ public String format(final String text, final String name, final boolean isScrip
82106
formatterCallback,
83107
isScript,
84108
false,
85-
EditorConfigDefaults.Companion.getEmptyEditorConfigDefaults(),
109+
EditorConfigDefaults.Companion.getEMPTY_EDITOR_CONFIG_DEFAULTS(),
86110
editorConfigOverride,
87111
false));
88112
}
@@ -98,7 +122,7 @@ private static EditorConfigOverride createEditorConfigOverride(final List<Rule>
98122

99123
// Create a mapping of properties to their names based on rule properties and default properties
100124
Map<String, EditorConfigProperty<?>> supportedProperties = Stream
101-
.concat(ruleProperties, DefaultEditorConfigProperties.INSTANCE.getEditorConfigProperties().stream())
125+
.concat(ruleProperties, DEFAULT_EDITOR_CONFIG_PROPERTIES.stream())
102126
.distinct()
103127
.collect(Collectors.toMap(EditorConfigProperty::getName, property -> property));
104128

@@ -109,6 +133,18 @@ private static EditorConfigOverride createEditorConfigOverride(final List<Rule>
109133
EditorConfigProperty<?> property = supportedProperties.get(entry.getKey());
110134
if (property != null) {
111135
return new Pair<>(property, entry.getValue());
136+
} else if (entry.getKey().startsWith("ktlint_")) {
137+
String[] parts = entry.getKey().substring(7).split("_", 2);
138+
if (parts.length == 1) {
139+
// convert ktlint_{ruleset} to {ruleset}
140+
String qualifiedRuleId = parts[0];
141+
property = RuleExecutionEditorConfigPropertyKt.createRuleSetExecutionEditorConfigProperty(qualifiedRuleId);
142+
} else {
143+
// convert ktlint_{ruleset}_{rulename} to {ruleset}:{rulename}
144+
String qualifiedRuleId = parts[0] + ":" + parts[1];
145+
property = RuleExecutionEditorConfigPropertyKt.createRuleExecutionEditorConfigProperty(qualifiedRuleId);
146+
}
147+
return new Pair<>(property, entry.getValue());
112148
} else {
113149
return null;
114150
}

lib/src/main/java/com/diffplug/spotless/generic/LicenseHeaderStep.java

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2021 DiffPlug
2+
* Copyright 2016-2023 DiffPlug
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -51,7 +51,7 @@ public static LicenseHeaderStep headerDelimiter(String header, String delimiter)
5151
}
5252

5353
public static LicenseHeaderStep headerDelimiter(ThrowingEx.Supplier<String> headerLazy, String delimiter) {
54-
return new LicenseHeaderStep(null, null, headerLazy, delimiter, DEFAULT_YEAR_DELIMITER, () -> YearMode.PRESERVE);
54+
return new LicenseHeaderStep(null, null, headerLazy, delimiter, DEFAULT_YEAR_DELIMITER, () -> YearMode.PRESERVE, null);
5555
}
5656

5757
final String name;
@@ -60,50 +60,56 @@ public static LicenseHeaderStep headerDelimiter(ThrowingEx.Supplier<String> head
6060
final String delimiter;
6161
final String yearSeparator;
6262
final Supplier<YearMode> yearMode;
63+
final @Nullable String skipLinesMatching;
6364

64-
private LicenseHeaderStep(@Nullable String name, @Nullable String contentPattern, ThrowingEx.Supplier<String> headerLazy, String delimiter, String yearSeparator, Supplier<YearMode> yearMode) {
65+
private LicenseHeaderStep(@Nullable String name, @Nullable String contentPattern, ThrowingEx.Supplier<String> headerLazy, String delimiter, String yearSeparator, Supplier<YearMode> yearMode, @Nullable String skipLinesMatching) {
6566
this.name = sanitizeName(name);
66-
this.contentPattern = sanitizeContentPattern(contentPattern);
67+
this.contentPattern = sanitizePattern(contentPattern);
6768
this.headerLazy = Objects.requireNonNull(headerLazy);
6869
this.delimiter = Objects.requireNonNull(delimiter);
6970
this.yearSeparator = Objects.requireNonNull(yearSeparator);
7071
this.yearMode = Objects.requireNonNull(yearMode);
72+
this.skipLinesMatching = sanitizePattern(skipLinesMatching);
7173
}
7274

7375
public String getName() {
7476
return name;
7577
}
7678

7779
public LicenseHeaderStep withName(String name) {
78-
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode);
80+
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesMatching);
7981
}
8082

8183
public LicenseHeaderStep withContentPattern(String contentPattern) {
82-
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode);
84+
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesMatching);
8385
}
8486

8587
public LicenseHeaderStep withHeaderString(String header) {
8688
return withHeaderLazy(() -> header);
8789
}
8890

8991
public LicenseHeaderStep withHeaderLazy(ThrowingEx.Supplier<String> headerLazy) {
90-
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode);
92+
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesMatching);
9193
}
9294

9395
public LicenseHeaderStep withDelimiter(String delimiter) {
94-
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode);
96+
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesMatching);
9597
}
9698

9799
public LicenseHeaderStep withYearSeparator(String yearSeparator) {
98-
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode);
100+
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesMatching);
99101
}
100102

101103
public LicenseHeaderStep withYearMode(YearMode yearMode) {
102104
return withYearModeLazy(() -> yearMode);
103105
}
104106

105107
public LicenseHeaderStep withYearModeLazy(Supplier<YearMode> yearMode) {
106-
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode);
108+
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesMatching);
109+
}
110+
111+
public LicenseHeaderStep withSkipLinesMatching(@Nullable String skipLinesMatching) {
112+
return new LicenseHeaderStep(name, contentPattern, headerLazy, delimiter, yearSeparator, yearMode, skipLinesMatching);
107113
}
108114

109115
public FormatterStep build() {
@@ -112,7 +118,7 @@ public FormatterStep build() {
112118
if (yearMode.get() == YearMode.SET_FROM_GIT) {
113119
formatterStep = FormatterStep.createNeverUpToDateLazy(name, () -> {
114120
boolean updateYear = false; // doesn't matter
115-
Runtime runtime = new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear);
121+
Runtime runtime = new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear, skipLinesMatching);
116122
return FormatterFunc.needsFile(runtime::setLicenseHeaderYearsFromGitHistory);
117123
});
118124
} else {
@@ -130,7 +136,7 @@ public FormatterStep build() {
130136
default:
131137
throw new IllegalStateException(yearMode.toString());
132138
}
133-
return new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear);
139+
return new Runtime(headerLazy.get(), delimiter, yearSeparator, updateYear, skipLinesMatching);
134140
}, step -> step::format);
135141
}
136142

@@ -156,18 +162,18 @@ private String sanitizeName(@Nullable String name) {
156162
}
157163

158164
@Nullable
159-
private String sanitizeContentPattern(@Nullable String contentPattern) {
160-
if (contentPattern == null) {
161-
return contentPattern;
165+
private String sanitizePattern(@Nullable String pattern) {
166+
if (pattern == null) {
167+
return pattern;
162168
}
163169

164-
contentPattern = contentPattern.trim();
170+
pattern = pattern.trim();
165171

166-
if (contentPattern.isEmpty()) {
172+
if (pattern.isEmpty()) {
167173
return null;
168174
}
169175

170-
return contentPattern;
176+
return pattern;
171177
}
172178

173179
private static final String DEFAULT_NAME_PREFIX = LicenseHeaderStep.class.getName();
@@ -195,6 +201,7 @@ private static class Runtime implements Serializable {
195201
private static final long serialVersionUID = 1475199492829130965L;
196202

197203
private final Pattern delimiterPattern;
204+
private final @Nullable Pattern skipLinesMatching;
198205
private final String yearSepOrFull;
199206
private final @Nullable String yearToday;
200207
private final @Nullable String beforeYear;
@@ -203,7 +210,7 @@ private static class Runtime implements Serializable {
203210
private final boolean licenseHeaderWithRange;
204211

205212
/** The license that we'd like enforced. */
206-
private Runtime(String licenseHeader, String delimiter, String yearSeparator, boolean updateYearWithLatest) {
213+
private Runtime(String licenseHeader, String delimiter, String yearSeparator, boolean updateYearWithLatest, @Nullable String skipLinesMatching) {
207214
if (delimiter.contains("\n")) {
208215
throw new IllegalArgumentException("The delimiter must not contain any newlines.");
209216
}
@@ -213,6 +220,7 @@ private Runtime(String licenseHeader, String delimiter, String yearSeparator, bo
213220
licenseHeader = licenseHeader + "\n";
214221
}
215222
this.delimiterPattern = Pattern.compile('^' + delimiter, Pattern.UNIX_LINES | Pattern.MULTILINE);
223+
this.skipLinesMatching = skipLinesMatching == null ? null : Pattern.compile(skipLinesMatching);
216224

217225
Optional<String> yearToken = getYearToken(licenseHeader);
218226
if (yearToken.isPresent()) {
@@ -254,6 +262,31 @@ private static Optional<String> getYearToken(String licenseHeader) {
254262

255263
/** Formats the given string. */
256264
private String format(String raw) {
265+
if (skipLinesMatching == null) {
266+
return addOrUpdateLicenseHeader(raw);
267+
} else {
268+
String[] lines = raw.split("\n");
269+
StringBuilder skippedLinesBuilder = new StringBuilder();
270+
StringBuilder remainingLinesBuilder = new StringBuilder();
271+
boolean lastMatched = true;
272+
for (String line : lines) {
273+
if (lastMatched) {
274+
Matcher matcher = skipLinesMatching.matcher(line);
275+
if (matcher.find()) {
276+
skippedLinesBuilder.append(line).append('\n');
277+
} else {
278+
remainingLinesBuilder.append(line).append('\n');
279+
lastMatched = false;
280+
}
281+
} else {
282+
remainingLinesBuilder.append(line).append('\n');
283+
}
284+
}
285+
return skippedLinesBuilder + addOrUpdateLicenseHeader(remainingLinesBuilder.toString());
286+
}
287+
}
288+
289+
private String addOrUpdateLicenseHeader(String raw) {
257290
Matcher contentMatcher = delimiterPattern.matcher(raw);
258291
if (!contentMatcher.find()) {
259292
throw new IllegalArgumentException("Unable to find delimiter regex " + delimiterPattern);

lib/src/main/java/com/diffplug/spotless/kotlin/KtLintStep.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public class KtLintStep {
3333
// prevent direct instantiation
3434
private KtLintStep() {}
3535

36-
private static final String DEFAULT_VERSION = "0.48.0";
36+
private static final String DEFAULT_VERSION = "0.48.1";
3737
static final String NAME = "ktlint";
3838
static final String PACKAGE_PRE_0_32 = "com.github.shyiko";
3939
static final String PACKAGE = "com.pinterest";

0 commit comments

Comments
 (0)