Skip to content

Commit e13f43f

Browse files
committed
Support editorconfig file for prettier
1 parent 8418bf0 commit e13f43f

File tree

12 files changed

+108
-29
lines changed

12 files changed

+108
-29
lines changed

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

+9-1
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,12 @@ public class PrettierConfig implements Serializable {
3232

3333
private final TreeMap<String, Object> options;
3434

35-
public PrettierConfig(@Nullable File prettierConfigPath, @Nullable Map<String, Object> options) {
35+
private final Boolean editorconfig;
36+
37+
public PrettierConfig(@Nullable File prettierConfigPath, @Nullable Map<String, Object> options, @Nullable Boolean editorconfig) {
3638
this.prettierConfigPathSignature = prettierConfigPath == null ? null : FileSignature.promise(prettierConfigPath);
3739
this.options = options == null ? new TreeMap<>() : new TreeMap<>(options);
40+
this.editorconfig = editorconfig;
3841
}
3942

4043
@Nullable
@@ -45,4 +48,9 @@ public File getPrettierConfigPath() {
4548
public Map<String, Object> getOptions() {
4649
return new TreeMap<>(this.options);
4750
}
51+
52+
@Nullable
53+
public Boolean getEditorconfig() {
54+
return editorconfig;
55+
}
4856
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public FormatterFunc createFormatterFunc() {
9090
logger.info("creating formatter function (starting server)");
9191
ServerProcessInfo prettierRestServer = toRuntime().npmRunServer();
9292
PrettierRestService restService = new PrettierRestService(prettierRestServer.getBaseUrl());
93-
String prettierConfigOptions = restService.resolveConfig(this.prettierConfig.getPrettierConfigPath(), this.prettierConfig.getOptions());
93+
String prettierConfigOptions = restService.resolveConfig(this.prettierConfig.getPrettierConfigPath(), this.prettierConfig.getOptions(), prettierConfig.getEditorconfig());
9494
return Closeable.ofDangerous(() -> endServer(restService, prettierRestServer), new PrettierFilePathPassingFormatterFunc(prettierConfigOptions, restService));
9595
} catch (IOException e) {
9696
throw ThrowingEx.asRuntime(e);

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,17 @@ public class PrettierRestService extends BaseNpmRestService {
2525
super(baseUrl);
2626
}
2727

28-
public String resolveConfig(File prettierConfigPath, Map<String, Object> prettierConfigOptions) {
28+
public String resolveConfig(File prettierConfigPath, Map<String, Object> prettierConfigOptions, Boolean editorconfig) {
2929
Map<String, Object> jsonProperties = new LinkedHashMap<>();
3030
if (prettierConfigPath != null) {
3131
jsonProperties.put("prettier_config_path", prettierConfigPath.getAbsolutePath());
3232
}
3333
if (prettierConfigOptions != null) {
3434
jsonProperties.put("prettier_config_options", JsonWriter.of(prettierConfigOptions).toJsonRawValue());
3535
}
36+
if (editorconfig != null) {
37+
jsonProperties.put("editorconfig", editorconfig);
38+
}
3639
return restClient.postJson("/prettier/config-options", jsonProperties);
3740
}
3841

lib/src/main/resources/com/diffplug/spotless/npm/prettier-serve.js

+8-13
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,14 @@ app.post("/prettier/config-options", (req, res) => {
55
const prettier_config_path = config_data.prettier_config_path;
66
const prettier_config_options = config_data.prettier_config_options || {};
77

8-
if (prettier_config_path) {
9-
prettier
10-
.resolveConfig(undefined, { config: prettier_config_path })
11-
.then(options => {
12-
const mergedConfigOptions = mergeConfigOptions(options, prettier_config_options);
13-
res.set("Content-Type", "application/json")
14-
res.json(mergedConfigOptions);
15-
})
16-
.catch(reason => res.status(501).send("Exception while resolving config_file_path: " + reason));
17-
return;
18-
}
19-
res.set("Content-Type", "application/json")
20-
res.json(prettier_config_options);
8+
prettier
9+
.resolveConfig(prettier_config_path, { editorconfig: config_data.editorconfig })
10+
.then(options => {
11+
const mergedConfigOptions = mergeConfigOptions(options, prettier_config_options);
12+
res.set("Content-Type", "application/json")
13+
res.json(mergedConfigOptions);
14+
})
15+
.catch(reason => res.status(501).send("Exception while resolving config_file_path: " + reason));
2116
});
2217

2318
app.post("/prettier/format", async (req, res) => {

plugin-gradle/src/main/java/com/diffplug/gradle/spotless/FormatExtension.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,9 @@ public class PrettierConfig extends NpmStepConfig<PrettierConfig> {
769769
@Nullable
770770
Map<String, Object> prettierConfig;
771771

772+
@Nullable
773+
Boolean editorconfig;
774+
772775
final Map<String, String> devDependencies;
773776

774777
PrettierConfig(Map<String, String> devDependencies) {
@@ -788,6 +791,12 @@ public PrettierConfig config(final Map<String, Object> prettierConfig) {
788791
return this;
789792
}
790793

794+
public PrettierConfig editorconfig(Boolean editorconfig) {
795+
this.editorconfig = editorconfig;
796+
replaceStep();
797+
return this;
798+
}
799+
791800
@Override
792801
protected FormatterStep createStep() {
793802
final Project project = getProject();
@@ -797,7 +806,7 @@ protected FormatterStep createStep() {
797806
Arrays.asList(project.getProjectDir(), project.getRootDir())),
798807
new com.diffplug.spotless.npm.PrettierConfig(
799808
this.prettierConfigFile != null ? project.file(this.prettierConfigFile) : null,
800-
this.prettierConfig));
809+
this.prettierConfig, this.editorconfig));
801810
}
802811
}
803812

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

+29
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,35 @@ void useFileConfig(String prettierVersion) throws IOException {
115115
}
116116
}
117117

118+
@ParameterizedTest(name = "{index}: useEditorconfig with prettier {0}")
119+
@ValueSource(strings = {PRETTIER_VERSION_2, PRETTIER_VERSION_3})
120+
void useEditorconfig(String prettierVersion) throws IOException {
121+
setFile(".prettierrc.yml").toResource("npm/prettier/config/.prettierrc_noop.yml");
122+
setFile(".editorconfig").toResource("npm/prettier/config/.editorconfig_20");
123+
setFile("build.gradle").toLines(
124+
"plugins {",
125+
" id 'com.diffplug.spotless'",
126+
"}",
127+
"repositories { mavenCentral() }",
128+
"spotless {",
129+
" format 'mytypescript', {",
130+
" target 'test.ts'",
131+
" prettier('" + prettierVersion + "').configFile('.prettierrc.yml').editorconfig(true)",
132+
" }",
133+
"}");
134+
setFile("test.ts").toResource("npm/prettier/config/typescript.dirty");
135+
final BuildResult spotlessApply = gradleRunner().withArguments("--stacktrace", "spotlessApply").build();
136+
Assertions.assertThat(spotlessApply.getOutput()).contains("BUILD SUCCESSFUL");
137+
switch (prettierVersion) {
138+
case PRETTIER_VERSION_2:
139+
assertFile("test.ts").sameAsResource("npm/prettier/config/typescript.configfile_prettier_2.clean");
140+
break;
141+
case PRETTIER_VERSION_3:
142+
assertFile("test.ts").sameAsResource("npm/prettier/config/typescript.configfile_prettier_3.clean");
143+
break;
144+
}
145+
}
146+
118147
@ParameterizedTest(name = "{index}: chooseParserBasedOnFilename with prettier {0}")
119148
@ValueSource(strings = {PRETTIER_VERSION_2, PRETTIER_VERSION_3})
120149
void chooseParserBasedOnFilename(String prettierVersion) throws IOException {

plugin-maven/src/main/java/com/diffplug/spotless/maven/generic/Prettier.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ public class Prettier extends AbstractNpmFormatterStepFactory {
4747
@Parameter
4848
private String configFile;
4949

50+
@Parameter
51+
private Boolean editorconfig;
52+
5053
@Override
5154
public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) {
5255

@@ -101,7 +104,7 @@ public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) {
101104
File baseDir = baseDir(stepConfig);
102105
File buildDir = buildDir(stepConfig);
103106
File cacheDir = cacheDir(stepConfig);
104-
PrettierConfig prettierConfig = new PrettierConfig(configFileHandler, configInline);
107+
PrettierConfig prettierConfig = new PrettierConfig(configFileHandler, configInline, editorconfig);
105108
NpmPathResolver npmPathResolver = npmPathResolver(stepConfig);
106109
return PrettierFormatterStep.create(devDependencies, stepConfig.getProvisioner(), baseDir, buildDir, cacheDir, npmPathResolver, prettierConfig);
107110
}

plugin-maven/src/test/java/com/diffplug/spotless/maven/prettier/PrettierFormatStepTest.java

+19
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,25 @@ void multiple_prettier_configs() throws Exception {
158158

159159
}
160160

161+
@Test
162+
void prettier_editorconfig() throws Exception {
163+
String suffix = "ts";
164+
writePomWithPrettierSteps("**/*." + suffix,
165+
"<prettier>",
166+
" <prettierVersion>1.16.4</prettierVersion>",
167+
" <configFile>.prettierrc.yml</configFile>",
168+
" <editorconfig>true</editorconfig>",
169+
"</prettier>");
170+
171+
String kind = "typescript";
172+
setFile(".prettierrc.yml").toResource("npm/prettier/config/.prettierrc_noop.yml");
173+
setFile(".editorconfig").toResource("npm/prettier/config/.editorconfig_300");
174+
String path = "src/main/" + kind + "/test." + suffix;
175+
setFile(path).toResource("npm/prettier/filetypes/" + kind + "/" + kind + ".dirty");
176+
mavenRunner().withArguments("spotless:apply").runNoError();
177+
assertFile(path).sameAsResource("npm/prettier/filetypes/" + kind + "/" + kind + ".clean");
178+
}
179+
161180
@Test
162181
void custom_plugin() throws Exception {
163182
writePomWithFormatSteps(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[*]
2+
max_line_length = 20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[*]
2+
max_line_length = 300
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
parser: typescript

testlib/src/test/java/com/diffplug/spotless/npm/PrettierFormatterStepTest.java

+19-11
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ private void runTestUsingPrettier(String fileType, Map<String, String> dependenc
6969
buildDir(),
7070
null,
7171
npmPathResolver(),
72-
new PrettierConfig(prettierRc, null));
72+
new PrettierConfig(prettierRc, null, null));
7373

7474
try (StepHarness stepHarness = StepHarness.forStep(formatterStep)) {
7575
stepHarness.testResource(dirtyFile, cleanFile);
@@ -96,7 +96,7 @@ void parserInferenceBasedOnExplicitFilepathIsWorking(String prettierVersion) thr
9696
buildDir(),
9797
null,
9898
npmPathResolver(),
99-
new PrettierConfig(null, ImmutableMap.of("filepath", "anyname.json"))); // should select parser based on this name
99+
new PrettierConfig(null, ImmutableMap.of("filepath", "anyname.json"), null)); // should select parser based on this name
100100

101101
try (StepHarness stepHarness = StepHarness.forStep(formatterStep)) {
102102
stepHarness.testResource(dirtyFile, cleanFile);
@@ -118,7 +118,7 @@ void parserInferenceBasedOnFilenameIsWorking(String prettierVersion) throws Exce
118118
buildDir(),
119119
null,
120120
npmPathResolver(),
121-
new PrettierConfig(null, Collections.emptyMap()));
121+
new PrettierConfig(null, Collections.emptyMap(), null));
122122

123123
try (StepHarnessWithFile stepHarness = StepHarnessWithFile.forStep(this, formatterStep)) {
124124
stepHarness.testResource("test.json", dirtyFile, cleanFile);
@@ -134,7 +134,7 @@ void verifyPrettierErrorMessageIsRelayed() throws Exception {
134134
buildDir(),
135135
null,
136136
npmPathResolver(),
137-
new PrettierConfig(null, ImmutableMap.of("parser", "postcss")));
137+
new PrettierConfig(null, ImmutableMap.of("parser", "postcss"), null));
138138
try (StepHarnessWithFile stepHarness = StepHarnessWithFile.forStep(this, formatterStep)) {
139139
stepHarness.expectLintsOfResource("npm/prettier/filetypes/scss/scss.dirty")
140140
.toBe("LINE_UNDEFINED prettier-format(com.diffplug.spotless.npm.SimpleRestClient$SimpleRestResponseException) Unexpected response status code at /prettier/format [HTTP 500] -- (Error while formatting: Error: Couldn't resolve parser \"postcss\") (...)");
@@ -170,19 +170,27 @@ void runFormatTest(String prettierVersion, PrettierConfig config, String cleanFi
170170
@ParameterizedTest(name = "{index}: defaults are applied with prettier {0}")
171171
@ValueSource(strings = {PRETTIER_VERSION_2, PRETTIER_VERSION_3})
172172
void defaultsAreApplied(String prettierVersion) throws Exception {
173-
runFormatTest(prettierVersion, new PrettierConfig(null, ImmutableMap.of("parser", "typescript")), "defaults_prettier_" + major(prettierVersion));
173+
runFormatTest(prettierVersion, new PrettierConfig(null, ImmutableMap.of("parser", "typescript"), null), "defaults_prettier_" + major(prettierVersion));
174174
}
175175

176176
@ParameterizedTest(name = "{index}: config file options are applied with prettier {0}")
177177
@ValueSource(strings = {PRETTIER_VERSION_2, PRETTIER_VERSION_3})
178178
void configFileOptionsAreApplied(String prettierVersion) throws Exception {
179-
runFormatTest(prettierVersion, new PrettierConfig(createTestFile(FILEDIR + ".prettierrc.yml"), null), "configfile_prettier_" + major(prettierVersion));
179+
runFormatTest(prettierVersion, new PrettierConfig(createTestFile(FILEDIR + ".prettierrc.yml"), null, null), "configfile_prettier_" + major(prettierVersion));
180180
}
181181

182-
@ParameterizedTest(name = "{index}: config file options can be overriden with prettier {0}")
182+
@ParameterizedTest(name = "{index}: config file options can be overridden with prettier {0}")
183183
@ValueSource(strings = {PRETTIER_VERSION_2, PRETTIER_VERSION_3})
184-
void configFileOptionsCanBeOverriden(String prettierVersion) throws Exception {
185-
runFormatTest(prettierVersion, new PrettierConfig(createTestFile(FILEDIR + ".prettierrc.yml"), ImmutableMap.of("printWidth", 300)), "override_prettier_" + major(prettierVersion));
184+
void configFileOptionsCanBeOverridden(String prettierVersion) throws Exception {
185+
runFormatTest(prettierVersion, new PrettierConfig(createTestFile(FILEDIR + ".prettierrc.yml"), ImmutableMap.of("printWidth", 300), null), "override_prettier_" + major(prettierVersion));
186+
}
187+
188+
@ParameterizedTest(name = "{index}: config file options can be extended with editorconfig with prettier {0}")
189+
@ValueSource(strings = {PRETTIER_VERSION_2, PRETTIER_VERSION_3})
190+
void configFileOptionsCanBeExtendedWithEditorconfig(String prettierVersion) throws Exception {
191+
setFile(".editorconfig").toResource(FILEDIR + ".editorconfig_300");
192+
File prettierConfigFile = setFile(".prettierrc.yml").toResource(FILEDIR + ".prettierrc_noop.yml");
193+
runFormatTest(prettierVersion, new PrettierConfig(prettierConfigFile, null, true), "override_prettier_" + major(prettierVersion));
186194
}
187195

188196
private String major(String semVer) {
@@ -194,7 +202,7 @@ private String major(String semVer) {
194202
void equality() {
195203
new SerializableEqualityTester() {
196204
String prettierVersion = "3.0.0";
197-
PrettierConfig config = new PrettierConfig(null, Map.of("parser", "typescript"));
205+
PrettierConfig config = new PrettierConfig(null, Map.of("parser", "typescript"), null);
198206

199207
@Override
200208
protected void setupTest(API api) {
@@ -203,7 +211,7 @@ protected void setupTest(API api) {
203211
// change the groupArtifact, and it's different
204212
prettierVersion = "2.8.8";
205213
api.areDifferentThan();
206-
config = new PrettierConfig(null, Map.of("parser", "css"));
214+
config = new PrettierConfig(null, Map.of("parser", "css"), null);
207215
api.areDifferentThan();
208216
}
209217

0 commit comments

Comments
 (0)