From b6341232bea7cb9f866e8c9001c1077b89b9fc48 Mon Sep 17 00:00:00 2001 From: lumir Date: Fri, 23 Oct 2026 16:25:32 +0900 Subject: [PATCH] perf: reduce `no-missing-label-refs` time complexity from quadratic to linear --- src/rules/no-missing-label-refs.js | 16 +++++------ tests/rules/no-missing-label-refs.test.js | 33 +++++++++++++++++++++++ 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/rules/no-missing-label-refs.js b/src/rules/no-missing-label-refs.js index f98fd8b0..4e1957de 100644 --- a/src/rules/no-missing-label-refs.js +++ b/src/rules/no-missing-label-refs.js @@ -139,11 +139,15 @@ export default /** @satisfies {NoMissingLabelRefsRuleDefinition} */ ({ const allowLabels = new Set(context.options[0].allowLabels); /** @type {Array<{label:string,position:Position}>} */ - let allMissingReferences = []; + const allMissingReferences = []; return { "root:exit"() { for (const missingReference of allMissingReferences) { + if (allowLabels.has(missingReference.label)) { + continue; + } + context.report({ loc: missingReference.position, messageId: "notFound", @@ -168,15 +172,7 @@ export default /** @satisfies {NoMissingLabelRefsRuleDefinition} */ ({ }, definition(node) { - /* - * Sometimes a poorly-formatted link will end up a text node instead of a link node - * even though the label definition exists. Here, we remove any missing references - * that have a matching label definition. - */ - allMissingReferences = allMissingReferences.filter( - missingReference => - missingReference.label !== node.identifier, - ); + allowLabels.add(node.identifier); }, }; }, diff --git a/tests/rules/no-missing-label-refs.test.js b/tests/rules/no-missing-label-refs.test.js index 07ce97e2..8b5f4ecc 100644 --- a/tests/rules/no-missing-label-refs.test.js +++ b/tests/rules/no-missing-label-refs.test.js @@ -46,6 +46,10 @@ ruleTester.run("no-missing-label-refs", rule, { "foo][bar][baz]\n\n[baz]: http://baz.com", "[][foo]\n\n[foo]: http://foo.com", "[foo][bar\\]\n\n[foo]: http://foo.com", + "[foo]: http://foo.com\n\n[foo][bar", + "[foo]: http://foo.com\n\n[foo][bar\\]", + "[foo][bar\n\n[foo]: http://foo.com\n\n[foo][bar", + "[foo][bar\\]\n\n[foo]: http://foo.com\n\n[foo][bar\\]", "\\[\\]", `${"\\".repeat(3)}[${"\\".repeat(3)}]`, `${"\\".repeat(5)}[${"\\".repeat(5)}]`, @@ -257,6 +261,35 @@ ruleTester.run("no-missing-label-refs", rule, { }, ], }, + { + code: "[foo]\n[bar]\n[foo]", + errors: [ + { + messageId: "notFound", + data: { label: "foo" }, + line: 1, + column: 2, + endLine: 1, + endColumn: 5, + }, + { + messageId: "notFound", + data: { label: "bar" }, + line: 2, + column: 2, + endLine: 2, + endColumn: 5, + }, + { + messageId: "notFound", + data: { label: "foo" }, + line: 3, + column: 2, + endLine: 3, + endColumn: 5, + }, + ], + }, { code: "- - - [foo]", errors: [