From 4790eaf7c71c20080e1dbc629ba79c08d2d75e47 Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Thu, 31 Oct 2024 14:17:52 +0900 Subject: [PATCH] feat: add `overrides` option to `yml/plain-scalar` (#374) * feat: add `overrides` option to `yml/plain-scalar` * Create chilled-emus-tap.md --- .changeset/chilled-emus-tap.md | 5 ++ docs/rules/plain-scalar.md | 4 ++ src/rules/plain-scalar.ts | 71 +++++++++++++++---- .../invalid/override-mapping-key/_config.json | 3 + .../override-mapping-key/map-test-errors.json | 22 ++++++ .../override-mapping-key/map-test-input.yml | 4 ++ .../override-mapping-key/map-test-output.yml | 5 ++ .../override-mapping-key/seq-test-errors.json | 12 ++++ .../override-mapping-key/seq-test-input.yml | 3 + .../override-mapping-key/seq-test-output.yml | 4 ++ .../valid/override-mapping-key/_config.json | 3 + .../override-mapping-key/map-test-input.yml | 2 + .../override-mapping-key/seq-test-input.yml | 3 + tests/utils/utils.ts | 3 +- 14 files changed, 131 insertions(+), 13 deletions(-) create mode 100644 .changeset/chilled-emus-tap.md create mode 100644 tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/_config.json create mode 100644 tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/map-test-errors.json create mode 100644 tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/map-test-input.yml create mode 100644 tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/map-test-output.yml create mode 100644 tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/seq-test-errors.json create mode 100644 tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/seq-test-input.yml create mode 100644 tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/seq-test-output.yml create mode 100644 tests/fixtures/rules/plain-scalar/valid/override-mapping-key/_config.json create mode 100644 tests/fixtures/rules/plain-scalar/valid/override-mapping-key/map-test-input.yml create mode 100644 tests/fixtures/rules/plain-scalar/valid/override-mapping-key/seq-test-input.yml diff --git a/.changeset/chilled-emus-tap.md b/.changeset/chilled-emus-tap.md new file mode 100644 index 00000000..bc63b0f9 --- /dev/null +++ b/.changeset/chilled-emus-tap.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-yml": minor +--- + +feat: add `overrides` option to `yml/plain-scalar` diff --git a/docs/rules/plain-scalar.md b/docs/rules/plain-scalar.md index d0bfa871..b842f454 100644 --- a/docs/rules/plain-scalar.md +++ b/docs/rules/plain-scalar.md @@ -41,12 +41,16 @@ yml/plain-scalar: - always # or "never" - ignorePatterns: - "[\\v\\f\\u0085\\u00a0\\u1680\\u180e\\u2000-\\u200b\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]" + overrides: + mappingKey: null # or "always" or "never" ``` - `"always"` ... Enforce the use of plain style scalars. - `"never"` ... Disallow the use of plain style scalars. - `ignorePatterns` ... Specify the pattern to be excluded from the check as an array. If `"always"`, the default is `[ "[\\v\\f\\u0085\\u00a0\\u1680\\u180e\\u2000-\\u200b\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]" ]`. It to ignores irregular whitespace. +- `overrides` ... Overrides any setting to a specific value. + - `mappingKey` ... Specify the style to use for the mapping key. ## :couple: Related rules diff --git a/src/rules/plain-scalar.ts b/src/rules/plain-scalar.ts index 62a1043f..5282c513 100644 --- a/src/rules/plain-scalar.ts +++ b/src/rules/plain-scalar.ts @@ -68,6 +68,13 @@ export default createRule("plain-scalar", { type: "array", items: { type: "string" }, }, + overrides: { + type: "object", + properties: { + mappingKey: { enum: ["always", "never", null] }, + }, + additionalProperties: false, + }, }, additionalProperties: false, }, @@ -83,16 +90,39 @@ export default createRule("plain-scalar", { if (!sourceCode.parserServices.isYAML) { return {}; } - const option: "always" | "never" = context.options[0] || "always"; - const ignorePatterns: RegExp[] = toRegExps( - context.options[1]?.ignorePatterns ?? - (option === "always" - ? [ - // Irregular white spaces - String.raw`[\v\f\u0085\u00a0\u1680\u180e\u2000-\u200b\u2028\u2029\u202f\u205f\u3000\ufeff]`, - ] - : []), - ); + type Option = { + prefer: "always" | "never"; + ignorePatterns: RegExp[]; + }; + const valueOption: Option = { + prefer: context.options[0] || "always", + ignorePatterns: [], + }; + const overridesMappingKey = context.options[1]?.overrides?.mappingKey; + const keyOption: Option = overridesMappingKey + ? { + prefer: overridesMappingKey, + ignorePatterns: [], + } + : valueOption; + if (context.options[1]?.ignorePatterns) { + valueOption.ignorePatterns = toRegExps( + context.options[1]?.ignorePatterns, + ); + } else { + if (valueOption.prefer === "always") { + valueOption.ignorePatterns = toRegExps([ + // Irregular white spaces + String.raw`[\v\f\u0085\u00a0\u1680\u180e\u2000-\u200b\u2028\u2029\u202f\u205f\u3000\ufeff]`, + ]); + } + if (overridesMappingKey && keyOption.prefer === "always") { + keyOption.ignorePatterns = toRegExps([ + // Irregular white spaces + String.raw`[\v\f\u0085\u00a0\u1680\u180e\u2000-\u200b\u2028\u2029\u202f\u205f\u3000\ufeff]`, + ]); + } + } let currentDocument: AST.YAMLDocument | undefined; @@ -202,6 +232,21 @@ export default createRule("plain-scalar", { }); } + /** + * Checks whether the given node is within key + */ + function withinKey(node: AST.YAMLScalar | AST.YAMLWithMeta) { + const parent = node.parent; + if (parent.type === "YAMLPair" && parent.key === node) { + return true; + } + const grandParent = parent.parent; + if (grandParent.type === "YAMLWithMeta") { + return withinKey(grandParent); + } + return false; + } + return { YAMLDocument(node) { currentDocument = node; @@ -210,10 +255,12 @@ export default createRule("plain-scalar", { if (!isStringScalar(node)) { return; } - if (ignorePatterns.some((p) => p.test(node.value))) { + const option = withinKey(node) ? keyOption : valueOption; + + if (option.ignorePatterns.some((p) => p.test(node.value))) { return; } - if (option === "always") { + if (option.prefer === "always") { verifyAlways(node); } else { verifyNever(node); diff --git a/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/_config.json b/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/_config.json new file mode 100644 index 00000000..e01dea65 --- /dev/null +++ b/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/_config.json @@ -0,0 +1,3 @@ +{ + "options": ["never", { "overrides": { "mappingKey": "always" } }] +} diff --git a/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/map-test-errors.json b/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/map-test-errors.json new file mode 100644 index 00000000..caeac89a --- /dev/null +++ b/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/map-test-errors.json @@ -0,0 +1,22 @@ +[ + { + "message": "Must use quoted style scalar.", + "line": 2, + "column": 6 + }, + { + "message": "Must use plain style scalar.", + "line": 3, + "column": 3 + }, + { + "message": "Must use quoted style scalar.", + "line": 4, + "column": 8 + }, + { + "message": "Must use plain style scalar.", + "line": 5, + "column": 5 + } +] diff --git a/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/map-test-input.yml b/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/map-test-input.yml new file mode 100644 index 00000000..4a258d5e --- /dev/null +++ b/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/map-test-input.yml @@ -0,0 +1,4 @@ +- a: b +- "a": "b" +- { a: b } +- { "a": "b" } diff --git a/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/map-test-output.yml b/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/map-test-output.yml new file mode 100644 index 00000000..3dbee324 --- /dev/null +++ b/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/map-test-output.yml @@ -0,0 +1,5 @@ +# plain-scalar/invalid/override-mapping-key/map-test-input.yml +- a: "b" +- a: "b" +- { a: "b" } +- { a: "b" } diff --git a/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/seq-test-errors.json b/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/seq-test-errors.json new file mode 100644 index 00000000..40aa1c1e --- /dev/null +++ b/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/seq-test-errors.json @@ -0,0 +1,12 @@ +[ + { + "message": "Must use quoted style scalar.", + "line": 2, + "column": 3 + }, + { + "message": "Must use quoted style scalar.", + "line": 4, + "column": 4 + } +] diff --git a/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/seq-test-input.yml b/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/seq-test-input.yml new file mode 100644 index 00000000..fab74df5 --- /dev/null +++ b/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/seq-test-input.yml @@ -0,0 +1,3 @@ +- a +- "b" +- [a, "b"] diff --git a/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/seq-test-output.yml b/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/seq-test-output.yml new file mode 100644 index 00000000..6fc3473d --- /dev/null +++ b/tests/fixtures/rules/plain-scalar/invalid/override-mapping-key/seq-test-output.yml @@ -0,0 +1,4 @@ +# plain-scalar/invalid/override-mapping-key/seq-test-input.yml +- "a" +- "b" +- ["a", "b"] diff --git a/tests/fixtures/rules/plain-scalar/valid/override-mapping-key/_config.json b/tests/fixtures/rules/plain-scalar/valid/override-mapping-key/_config.json new file mode 100644 index 00000000..e01dea65 --- /dev/null +++ b/tests/fixtures/rules/plain-scalar/valid/override-mapping-key/_config.json @@ -0,0 +1,3 @@ +{ + "options": ["never", { "overrides": { "mappingKey": "always" } }] +} diff --git a/tests/fixtures/rules/plain-scalar/valid/override-mapping-key/map-test-input.yml b/tests/fixtures/rules/plain-scalar/valid/override-mapping-key/map-test-input.yml new file mode 100644 index 00000000..69ea7849 --- /dev/null +++ b/tests/fixtures/rules/plain-scalar/valid/override-mapping-key/map-test-input.yml @@ -0,0 +1,2 @@ +- a: "b" +- { a: "b" } diff --git a/tests/fixtures/rules/plain-scalar/valid/override-mapping-key/seq-test-input.yml b/tests/fixtures/rules/plain-scalar/valid/override-mapping-key/seq-test-input.yml new file mode 100644 index 00000000..d89e6e61 --- /dev/null +++ b/tests/fixtures/rules/plain-scalar/valid/override-mapping-key/seq-test-input.yml @@ -0,0 +1,3 @@ +- "a" +- "b" +- ["a", "b"] diff --git a/tests/utils/utils.ts b/tests/utils/utils.ts index 0f194d46..2b7c2e7c 100644 --- a/tests/utils/utils.ts +++ b/tests/utils/utils.ts @@ -305,6 +305,7 @@ function writeFixtures( const result = linter.verify( config.code, { + files: ["**/*.*"], plugins: { yml: plugin, }, @@ -321,7 +322,7 @@ function writeFixtures( yml: ymlSettings, }, }, - config.filename, + inputFile, ); if (force || !fs.existsSync(errorFile)) { fs.writeFileSync(