Skip to content

Support editorconfig file for prettier #2364

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
@@ -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
@@ -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
@@ -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);
Original file line number Diff line number Diff line change
@@ -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);
}

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
@@ -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) => {
Original file line number Diff line number Diff line change
@@ -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) {
@@ -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();
@@ -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));
}
}

Original file line number Diff line number Diff line change
@@ -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 {
Original file line number Diff line number Diff line change
@@ -47,6 +47,9 @@ public class Prettier extends AbstractNpmFormatterStepFactory {
@Parameter
private String configFile;

@Parameter
private Boolean editorconfig;

@Override
public FormatterStep newFormatterStep(FormatterStepConfig stepConfig) {

@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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(
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
@@ -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);
@@ -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);
@@ -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);
@@ -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\") (...)");
@@ -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) {
@@ -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) {
@@ -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();
}

Loading