Skip to content

Commit c0668ad

Browse files
committed
Merge branch 'main' into config_cache
2 parents 32a5317 + d95083d commit c0668ad

File tree

49 files changed

+2098
-211
lines changed

Some content is hidden

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

49 files changed

+2098
-211
lines changed

CHANGES.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
1111

1212
## [Unreleased]
1313

14+
## [2.36.0] - 2023-02-27
15+
### Added
16+
* `gradlew equoIde` opens a repeatable clean Spotless dev environment. ([#1523](https://github.com/diffplug/spotless/pull/1523))
17+
* `cleanthat` added `includeDraft` option, to include draft mutators from composite mutators. ([#1574](https://github.com/diffplug/spotless/pull/1574))
18+
* `npm`-based formatters now support caching of `node_modules` directory ([#1590](https://github.com/diffplug/spotless/pull/1590))
19+
### Fixed
20+
* `JacksonJsonFormatterFunc` handles json files with an Array as root. ([#1585](https://github.com/diffplug/spotless/pull/1585))
21+
### Changes
22+
* Bump default `cleanthat` version to latest `2.1` -> `2.6` ([#1569](https://github.com/diffplug/spotless/pull/1569) and [#1574](https://github.com/diffplug/spotless/pull/1574))
23+
* Reduce logging-noise created by `npm`-based formatters ([#1590](https://github.com/diffplug/spotless/pull/1590) fixes [#1582](https://github.com/diffplug/spotless/issues/1582))
24+
1425
## [2.35.0] - 2023-02-10
1526
### Added
1627
* CleanThat Java Refactorer. ([#1560](https://github.com/diffplug/spotless/pull/1560))

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Contributing to Spotless
22

3-
Pull requests are welcome, preferably against `main`. Feel free to develop spotless any way you like.
3+
Pull requests are welcome, preferably against `main`. Feel free to develop spotless any way you like, but if you like Eclipse and Gradle Buildship then [`gradlew equoIde` will install an IDE and set it up for you](https://github.com/equodev/equo-ide).
44

55
## How Spotless works
66

build.gradle

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
plugins {
2+
// https://github.com/equodev/equo-ide/blob/main/plugin-gradle/CHANGELOG.md
3+
id 'dev.equo.ide' version '0.16.0'
4+
}
5+
equoIde {
6+
branding().title('Spotless').icon(file('_images/spotless_logo.png'))
7+
welcome().openUrl('https://github.com/diffplug/spotless/blob/main/CONTRIBUTING.md')
8+
gradleBuildship()
9+
}
10+
11+
repositories {
12+
mavenCentral()
13+
}
14+
115
apply from: rootProject.file('gradle/java-publish.gradle')
216
apply from: rootProject.file('gradle/changelog.gradle')
317
allprojects {

lib/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ tasks.named("check").configure {
5656

5757
dependencies {
5858
compileOnly 'org.slf4j:slf4j-api:2.0.0'
59+
testCommonImplementation 'org.slf4j:slf4j-api:2.0.0'
60+
5961
// zero runtime reqs is a hard requirements for spotless-lib
6062
// if you need a dep, put it in lib-extra
6163
testCommonImplementation "org.junit.jupiter:junit-jupiter:$VER_JUNIT"

lib/src/jackson/java/com/diffplug/spotless/glue/json/AJacksonFormatterFunc.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package com.diffplug.spotless.glue.json;
1717

1818
import java.io.IOException;
19-
import java.util.Map;
2019

2120
import com.fasterxml.jackson.core.JsonFactory;
2221
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -49,7 +48,7 @@ public String apply(String input) throws Exception {
4948
protected String format(ObjectMapper objectMapper, String input) throws IllegalArgumentException, IOException {
5049
try {
5150
// ObjectNode is not compatible with SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS
52-
Map objectNode = objectMapper.readValue(input, Map.class);
51+
Object objectNode = objectMapper.readValue(input, inferType(input));
5352
String output = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectNode);
5453

5554
return output;
@@ -58,6 +57,13 @@ protected String format(ObjectMapper objectMapper, String input) throws IllegalA
5857
}
5958
}
6059

60+
/**
61+
*
62+
* @param input
63+
* @return the {@link Class} into which the String has to be deserialized
64+
*/
65+
protected abstract Class<?> inferType(String input);
66+
6167
/**
6268
* @return a {@link JsonFactory}. May be overridden to handle alternative formats.
6369
* @see <a href="https://github.com/FasterXML/jackson-dataformats-text">jackson-dataformats-text</a>

lib/src/jackson/java/com/diffplug/spotless/glue/json/JacksonJsonFormatterFunc.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
*/
1616
package com.diffplug.spotless.glue.json;
1717

18+
import java.util.Collection;
19+
import java.util.Map;
20+
1821
import com.fasterxml.jackson.core.JsonFactory;
1922
import com.fasterxml.jackson.core.JsonFactoryBuilder;
2023
import com.fasterxml.jackson.core.JsonGenerator;
@@ -37,6 +40,15 @@ public JacksonJsonFormatterFunc(JacksonJsonConfig jacksonConfig) {
3740
this.jacksonConfig = jacksonConfig;
3841
}
3942

43+
@Override
44+
protected Class<?> inferType(String input) {
45+
if (input.trim().startsWith("[")) {
46+
return Collection.class;
47+
} else {
48+
return Map.class;
49+
}
50+
}
51+
4052
/**
4153
* @return a {@link JsonFactory}. May be overridden to handle alternative formats.
4254
* @see <a href="https://github.com/FasterXML/jackson-dataformats-text">jackson-dataformats-text</a>

lib/src/jackson/java/com/diffplug/spotless/glue/yaml/JacksonYamlFormatterFunc.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,18 @@ protected JsonFactory makeJsonFactory() {
5858
return yamlFactoryBuilder.build();
5959
}
6060

61+
@Override
62+
protected Class<?> inferType(String input) {
63+
return JsonNode.class;
64+
}
65+
6166
@Override
6267
protected String format(ObjectMapper objectMapper, String input) throws IllegalArgumentException, IOException {
6368
try {
6469
// https://stackoverflow.com/questions/25222327/deserialize-pojos-from-multiple-yaml-documents-in-a-single-file-in-jackson
6570
// https://github.com/FasterXML/jackson-dataformats-text/issues/66#issuecomment-375328648
6671
JsonParser yamlParser = objectMapper.getFactory().createParser(input);
67-
List<JsonNode> documents = objectMapper.readValues(yamlParser, JsonNode.class).readAll();
72+
List<?> documents = objectMapper.readValues(yamlParser, inferType(input)).readAll();
6873

6974
// https://github.com/FasterXML/jackson-dataformats-text/issues/66#issuecomment-554265055
7075
// https://github.com/FasterXML/jackson-dataformats-text/issues/66#issuecomment-554265055

lib/src/main/java/com/diffplug/spotless/json/package-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
@ParametersAreNonnullByDefault
22
@ReturnValuesAreNonnullByDefault
3-
package com.diffplug.spotless.extra.json.java;
3+
package com.diffplug.spotless.json;
44

55
import javax.annotation.ParametersAreNonnullByDefault;
66

lib/src/main/java/com/diffplug/spotless/npm/EslintFormatterStep.java

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

18-
import static com.diffplug.spotless.LazyArgLogger.lazy;
1918
import static java.util.Objects.requireNonNull;
2019

2120
import java.io.File;
@@ -71,13 +70,13 @@ public static Map<String, String> defaultDevDependenciesWithEslint(String versio
7170
return Collections.singletonMap("eslint", version);
7271
}
7372

74-
public static FormatterStep create(Map<String, String> devDependencies, Provisioner provisioner, File projectDir, File buildDir, NpmPathResolver npmPathResolver, EslintConfig eslintConfig) {
73+
public static FormatterStep create(Map<String, String> devDependencies, Provisioner provisioner, File projectDir, File buildDir, File cacheDir, NpmPathResolver npmPathResolver, EslintConfig eslintConfig) {
7574
requireNonNull(devDependencies);
7675
requireNonNull(provisioner);
7776
requireNonNull(projectDir);
7877
requireNonNull(buildDir);
7978
return FormatterStep.createLazy(NAME,
80-
() -> new State(NAME, devDependencies, projectDir, buildDir, npmPathResolver, eslintConfig),
79+
() -> new State(NAME, devDependencies, projectDir, buildDir, cacheDir, npmPathResolver, eslintConfig),
8180
State::createFormatterFunc);
8281
}
8382

@@ -89,20 +88,20 @@ private static class State extends NpmFormatterStepStateBase implements Serializ
8988
@SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED")
9089
private transient EslintConfig eslintConfigInUse;
9190

92-
State(String stepName, Map<String, String> devDependencies, File projectDir, File buildDir, NpmPathResolver npmPathResolver, EslintConfig eslintConfig) throws IOException {
91+
State(String stepName, Map<String, String> devDependencies, File projectDir, File buildDir, File cacheDir, NpmPathResolver npmPathResolver, EslintConfig eslintConfig) throws IOException {
9392
super(stepName,
9493
new NpmConfig(
9594
replaceDevDependencies(
9695
NpmResourceHelper.readUtf8StringFromClasspath(EslintFormatterStep.class, "/com/diffplug/spotless/npm/eslint-package.json"),
9796
new TreeMap<>(devDependencies)),
98-
"eslint",
9997
NpmResourceHelper.readUtf8StringFromClasspath(EslintFormatterStep.class,
10098
"/com/diffplug/spotless/npm/common-serve.js",
10199
"/com/diffplug/spotless/npm/eslint-serve.js"),
102100
npmPathResolver.resolveNpmrcContent()),
103101
new NpmFormatterStepLocations(
104102
projectDir,
105103
buildDir,
104+
cacheDir,
106105
npmPathResolver::resolveNpmExecutable,
107106
npmPathResolver::resolveNodeExecutable));
108107
this.origEslintConfig = requireNonNull(eslintConfig.verify());
@@ -116,7 +115,7 @@ protected void prepareNodeServerLayout() throws IOException {
116115
// If any config files are provided, we need to make sure they are at the same location as the node modules
117116
// as eslint will try to resolve plugin/config names relatively to the config file location and some
118117
// eslint configs contain relative paths to additional config files (such as tsconfig.json e.g.)
119-
logger.info("Copying config file <{}> to <{}> and using the copy", origEslintConfig.getEslintConfigPath(), nodeServerLayout.nodeModulesDir());
118+
logger.debug("Copying config file <{}> to <{}> and using the copy", origEslintConfig.getEslintConfigPath(), nodeServerLayout.nodeModulesDir());
120119
File configFileCopy = NpmResourceHelper.copyFileToDir(origEslintConfig.getEslintConfigPath(), nodeServerLayout.nodeModulesDir());
121120
this.eslintConfigInUse = this.origEslintConfig.withEslintConfigPath(configFileCopy).verify();
122121
}
@@ -162,8 +161,6 @@ public EslintFilePathPassingFormatterFunc(File projectDir, File nodeModulesDir,
162161

163162
@Override
164163
public String applyWithFile(String unix, File file) throws Exception {
165-
logger.info("formatting String '{}[...]' in file '{}'", lazy(() -> unix.substring(0, Math.min(50, unix.length()))), file);
166-
167164
Map<FormatOption, Object> eslintCallOptions = new HashMap<>();
168165
setConfigToCallOptions(eslintCallOptions);
169166
setFilePathToCallOptions(eslintCallOptions, file);
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright 2023 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.npm;
17+
18+
import java.util.Objects;
19+
20+
import javax.annotation.Nonnull;
21+
22+
import org.slf4j.Logger;
23+
import org.slf4j.LoggerFactory;
24+
25+
public class NodeApp {
26+
27+
private static final Logger logger = LoggerFactory.getLogger(NodeApp.class);
28+
29+
private static final TimedLogger timedLogger = TimedLogger.forLogger(logger);
30+
31+
@Nonnull
32+
protected final NodeServerLayout nodeServerLayout;
33+
34+
@Nonnull
35+
protected final NpmConfig npmConfig;
36+
37+
@Nonnull
38+
protected final NpmProcessFactory npmProcessFactory;
39+
40+
@Nonnull
41+
protected final NpmFormatterStepLocations formatterStepLocations;
42+
43+
public NodeApp(@Nonnull NodeServerLayout nodeServerLayout, @Nonnull NpmConfig npmConfig, @Nonnull NpmFormatterStepLocations formatterStepLocations) {
44+
this.nodeServerLayout = Objects.requireNonNull(nodeServerLayout);
45+
this.npmConfig = Objects.requireNonNull(npmConfig);
46+
this.npmProcessFactory = processFactory(formatterStepLocations);
47+
this.formatterStepLocations = Objects.requireNonNull(formatterStepLocations);
48+
}
49+
50+
private static NpmProcessFactory processFactory(NpmFormatterStepLocations formatterStepLocations) {
51+
if (formatterStepLocations.cacheDir() != null) {
52+
logger.info("Caching npm install results in {}.", formatterStepLocations.cacheDir());
53+
return NodeModulesCachingNpmProcessFactory.create(formatterStepLocations.cacheDir());
54+
}
55+
logger.debug("Not caching npm install results.");
56+
return StandardNpmProcessFactory.INSTANCE;
57+
}
58+
59+
boolean needsNpmInstall() {
60+
return !this.nodeServerLayout.isNodeModulesPrepared();
61+
}
62+
63+
boolean needsPrepareNodeAppLayout() {
64+
return !this.nodeServerLayout.isLayoutPrepared();
65+
}
66+
67+
void prepareNodeAppLayout() {
68+
timedLogger.withInfo("Preparing {} for npm step {}.", this.nodeServerLayout, getClass().getName()).run(() -> {
69+
NpmResourceHelper.assertDirectoryExists(nodeServerLayout.nodeModulesDir());
70+
NpmResourceHelper.writeUtf8StringToFile(nodeServerLayout.packageJsonFile(), this.npmConfig.getPackageJsonContent());
71+
if (this.npmConfig.getServeScriptContent() != null) {
72+
NpmResourceHelper.writeUtf8StringToFile(nodeServerLayout.serveJsFile(), this.npmConfig.getServeScriptContent());
73+
} else {
74+
NpmResourceHelper.deleteFileIfExists(nodeServerLayout.serveJsFile());
75+
}
76+
if (this.npmConfig.getNpmrcContent() != null) {
77+
NpmResourceHelper.writeUtf8StringToFile(nodeServerLayout.npmrcFile(), this.npmConfig.getNpmrcContent());
78+
} else {
79+
NpmResourceHelper.deleteFileIfExists(nodeServerLayout.npmrcFile());
80+
}
81+
});
82+
}
83+
84+
void npmInstall() {
85+
timedLogger.withInfo("Installing npm dependencies for {} with {}.", this.nodeServerLayout, this.npmProcessFactory.describe())
86+
.run(() -> npmProcessFactory.createNpmInstallProcess(nodeServerLayout, formatterStepLocations).waitFor());
87+
}
88+
}

0 commit comments

Comments
 (0)