chore(deps): treat line comments as trivia too in the import scan
From Copilot's fifth pass of #1962. `TRIVIA` covered block comments but not `//`, despite the contract right above it saying a comment is legal wherever whitespace is — so `import(// lazy\n"pkg")`, `require(// lazy\n"pkg")`, and `from // reason\n"pkg"` were stepped over, and such a package would never enter the candidate set. Same silent-miss direction as the block-comment gap. Both comment syntaxes are now covered. The line-comment branch runs to end-of-line only; the newline itself is matched by TRIVIA's `\s` branch. Regression test added alongside the block-comment one. The derived set is unchanged at 18 real names — widening trivia does not admit prose, since a specifier must still follow immediately and `packageNameOf` rejects anything not shaped like one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HDdo1rNRVQnVRRdsqSrvG3
This commit is contained in:
parent
2dcf1450b2
commit
2f1d97e7bb
2 changed files with 25 additions and 4 deletions
|
|
@ -132,10 +132,12 @@ export function packageNameOf(specifier) {
|
||||||
// name would silently widen the set.
|
// name would silently widen the set.
|
||||||
//
|
//
|
||||||
// Whitespace between tokens is really *trivia*: TypeScript allows a comment
|
// Whitespace between tokens is really *trivia*: TypeScript allows a comment
|
||||||
// anywhere whitespace is legal, so `import(/* webpackIgnore: true */ "pkg")`
|
// anywhere whitespace is legal, so `import(/* webpackIgnore: true */ "pkg")`,
|
||||||
// and `from /* why */ "pkg"` are valid and must still be seen (Copilot,
|
// `from /* why */ "pkg"`, and the line-comment forms (`import(// lazy\n"pkg")`)
|
||||||
// #1962). `TRIVIA` stands in for `\s*` at every such position.
|
// are all valid and must still be seen (Copilot, #1962). `TRIVIA` stands in for
|
||||||
const TRIVIA = String.raw`(?:\s|/\*[\s\S]*?\*/)*`;
|
// `\s*` at every such position and covers both comment syntaxes. A line comment
|
||||||
|
// runs to end-of-line only — the newline itself is matched by the `\s` branch.
|
||||||
|
const TRIVIA = String.raw`(?:\s|/\*[\s\S]*?\*/|//[^\n]*)*`;
|
||||||
const SPECIFIER_FORMS = [
|
const SPECIFIER_FORMS = [
|
||||||
// import … from "x" / export … from "x"
|
// import … from "x" / export … from "x"
|
||||||
new RegExp(String.raw`\bfrom${TRIVIA}["']([^"']+)["']`, "g"),
|
new RegExp(String.raw`\bfrom${TRIVIA}["']([^"']+)["']`, "g"),
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,25 @@ test("importedPackageNames: comment trivia between tokens (Copilot, #1962)", ()
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("importedPackageNames: line-comment trivia, not just block (Copilot, #1962)", () => {
|
||||||
|
// `//` runs to end-of-line and is legal in every position a block comment is,
|
||||||
|
// so these are valid imports too. The newline is matched by TRIVIA's `\\s`
|
||||||
|
// branch rather than by the line-comment branch.
|
||||||
|
const source = [
|
||||||
|
"import { a } from // reason",
|
||||||
|
' "express";',
|
||||||
|
"const b = await import(// lazy",
|
||||||
|
' "undici");',
|
||||||
|
"const c = require(// lazy",
|
||||||
|
' "yaml");',
|
||||||
|
].join("\n");
|
||||||
|
assert.deepEqual([...importedPackageNames(source)].sort(), [
|
||||||
|
"express",
|
||||||
|
"undici",
|
||||||
|
"yaml",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
test("importedPackageNames: the three specifier forms that introduce types", () => {
|
test("importedPackageNames: the three specifier forms that introduce types", () => {
|
||||||
const source = `
|
const source = `
|
||||||
import { z } from "zod/v4";
|
import { z } from "zod/v4";
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue