From d62646802456126e3697afee269520f7b02275a9 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Wed, 25 Dec 2024 16:58:48 -0700 Subject: [PATCH] Fix `@link` with declaration reference using `!~` Resolves #2810 --- CHANGELOG.md | 1 + site/declaration-references.md | 5 +++++ src/lib/converter/comments/declarationReference.ts | 13 ++++++++++++- src/test/declarationReference.test.ts | 11 +++++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 941463bed..b49e12606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ title: Changelog - TypeDoc will now avoid making references to references, #2811. - Fixed output specific option specification, #2818. - Improved type reference conversion to avoid including defaulted type arguments, #2820. +- Fixed parsing of declaration references which include a module and a local reference, #2810. - Improved link resolution logic to prioritize type alias properties with the same symbol over type literal properties within function parameters. diff --git a/site/declaration-references.md b/site/declaration-references.md index 2e5668f3a..35068d360 100644 --- a/site/declaration-references.md +++ b/site/declaration-references.md @@ -48,6 +48,11 @@ The deliminator is used to determine how to navigate the project tree. | `#` | Indicates that the next component is a "member", including class instance properties, interface members, and enum members. | | `~` | Indicates that the next component is an export of a namespace/module. | +> [!warning] The TSDoc specification says that `~` traverses via locals. This is +> different than TypeDoc's behavior. TypeDoc will treat `~` as a stricter `.` +> which only supports navigating to a namespace/module export. It should +> generally be avoided in favor of `.` for improved compatibility with VSCode. + ```ts // module.ts /** diff --git a/src/lib/converter/comments/declarationReference.ts b/src/lib/converter/comments/declarationReference.ts index d54f72aae..aac97a8c9 100644 --- a/src/lib/converter/comments/declarationReference.ts +++ b/src/lib/converter/comments/declarationReference.ts @@ -65,7 +65,8 @@ export interface ComponentPath { * How to resolve the `path` * - `.` - Navigate via `exports` of symbol * - `#` - Navigate via `members` of symbol - * - `~` - Navigate via `locals` of symbol + * - `~` - Navigate via `locals` of symbol (note: TypeDoc does not support + * locals, see the declaration reference docs) */ navigation: "." | "#" | "~"; path: string; @@ -432,6 +433,7 @@ export function parseDeclarationReference( let moduleSource: string | undefined; let symbolReference: SymbolReference | undefined; let resolutionStart: "global" | "local" = "local"; + let topLevelLocalReference = false; const moduleSourceOrSymbolRef = parseModuleSource(source, pos, end); if (moduleSourceOrSymbolRef) { @@ -443,6 +445,12 @@ export function parseDeclarationReference( pos = moduleSourceOrSymbolRef[1] + 1; resolutionStart = "global"; moduleSource = moduleSourceOrSymbolRef[0]; + + // We might be referencing a local of a module + if (source[pos] === "~") { + topLevelLocalReference = true; + pos++; + } } } else if (source[pos] === "!") { pos++; @@ -452,6 +460,9 @@ export function parseDeclarationReference( const ref = parseSymbolReference(source, pos, end); if (ref) { symbolReference = ref[0]; + if (topLevelLocalReference && symbolReference.path?.length) { + symbolReference.path[0].navigation = "~"; + } pos = ref[1]; } diff --git a/src/test/declarationReference.test.ts b/src/test/declarationReference.test.ts index 578654cb6..49f71caef 100644 --- a/src/test/declarationReference.test.ts +++ b/src/test/declarationReference.test.ts @@ -215,5 +215,16 @@ describe("Declaration References", () => { equal(parse(""), undefined); equal(parse("@test/foo"), undefined); }); + + it("Handles module reference with top level ~ reference", () => { + equal(parse("mod!~foo"), { + moduleSource: "mod", + resolutionStart: "global", + symbolReference: { + path: [{ navigation: "~", path: "foo" }], + meaning: undefined, + }, + }); + }); }); });