Skip to content

Commit 46ee809

Browse files
authored
feat: add support for prettier 3+ (#1760)
2 parents 0c0be38 + b4a118a commit 46ee809

31 files changed

+311
-120
lines changed

CHANGES.md

+5
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+
### Fixed
14+
* Add support for `prettier` version `3.0.0` and newer. ([#1760]https://github.com/diffplug/spotless/pull/1760), [#1751](https://github.com/diffplug/spotless/issues/1751))
15+
* Fix npm install calls when npm cache is not up-to-date. ([#1760]https://github.com/diffplug/spotless/pull/1760), [#1750](https://github.com/diffplug/spotless/issues/1750))
16+
### Changes
17+
* Bump default `prettier` version to latest (v2) `2.8.1` -> `2.8.8`. ([#1760](https://github.com/diffplug/spotless/pull/1760))
1318

1419
## [2.40.0] - 2023-07-17
1520
### Added

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

+28-1
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@
1515
*/
1616
package com.diffplug.spotless.npm;
1717

18+
import static com.diffplug.spotless.npm.NpmProcessFactory.OnlinePreferrence.PREFER_OFFLINE;
19+
import static com.diffplug.spotless.npm.NpmProcessFactory.OnlinePreferrence.PREFER_ONLINE;
20+
1821
import java.util.Objects;
1922

2023
import javax.annotation.Nonnull;
2124

2225
import org.slf4j.Logger;
2326
import org.slf4j.LoggerFactory;
2427

28+
import com.diffplug.spotless.ProcessRunner;
29+
2530
public class NodeApp {
2631

2732
private static final Logger logger = LoggerFactory.getLogger(NodeApp.class);
@@ -83,6 +88,28 @@ void prepareNodeAppLayout() {
8388

8489
void npmInstall() {
8590
timedLogger.withInfo("Installing npm dependencies for {} with {}.", this.nodeServerLayout, this.npmProcessFactory.describe())
86-
.run(() -> npmProcessFactory.createNpmInstallProcess(nodeServerLayout, formatterStepLocations).waitFor());
91+
.run(this::optimizedNpmInstall);
92+
}
93+
94+
private void optimizedNpmInstall() {
95+
try {
96+
npmProcessFactory.createNpmInstallProcess(nodeServerLayout, formatterStepLocations, PREFER_OFFLINE).waitFor();
97+
} catch (NpmProcessException e) {
98+
if (!offlineInstallFailed(e.getResult())) {
99+
throw e; // pass through
100+
}
101+
// if the npm install fails with message "No matching version found for <package>@<version>", we try again without the offline flag
102+
npmProcessFactory.createNpmInstallProcess(nodeServerLayout, formatterStepLocations, PREFER_ONLINE).waitFor();
103+
}
104+
}
105+
106+
private boolean offlineInstallFailed(ProcessRunner.Result result) {
107+
if (result == null) {
108+
return false; // no result, something else must have happened
109+
}
110+
if (result.exitCode() == 0) {
111+
return false; // all is well
112+
}
113+
return result.stdOutUtf8().contains("code ETARGET") && result.stdOutUtf8().contains("No matching version found for"); // offline install failed, needs online install
87114
}
88115
}

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ public static NodeModulesCachingNpmProcessFactory create(@Nonnull File cacheDir)
5858
}
5959

6060
@Override
61-
public NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations) {
62-
NpmProcess actualNpmInstallProcess = StandardNpmProcessFactory.INSTANCE.createNpmInstallProcess(nodeServerLayout, formatterStepLocations);
61+
public NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations, OnlinePreferrence onlinePreferrence) {
62+
NpmProcess actualNpmInstallProcess = StandardNpmProcessFactory.INSTANCE.createNpmInstallProcess(nodeServerLayout, formatterStepLocations, onlinePreferrence);
6363
return new CachingNmpInstall(actualNpmInstallProcess, nodeServerLayout);
6464
}
6565

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

+13-1
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,26 @@
1515
*/
1616
package com.diffplug.spotless.npm;
1717

18+
import javax.annotation.CheckForNull;
19+
20+
import com.diffplug.spotless.ProcessRunner;
21+
1822
public class NpmProcessException extends RuntimeException {
1923
private static final long serialVersionUID = 6424331316676759525L;
24+
private final transient ProcessRunner.Result result;
2025

21-
public NpmProcessException(String message) {
26+
public NpmProcessException(String message, ProcessRunner.Result result) {
2227
super(message);
28+
this.result = result;
2329
}
2430

2531
public NpmProcessException(String message, Throwable cause) {
2632
super(message, cause);
33+
this.result = null;
34+
}
35+
36+
@CheckForNull
37+
public ProcessRunner.Result getResult() {
38+
return result;
2739
}
2840
}

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

+16-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,22 @@
1616
package com.diffplug.spotless.npm;
1717

1818
public interface NpmProcessFactory {
19-
NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations);
19+
20+
enum OnlinePreferrence {
21+
PREFER_OFFLINE("--prefer-offline"), PREFER_ONLINE("--prefer-online");
22+
23+
private final String option;
24+
25+
OnlinePreferrence(String option) {
26+
this.option = option;
27+
}
28+
29+
public String option() {
30+
return option;
31+
}
32+
}
33+
34+
NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations, OnlinePreferrence onlinePreferrence);
2035

2136
NpmLongRunningProcess createNpmServeProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations);
2237

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ public class PrettierFormatterStep {
4141

4242
public static final String NAME = "prettier-format";
4343

44+
public static final String DEFAULT_VERSION = "2.8.8";
45+
4446
public static final Map<String, String> defaultDevDependencies() {
45-
return defaultDevDependenciesWithPrettier("2.8.1");
47+
return defaultDevDependenciesWithPrettier(DEFAULT_VERSION);
4648
}
4749

4850
public static final Map<String, String> defaultDevDependenciesWithPrettier(String version) {

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

+8-5
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ private StandardNpmProcessFactory() {
3232
}
3333

3434
@Override
35-
public NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations) {
36-
return new NpmInstall(nodeServerLayout.nodeModulesDir(), formatterStepLocations);
35+
public NpmProcess createNpmInstallProcess(NodeServerLayout nodeServerLayout, NpmFormatterStepLocations formatterStepLocations, OnlinePreferrence onlinePreferrence) {
36+
return new NpmInstall(nodeServerLayout.nodeModulesDir(), formatterStepLocations, onlinePreferrence);
3737
}
3838

3939
@Override
@@ -80,8 +80,11 @@ public String doDescribe() {
8080

8181
private static class NpmInstall extends AbstractStandardNpmProcess implements NpmProcess {
8282

83-
public NpmInstall(File workingDir, NpmFormatterStepLocations formatterStepLocations) {
83+
private final OnlinePreferrence onlinePreferrence;
84+
85+
public NpmInstall(File workingDir, NpmFormatterStepLocations formatterStepLocations, OnlinePreferrence onlinePreferrence) {
8486
super(workingDir, formatterStepLocations);
87+
this.onlinePreferrence = onlinePreferrence;
8588
}
8689

8790
@Override
@@ -91,7 +94,7 @@ protected List<String> commandLine() {
9194
"install",
9295
"--no-audit",
9396
"--no-fund",
94-
"--prefer-offline");
97+
onlinePreferrence.option());
9598
}
9699

97100
@Override
@@ -103,7 +106,7 @@ public String describe() {
103106
public ProcessRunner.Result waitFor() {
104107
try (ProcessRunner.LongRunningProcess npmProcess = doStart()) {
105108
if (npmProcess.waitFor() != 0) {
106-
throw new NpmProcessException("Running npm command '" + describe() + "' failed with exit code: " + npmProcess.exitValue() + "\n\n" + npmProcess.result());
109+
throw new NpmProcessException("Running npm command '" + describe() + "' failed with exit code: " + npmProcess.exitValue() + "\n\n" + npmProcess.result(), npmProcess.result());
107110
}
108111
return npmProcess.result();
109112
} catch (InterruptedException e) {
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
const prettier = require("prettier");
22

33
app.post("/prettier/config-options", (req, res) => {
4-
var config_data = req.body;
5-
var prettier_config_path = config_data.prettier_config_path;
6-
var prettier_config_options = config_data.prettier_config_options || {};
4+
const config_data = req.body;
5+
const prettier_config_path = config_data.prettier_config_path;
6+
const prettier_config_options = config_data.prettier_config_options || {};
77

88
if (prettier_config_path) {
99
prettier
1010
.resolveConfig(undefined, { config: prettier_config_path })
1111
.then(options => {
12-
var mergedConfigOptions = mergeConfigOptions(options, prettier_config_options);
12+
const mergedConfigOptions = mergeConfigOptions(options, prettier_config_options);
1313
res.set("Content-Type", "application/json")
1414
res.json(mergedConfigOptions);
1515
})
@@ -20,12 +20,12 @@ app.post("/prettier/config-options", (req, res) => {
2020
res.json(prettier_config_options);
2121
});
2222

23-
app.post("/prettier/format", (req, res) => {
24-
var format_data = req.body;
23+
app.post("/prettier/format", async (req, res) => {
24+
const format_data = req.body;
2525

26-
var formatted_file_content = "";
26+
let formatted_file_content = "";
2727
try {
28-
formatted_file_content = prettier.format(format_data.file_content, format_data.config_options);
28+
formatted_file_content = await prettierFormat(format_data.file_content, format_data.config_options);
2929
} catch(err) {
3030
res.status(500).send("Error while formatting: " + err);
3131
return;
@@ -34,7 +34,20 @@ app.post("/prettier/format", (req, res) => {
3434
res.send(formatted_file_content);
3535
});
3636

37-
var mergeConfigOptions = function(resolved_config_options, config_options) {
37+
const prettierFormat = async function(file_content, config_options) {
38+
const result = prettier.format(file_content, config_options);
39+
40+
// Check if result is a Promise (version 3.0.0 and above)
41+
if (typeof result.then === 'function') {
42+
return result;
43+
}
44+
45+
// If it's not a Promise (meaning it's a string), wrap it in a Promise (< 3.0.0)
46+
return Promise.resolve(result);
47+
}
48+
49+
50+
const mergeConfigOptions = function(resolved_config_options, config_options) {
3851
if (resolved_config_options !== undefined && config_options !== undefined) {
3952
return extend(resolved_config_options, config_options);
4053
}
@@ -46,15 +59,15 @@ var mergeConfigOptions = function(resolved_config_options, config_options) {
4659
}
4760
};
4861

49-
var extend = function() {
62+
const extend = function() {
5063
// Variables
51-
var extended = {};
52-
var i = 0;
53-
var length = arguments.length;
64+
const extended = {};
65+
let i = 0;
66+
const length = arguments.length;
5467

5568
// Merge the object into the extended object
56-
var merge = function(obj) {
57-
for (var prop in obj) {
69+
const merge = function (obj) {
70+
for (const prop in obj) {
5871
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
5972
extended[prop] = obj[prop];
6073
}
@@ -63,9 +76,8 @@ var extend = function() {
6376

6477
// Loop through each object and conduct a merge
6578
for (; i < length; i++) {
66-
var obj = arguments[i];
79+
const obj = arguments[i];
6780
merge(obj);
6881
}
69-
7082
return extended;
7183
};

plugin-gradle/CHANGES.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (starting after version `3.27.0`).
44

55
## [Unreleased]
6+
### Fixed
7+
* Add support for `prettier` version `3.0.0` and newer. ([#1760]https://github.com/diffplug/spotless/pull/1760), [#1751](https://github.com/diffplug/spotless/issues/1751))
8+
* Fix npm install calls when npm cache is not up-to-date. ([#1760]https://github.com/diffplug/spotless/pull/1760), [#1750](https://github.com/diffplug/spotless/issues/1750))
9+
### Changes
10+
* Bump default `prettier` version to latest (v2) `2.8.1` -> `2.8.8`. ([#1760](https://github.com/diffplug/spotless/pull/1760))
611

712
## [6.20.0] - 2023-07-17
813
### Added
@@ -23,7 +28,6 @@ We adhere to the [keepachangelog](https://keepachangelog.com/en/1.0.0/) format (
2328
* Bump default `ktlint` version to latest `0.49.1` -> `0.50.0`. ([#1741](https://github.com/diffplug/spotless/issues/1741))
2429
* Dropped support for `ktlint 0.47.x` following our policy of supporting two breaking changes at a time.
2530
* Dropped support for deprecated `useExperimental` parameter in favor of the `ktlint_experimental` property.
26-
2731
## [6.19.0] - 2023-05-24
2832
### Added
2933
* Support Rome as a formatter for JavaScript and TypeScript code. Adds a new `rome` step to `javascript` and `typescript` formatter configurations. ([#1663](https://github.com/diffplug/spotless/pull/1663))

plugin-gradle/README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,7 @@ spotless {
882882
yaml {
883883
target 'src/**/*.yaml' // you have to set the target manually
884884
jackson() // has its own section below
885+
prettier() // has its own section below
885886
}
886887
}
887888
```
@@ -978,11 +979,11 @@ Since spotless uses the actual npm prettier package behind the scenes, it is pos
978979
```gradle
979980
spotless {
980981
java {
981-
prettier(['prettier': '2.0.5', 'prettier-plugin-java': '0.8.0']).config(['parser': 'java', 'tabWidth': 4])
982+
prettier(['prettier': '2.8.8', 'prettier-plugin-java': '2.2.0']).config(['parser': 'java', 'tabWidth': 4])
982983
}
983984
format 'php', {
984985
target 'src/**/*.php'
985-
prettier(['prettier': '2.0.5', '@prettier/plugin-php': '0.14.2']).config(['parser': 'php', 'tabWidth': 3])
986+
prettier(['prettier': '2.8.8', '@prettier/plugin-php': '0.19.6']).config(['parser': 'php', 'tabWidth': 3])
986987
}
987988
}
988989
```

plugin-gradle/src/test/java/com/diffplug/gradle/spotless/NpmInstallCacheIntegrationTests.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ private BuildResult runPhpPrettierOnDir(File projDir, File cacheDir) throws IOEx
112112
"prettierConfig['tabWidth'] = 3",
113113
"prettierConfig['parser'] = 'php'",
114114
"def prettierPackages = [:]",
115-
"prettierPackages['prettier'] = '2.0.5'",
116-
"prettierPackages['@prettier/plugin-php'] = '0.14.2'",
115+
"prettierPackages['prettier'] = '2.8.8'",
116+
"prettierPackages['@prettier/plugin-php'] = '0.19.6'",
117117
"spotless {",
118118
" format 'php', {",
119119
" target 'php-example.php'",

0 commit comments

Comments
 (0)