Skip to content

Commit

Permalink
Support editorconfig file for prettier
Browse files Browse the repository at this point in the history
  • Loading branch information
skuznets0v committed Dec 13, 2024
1 parent 8418bf0 commit e13f43f
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 29 deletions.
10 changes: 9 additions & 1 deletion lib/src/main/java/com/diffplug/spotless/npm/PrettierConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,12 @@ public class PrettierConfig implements Serializable {

private final TreeMap<String, Object> options;

public PrettierConfig(@Nullable File prettierConfigPath, @Nullable Map<String, Object> options) {
private final Boolean editorconfig;

public PrettierConfig(@Nullable File prettierConfigPath, @Nullable Map<String, Object> options, @Nullable Boolean editorconfig) {
this.prettierConfigPathSignature = prettierConfigPath == null ? null : FileSignature.promise(prettierConfigPath);
this.options = options == null ? new TreeMap<>() : new TreeMap<>(options);
this.editorconfig = editorconfig;
}

@Nullable
Expand All @@ -45,4 +48,9 @@ public File getPrettierConfigPath() {
public Map<String, Object> getOptions() {
return new TreeMap<>(this.options);
}

@Nullable
public Boolean getEditorconfig() {
return editorconfig;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public FormatterFunc createFormatterFunc() {
logger.info("creating formatter function (starting server)");
ServerProcessInfo prettierRestServer = toRuntime().npmRunServer();
PrettierRestService restService = new PrettierRestService(prettierRestServer.getBaseUrl());
String prettierConfigOptions = restService.resolveConfig(this.prettierConfig.getPrettierConfigPath(), this.prettierConfig.getOptions());
String prettierConfigOptions = restService.resolveConfig(this.prettierConfig.getPrettierConfigPath(), this.prettierConfig.getOptions(), prettierConfig.getEditorconfig());
return Closeable.ofDangerous(() -> endServer(restService, prettierRestServer), new PrettierFilePathPassingFormatterFunc(prettierConfigOptions, restService));
} catch (IOException e) {
throw ThrowingEx.asRuntime(e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,17 @@ public class PrettierRestService extends BaseNpmRestService {
super(baseUrl);
}

public String resolveConfig(File prettierConfigPath, Map<String, Object> prettierConfigOptions) {
public String resolveConfig(File prettierConfigPath, Map<String, Object> prettierConfigOptions, Boolean editorconfig) {
Map<String, Object> jsonProperties = new LinkedHashMap<>();
if (prettierConfigPath != null) {
jsonProperties.put("prettier_config_path", prettierConfigPath.getAbsolutePath());
}
if (prettierConfigOptions != null) {
jsonProperties.put("prettier_config_options", JsonWriter.of(prettierConfigOptions).toJsonRawValue());
}
if (editorconfig != null) {
jsonProperties.put("editorconfig", editorconfig);
}
return restClient.postJson("/prettier/config-options", jsonProperties);
}

Expand Down
21 changes: 8 additions & 13 deletions lib/src/main/resources/com/diffplug/spotless/npm/prettier-serve.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,14 @@ app.post("/prettier/config-options", (req, res) => {
const prettier_config_path = config_data.prettier_config_path;
const prettier_config_options = config_data.prettier_config_options || {};

if (prettier_config_path) {
prettier
.resolveConfig(undefined, { config: prettier_config_path })
.then(options => {
const mergedConfigOptions = mergeConfigOptions(options, prettier_config_options);
res.set("Content-Type", "application/json")
res.json(mergedConfigOptions);
})
.catch(reason => res.status(501).send("Exception while resolving config_file_path: " + reason));
return;
}
res.set("Content-Type", "application/json")
res.json(prettier_config_options);
prettier
.resolveConfig(prettier_config_path, { editorconfig: config_data.editorconfig })
.then(options => {
const mergedConfigOptions = mergeConfigOptions(options, prettier_config_options);
res.set("Content-Type", "application/json")
res.json(mergedConfigOptions);
})
.catch(reason => res.status(501).send("Exception while resolving config_file_path: " + reason));
});

app.post("/prettier/format", async (req, res) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,9 @@ public class PrettierConfig extends NpmStepConfig<PrettierConfig> {
@Nullable
Map<String, Object> prettierConfig;

@Nullable
Boolean editorconfig;

final Map<String, String> devDependencies;

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

public PrettierConfig editorconfig(Boolean editorconfig) {
this.editorconfig = editorconfig;
replaceStep();
return this;
}

@Override
protected FormatterStep createStep() {
final Project project = getProject();
Expand All @@ -797,7 +806,7 @@ protected FormatterStep createStep() {
Arrays.asList(project.getProjectDir(), project.getRootDir())),
new com.diffplug.spotless.npm.PrettierConfig(
this.prettierConfigFile != null ? project.file(this.prettierConfigFile) : null,
this.prettierConfig));
this.prettierConfig, this.editorconfig));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,35 @@ void useFileConfig(String prettierVersion) throws IOException {
}
}

@ParameterizedTest(name = "{index}: useEditorconfig with prettier {0}")
@ValueSource(strings = {PRETTIER_VERSION_2, PRETTIER_VERSION_3})
void useEditorconfig(String prettierVersion) throws IOException {
setFile(".prettierrc.yml").toResource("npm/prettier/config/.prettierrc_noop.yml");
setFile(".editorconfig").toResource("npm/prettier/config/.editorconfig_20");
setFile("build.gradle").toLines(
"plugins {",
" id 'com.diffplug.spotless'",
"}",
"repositories { mavenCentral() }",
"spotless {",
" format 'mytypescript', {",
" target 'test.ts'",
" prettier('" + prettierVersion + "').configFile('.prettierrc.yml').editorconfig(true)",
" }",
"}");
setFile("test.ts").toResource("npm/prettier/config/typescript.dirty");
final BuildResult spotlessApply = gradleRunner().withArguments("--stacktrace", "spotlessApply").build();
Assertions.assertThat(spotlessApply.getOutput()).contains("BUILD SUCCESSFUL");
switch (prettierVersion) {
case PRETTIER_VERSION_2:
assertFile("test.ts").sameAsResource("npm/prettier/config/typescript.configfile_prettier_2.clean");
break;
case PRETTIER_VERSION_3:
assertFile("test.ts").sameAsResource("npm/prettier/config/typescript.configfile_prettier_3.clean");
break;
}
}

@ParameterizedTest(name = "{index}: chooseParserBasedOnFilename with prettier {0}")
@ValueSource(strings = {PRETTIER_VERSION_2, PRETTIER_VERSION_3})
void chooseParserBasedOnFilename(String prettierVersion) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ public class Prettier extends AbstractNpmFormatterStepFactory {
@Parameter
private String configFile;

@Parameter
private Boolean editorconfig;

@Override
public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) {

Expand Down Expand Up @@ -101,7 +104,7 @@ public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) {
File baseDir = baseDir(stepConfig);
File buildDir = buildDir(stepConfig);
File cacheDir = cacheDir(stepConfig);
PrettierConfig prettierConfig = new PrettierConfig(configFileHandler, configInline);
PrettierConfig prettierConfig = new PrettierConfig(configFileHandler, configInline, editorconfig);
NpmPathResolver npmPathResolver = npmPathResolver(stepConfig);
return PrettierFormatterStep.create(devDependencies, stepConfig.getProvisioner(), baseDir, buildDir, cacheDir, npmPathResolver, prettierConfig);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,25 @@ void multiple_prettier_configs() throws Exception {

}

@Test
void prettier_editorconfig() throws Exception {
String suffix = "ts";
writePomWithPrettierSteps("**/*." + suffix,
"<prettier>",
" <prettierVersion>1.16.4</prettierVersion>",
" <configFile>.prettierrc.yml</configFile>",
" <editorconfig>true</editorconfig>",
"</prettier>");

String kind = "typescript";
setFile(".prettierrc.yml").toResource("npm/prettier/config/.prettierrc_noop.yml");
setFile(".editorconfig").toResource("npm/prettier/config/.editorconfig_300");
String path = "src/main/" + kind + "/test." + suffix;
setFile(path).toResource("npm/prettier/filetypes/" + kind + "/" + kind + ".dirty");
mavenRunner().withArguments("spotless:apply").runNoError();
assertFile(path).sameAsResource("npm/prettier/filetypes/" + kind + "/" + kind + ".clean");
}

@Test
void custom_plugin() throws Exception {
writePomWithFormatSteps(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[*]
max_line_length = 20
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[*]
max_line_length = 300
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
parser: typescript
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ private void runTestUsingPrettier(String fileType, Map<String, String> dependenc
buildDir(),
null,
npmPathResolver(),
new PrettierConfig(prettierRc, null));
new PrettierConfig(prettierRc, null, null));

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

try (StepHarness stepHarness = StepHarness.forStep(formatterStep)) {
stepHarness.testResource(dirtyFile, cleanFile);
Expand All @@ -118,7 +118,7 @@ void parserInferenceBasedOnFilenameIsWorking(String prettierVersion) throws Exce
buildDir(),
null,
npmPathResolver(),
new PrettierConfig(null, Collections.emptyMap()));
new PrettierConfig(null, Collections.emptyMap(), null));

try (StepHarnessWithFile stepHarness = StepHarnessWithFile.forStep(this, formatterStep)) {
stepHarness.testResource("test.json", dirtyFile, cleanFile);
Expand All @@ -134,7 +134,7 @@ void verifyPrettierErrorMessageIsRelayed() throws Exception {
buildDir(),
null,
npmPathResolver(),
new PrettierConfig(null, ImmutableMap.of("parser", "postcss")));
new PrettierConfig(null, ImmutableMap.of("parser", "postcss"), null));
try (StepHarnessWithFile stepHarness = StepHarnessWithFile.forStep(this, formatterStep)) {
stepHarness.expectLintsOfResource("npm/prettier/filetypes/scss/scss.dirty")
.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\") (...)");
Expand Down Expand Up @@ -170,19 +170,27 @@ void runFormatTest(String prettierVersion, PrettierConfig config, String cleanFi
@ParameterizedTest(name = "{index}: defaults are applied with prettier {0}")
@ValueSource(strings = {PRETTIER_VERSION_2, PRETTIER_VERSION_3})
void defaultsAreApplied(String prettierVersion) throws Exception {
runFormatTest(prettierVersion, new PrettierConfig(null, ImmutableMap.of("parser", "typescript")), "defaults_prettier_" + major(prettierVersion));
runFormatTest(prettierVersion, new PrettierConfig(null, ImmutableMap.of("parser", "typescript"), null), "defaults_prettier_" + major(prettierVersion));
}

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

@ParameterizedTest(name = "{index}: config file options can be overriden with prettier {0}")
@ParameterizedTest(name = "{index}: config file options can be overridden with prettier {0}")
@ValueSource(strings = {PRETTIER_VERSION_2, PRETTIER_VERSION_3})
void configFileOptionsCanBeOverriden(String prettierVersion) throws Exception {
runFormatTest(prettierVersion, new PrettierConfig(createTestFile(FILEDIR + ".prettierrc.yml"), ImmutableMap.of("printWidth", 300)), "override_prettier_" + major(prettierVersion));
void configFileOptionsCanBeOverridden(String prettierVersion) throws Exception {
runFormatTest(prettierVersion, new PrettierConfig(createTestFile(FILEDIR + ".prettierrc.yml"), ImmutableMap.of("printWidth", 300), null), "override_prettier_" + major(prettierVersion));
}

@ParameterizedTest(name = "{index}: config file options can be extended with editorconfig with prettier {0}")
@ValueSource(strings = {PRETTIER_VERSION_2, PRETTIER_VERSION_3})
void configFileOptionsCanBeExtendedWithEditorconfig(String prettierVersion) throws Exception {
setFile(".editorconfig").toResource(FILEDIR + ".editorconfig_300");
File prettierConfigFile = setFile(".prettierrc.yml").toResource(FILEDIR + ".prettierrc_noop.yml");
runFormatTest(prettierVersion, new PrettierConfig(prettierConfigFile, null, true), "override_prettier_" + major(prettierVersion));
}

private String major(String semVer) {
Expand All @@ -194,7 +202,7 @@ private String major(String semVer) {
void equality() {
new SerializableEqualityTester() {
String prettierVersion = "3.0.0";
PrettierConfig config = new PrettierConfig(null, Map.of("parser", "typescript"));
PrettierConfig config = new PrettierConfig(null, Map.of("parser", "typescript"), null);

@Override
protected void setupTest(API api) {
Expand All @@ -203,7 +211,7 @@ protected void setupTest(API api) {
// change the groupArtifact, and it's different
prettierVersion = "2.8.8";
api.areDifferentThan();
config = new PrettierConfig(null, Map.of("parser", "css"));
config = new PrettierConfig(null, Map.of("parser", "css"), null);
api.areDifferentThan();
}

Expand Down

0 comments on commit e13f43f

Please sign in to comment.