Skip to content

Commit 50c389b

Browse files
committed
fix(oxfmt): Support .editorconfig quote_type (#20989)
Fixes #20563 --- - [x] Merge oxc-project/editorconfig-parser#42 - [x] Release oxc-project/editorconfig-parser#43 - [x] Update crates version - [x] Implement - [x] Test - [x] Update schema, snapshots
1 parent 60b1678 commit 50c389b

12 files changed

Lines changed: 61 additions & 12 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ tracing-subscriber = "0.3.22" # Tracing implementation
236236
ureq = { version = "3.1.4", default-features = false } # HTTP client
237237
url = { version = "2.5.8" } # URL parsing
238238
walkdir = "2.5.0" # Directory traversal
239-
editorconfig-parser = "0.0.3"
239+
editorconfig-parser = "0.0.4"
240240
natord = "1.0.9"
241241
oxfmt = { path = "apps/oxfmt" }
242242
sort-package-json = "0.0.12"

apps/oxfmt/src-js/config.generated.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ export interface Oxfmtrc {
158158
* For JSX, you can set the `jsxSingleQuote` option.
159159
*
160160
* - Default: `false`
161+
* - Overrides `.editorconfig.quote_type`
161162
*/
162163
singleQuote?: boolean;
163164
/**
@@ -435,6 +436,7 @@ export interface FormatConfig {
435436
* For JSX, you can set the `jsxSingleQuote` option.
436437
*
437438
* - Default: `false`
439+
* - Overrides `.editorconfig.quote_type`
438440
*/
439441
singleQuote?: boolean;
440442
/**

apps/oxfmt/src/core/config.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::path::{Path, PathBuf};
22

33
use editorconfig_parser::{
44
EditorConfig, EditorConfigProperties, EditorConfigProperty, EndOfLine, IndentStyle,
5-
MaxLineLength,
5+
MaxLineLength, QuoteType,
66
};
77
use fast_glob::glob_match;
88
use serde_json::Value;
@@ -613,6 +613,7 @@ fn load_editorconfig(
613613
/// - indent_size
614614
/// - tab_width
615615
/// - insert_final_newline
616+
/// - quote_type
616617
fn has_editorconfig_overrides(editorconfig: &EditorConfig, path: &Path) -> bool {
617618
let sections = editorconfig.sections();
618619

@@ -635,6 +636,7 @@ fn has_editorconfig_overrides(editorconfig: &EditorConfig, path: &Path) -> bool
635636
|| resolved.indent_size != root.indent_size
636637
|| resolved.tab_width != root.tab_width
637638
|| resolved.insert_final_newline != root.insert_final_newline
639+
|| resolved.quote_type != root.quote_type
638640
}
639641
// No `[*]` section means any resolved property is an override
640642
None => {
@@ -644,6 +646,7 @@ fn has_editorconfig_overrides(editorconfig: &EditorConfig, path: &Path) -> bool
644646
|| resolved.indent_size != EditorConfigProperty::Unset
645647
|| resolved.tab_width != EditorConfigProperty::Unset
646648
|| resolved.insert_final_newline != EditorConfigProperty::Unset
649+
|| resolved.quote_type != EditorConfigProperty::Unset
647650
}
648651
}
649652
}
@@ -697,4 +700,16 @@ fn apply_editorconfig(config: &mut FormatConfig, props: &EditorConfigProperties)
697700
{
698701
config.insert_final_newline = Some(v);
699702
}
703+
704+
if config.single_quote.is_none() {
705+
match props.quote_type {
706+
EditorConfigProperty::Value(QuoteType::Single) => {
707+
config.single_quote = Some(true);
708+
}
709+
EditorConfigProperty::Value(QuoteType::Double) => {
710+
config.single_quote = Some(false);
711+
}
712+
_ => {}
713+
}
714+
}
700715
}

apps/oxfmt/src/core/oxfmtrc/format_config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ pub struct FormatConfig {
8888
/// For JSX, you can set the `jsxSingleQuote` option.
8989
///
9090
/// - Default: `false`
91+
/// - Overrides `.editorconfig.quote_type`
9192
#[serde(skip_serializing_if = "Option::is_none")]
9293
pub single_quote: Option<bool>,
9394
/// Use single quotes instead of double quotes in JSX.

apps/oxfmt/test/cli/editorconfig/__snapshots__/editorconfig.test.ts.snap

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,20 @@ nested/deep/test.json
154154
--------------------"
155155
`;
156156
157+
exports[`editorconfig > quote_type maps to singleQuote 1`] = `
158+
"--- FILE -----------
159+
test.js
160+
--- BEFORE ---------
161+
const a = "hello";
162+
const b = "world";
163+
164+
--- AFTER ----------
165+
const a = 'hello';
166+
const b = 'world';
167+
168+
--------------------"
169+
`;
170+
157171
exports[`editorconfig > tab_width fallback when indent_size is not set 1`] = `
158172
"--- FILE -----------
159173
test.js

apps/oxfmt/test/cli/editorconfig/editorconfig.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,17 @@ describe("editorconfig", () => {
9090
expect(snapshot).toMatchSnapshot();
9191
});
9292

93+
// .editorconfig:
94+
// [*] quote_type=single
95+
//
96+
// Expected: singleQuote=true
97+
// - String literals should use single quotes instead of double quotes
98+
it("quote_type maps to singleQuote", async () => {
99+
const cwd = join(fixturesDir, "quote_type");
100+
const snapshot = await runWriteModeAndSnapshot(cwd, ["test.js"]);
101+
expect(snapshot).toMatchSnapshot();
102+
});
103+
93104
// .editorconfig: (empty file)
94105
//
95106
// Expected: default settings (useTabs=false, tabWidth=2)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[*]
2+
quote_type = single
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const a = "hello";
2+
const b = "world";

npm/oxfmt/configuration_schema.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@
130130
"markdownDescription": "Enforce single attribute per line in HTML, Vue, and JSX.\n\n- Default: `false`"
131131
},
132132
"singleQuote": {
133-
"description": "Use single quotes instead of double quotes.\n\nFor JSX, you can set the `jsxSingleQuote` option.\n\n- Default: `false`",
133+
"description": "Use single quotes instead of double quotes.\n\nFor JSX, you can set the `jsxSingleQuote` option.\n\n- Default: `false`\n- Overrides `.editorconfig.quote_type`",
134134
"type": "boolean",
135-
"markdownDescription": "Use single quotes instead of double quotes.\n\nFor JSX, you can set the `jsxSingleQuote` option.\n\n- Default: `false`"
135+
"markdownDescription": "Use single quotes instead of double quotes.\n\nFor JSX, you can set the `jsxSingleQuote` option.\n\n- Default: `false`\n- Overrides `.editorconfig.quote_type`"
136136
},
137137
"sortImports": {
138138
"description": "Sort import statements.\n\nUsing the similar algorithm as [eslint-plugin-perfectionist/sort-imports](https://perfectionist.dev/rules/sort-imports).\nFor details, see each field's documentation.\n\nPass `true` or an object to enable with defaults, or omit/set `false` to disable.\n\n- Default: Disabled",
@@ -359,9 +359,9 @@
359359
"markdownDescription": "Enforce single attribute per line in HTML, Vue, and JSX.\n\n- Default: `false`"
360360
},
361361
"singleQuote": {
362-
"description": "Use single quotes instead of double quotes.\n\nFor JSX, you can set the `jsxSingleQuote` option.\n\n- Default: `false`",
362+
"description": "Use single quotes instead of double quotes.\n\nFor JSX, you can set the `jsxSingleQuote` option.\n\n- Default: `false`\n- Overrides `.editorconfig.quote_type`",
363363
"type": "boolean",
364-
"markdownDescription": "Use single quotes instead of double quotes.\n\nFor JSX, you can set the `jsxSingleQuote` option.\n\n- Default: `false`"
364+
"markdownDescription": "Use single quotes instead of double quotes.\n\nFor JSX, you can set the `jsxSingleQuote` option.\n\n- Default: `false`\n- Overrides `.editorconfig.quote_type`"
365365
},
366366
"sortImports": {
367367
"description": "Sort import statements.\n\nUsing the similar algorithm as [eslint-plugin-perfectionist/sort-imports](https://perfectionist.dev/rules/sort-imports).\nFor details, see each field's documentation.\n\nPass `true` or an object to enable with defaults, or omit/set `false` to disable.\n\n- Default: Disabled",

0 commit comments

Comments
 (0)