Skip to content

[Experiment] feat(47558): Warning 6133 ignores @link tags #47822

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 33 additions & 7 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36955,6 +36955,12 @@ namespace ts {
checkSourceElement(node.typeExpression);
}

function checkJSDocLinkLikeTag(node: JSDocLink | JSDocLinkCode | JSDocLinkPlain) {
if (node.name) {
resolveJSDocMemberName(node.name, /*ignoreErrors*/ true);
}
}

function checkJSDocParameterTag(node: JSDocParameterTag) {
checkSourceElement(node.typeExpression);
}
Expand Down Expand Up @@ -41172,9 +41178,15 @@ namespace ts {
}

function checkSourceElementWorker(node: Node): void {
if (isInJSFile(node)) {
forEach((node as JSDocContainer).jsDoc, ({ tags }) => forEach(tags, checkSourceElement));
}
forEach((node as JSDocContainer).jsDoc, ({ comment, tags }) => {
checkJSDocCommentWorker(comment);
forEach(tags, tag => {
checkJSDocCommentWorker(tag.comment);
if (isInJSFile(node)) {
checkSourceElement(tag);
}
});
});

const kind = node.kind;
if (cancellationToken) {
Expand Down Expand Up @@ -41262,6 +41274,10 @@ namespace ts {
return checkJSDocTemplateTag(node as JSDocTemplateTag);
case SyntaxKind.JSDocTypeTag:
return checkJSDocTypeTag(node as JSDocTypeTag);
case SyntaxKind.JSDocLink:
case SyntaxKind.JSDocLinkCode:
case SyntaxKind.JSDocLinkPlain:
return checkJSDocLinkLikeTag(node as JSDocLink | JSDocLinkCode | JSDocLinkPlain);
case SyntaxKind.JSDocParameterTag:
return checkJSDocParameterTag(node as JSDocParameterTag);
case SyntaxKind.JSDocPropertyTag:
Expand Down Expand Up @@ -41357,6 +41373,16 @@ namespace ts {
}
}

function checkJSDocCommentWorker(node: string | readonly JSDocComment[] | undefined) {
if (isArray(node)) {
forEach(node, tag => {
if (isJSDocLinkLike(tag)) {
checkSourceElement(tag);
}
});
}
}

function checkJSDocTypeIsInJsFile(node: Node): void {
if (!isInJSFile(node)) {
grammarErrorOnNode(node, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments);
Expand Down Expand Up @@ -41990,7 +42016,7 @@ namespace ts {
if (!result && isJSDoc) {
const container = findAncestor(name, or(isClassLike, isInterfaceDeclaration));
if (container) {
return resolveJSDocMemberName(name, getSymbolOfNode(container));
return resolveJSDocMemberName(name, /*ignoreErrors*/ false, getSymbolOfNode(container));
}
}
return result;
Expand Down Expand Up @@ -42039,19 +42065,19 @@ namespace ts {
*
* For unqualified names, a container K may be provided as a second argument.
*/
function resolveJSDocMemberName(name: EntityName | JSDocMemberName, container?: Symbol): Symbol | undefined {
function resolveJSDocMemberName(name: EntityName | JSDocMemberName, ignoreErrors?: boolean, container?: Symbol): Symbol | undefined {
if (isEntityName(name)) {
// resolve static values first
const meaning = SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Value;
let symbol = resolveEntityName(name, meaning, /*ignoreErrors*/ false, /*dontResolveAlias*/ true, getHostSignatureFromJSDoc(name));
let symbol = resolveEntityName(name, meaning, ignoreErrors, /*dontResolveAlias*/ true, getHostSignatureFromJSDoc(name));
if (!symbol && isIdentifier(name) && container) {
symbol = getMergedSymbol(getSymbol(getExportsOfSymbol(container), name.escapedText, meaning));
}
if (symbol) {
return symbol;
}
}
const left = isIdentifier(name) ? container : resolveJSDocMemberName(name.left);
const left = isIdentifier(name) ? container : resolveJSDocMemberName(name.left, ignoreErrors, container);
const right = isIdentifier(name) ? name.escapedText : name.right.escapedText;
if (left) {
const proto = left.flags & SymbolFlags.Value && getPropertyOfType(getTypeOfSymbol(left), "prototype" as __String);
Expand Down
18 changes: 18 additions & 0 deletions tests/baselines/reference/jsdocLinkTag1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//// [tests/cases/conformance/jsdoc/jsdocLinkTag1.ts] ////

//// [a.ts]
export interface A {}

//// [b.ts]
import type { A } from "./a";

/** {@link A} */
export interface B {}


//// [a.js]
"use strict";
exports.__esModule = true;
//// [b.js]
"use strict";
exports.__esModule = true;
12 changes: 12 additions & 0 deletions tests/baselines/reference/jsdocLinkTag1.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
=== /a.ts ===
export interface A {}
>A : Symbol(A, Decl(a.ts, 0, 0))

=== /b.ts ===
import type { A } from "./a";
>A : Symbol(A, Decl(b.ts, 0, 13))

/** {@link A} */
export interface B {}
>B : Symbol(B, Decl(b.ts, 0, 29))

10 changes: 10 additions & 0 deletions tests/baselines/reference/jsdocLinkTag1.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
=== /a.ts ===
export interface A {}
No type information for this code.
No type information for this code.=== /b.ts ===
import type { A } from "./a";
>A : A

/** {@link A} */
export interface B {}

13 changes: 13 additions & 0 deletions tests/baselines/reference/jsdocLinkTag2.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
=== /a.js ===
export class A {}
>A : Symbol(A, Decl(a.js, 0, 0))

=== /b.js ===
import { A } from "./a";
>A : Symbol(A, Decl(b.js, 0, 8))

/** {@link A} */
export class B {}
>B : Symbol(B, Decl(b.js, 0, 24))


13 changes: 13 additions & 0 deletions tests/baselines/reference/jsdocLinkTag2.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
=== /a.js ===
export class A {}
>A : A

=== /b.js ===
import { A } from "./a";
>A : typeof A

/** {@link A} */
export class B {}
>B : B


26 changes: 26 additions & 0 deletions tests/baselines/reference/jsdocLinkTag3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//// [tests/cases/conformance/jsdoc/jsdocLinkTag3.ts] ////

//// [a.ts]
export interface A {}

//// [b.ts]
import type { A } from "./a";

/**
* @param {number} a - see {@link A}
*/
export function foo(a: string) {}


//// [a.js]
"use strict";
exports.__esModule = true;
//// [b.js]
"use strict";
exports.__esModule = true;
exports.foo = void 0;
/**
* @param {number} a - see {@link A}
*/
function foo(a) { }
exports.foo = foo;
15 changes: 15 additions & 0 deletions tests/baselines/reference/jsdocLinkTag3.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
=== /a.ts ===
export interface A {}
>A : Symbol(A, Decl(a.ts, 0, 0))

=== /b.ts ===
import type { A } from "./a";
>A : Symbol(A, Decl(b.ts, 0, 13))

/**
* @param {number} a - see {@link A}
*/
export function foo(a: string) {}
>foo : Symbol(foo, Decl(b.ts, 0, 29))
>a : Symbol(a, Decl(b.ts, 5, 20))

14 changes: 14 additions & 0 deletions tests/baselines/reference/jsdocLinkTag3.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
=== /a.ts ===
export interface A {}
No type information for this code.
No type information for this code.=== /b.ts ===
import type { A } from "./a";
>A : A

/**
* @param {number} a - see {@link A}
*/
export function foo(a: string) {}
>foo : (a: string) => void
>a : string

26 changes: 26 additions & 0 deletions tests/baselines/reference/jsdocLinkTag4.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//// [tests/cases/conformance/jsdoc/jsdocLinkTag4.ts] ////

//// [a.ts]
export interface A {}

//// [b.ts]
import * as a from "./a";

/**
* @param {number} a - see {@link a.A}
*/
export function foo(a: string) {}


//// [a.js]
"use strict";
exports.__esModule = true;
//// [b.js]
"use strict";
exports.__esModule = true;
exports.foo = void 0;
/**
* @param {number} a - see {@link a.A}
*/
function foo(a) { }
exports.foo = foo;
15 changes: 15 additions & 0 deletions tests/baselines/reference/jsdocLinkTag4.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
=== /a.ts ===
export interface A {}
>A : Symbol(A, Decl(a.ts, 0, 0))

=== /b.ts ===
import * as a from "./a";
>a : Symbol(a, Decl(b.ts, 0, 6))

/**
* @param {number} a - see {@link a.A}
*/
export function foo(a: string) {}
>foo : Symbol(foo, Decl(b.ts, 0, 25))
>a : Symbol(a, Decl(b.ts, 5, 20))

14 changes: 14 additions & 0 deletions tests/baselines/reference/jsdocLinkTag4.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
=== /a.ts ===
export interface A {}
No type information for this code.
No type information for this code.=== /b.ts ===
import * as a from "./a";
>a : typeof a

/**
* @param {number} a - see {@link a.A}
*/
export function foo(a: string) {}
>foo : (a: string) => void
>a : string

8 changes: 8 additions & 0 deletions tests/baselines/reference/jsdocLinkTag5.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//// [a.ts]
/** {@link UNRESOLVED_LINK} */
export interface A {}


//// [a.js]
"use strict";
exports.__esModule = true;
5 changes: 5 additions & 0 deletions tests/baselines/reference/jsdocLinkTag5.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
=== /a.ts ===
/** {@link UNRESOLVED_LINK} */
export interface A {}
>A : Symbol(A, Decl(a.ts, 0, 0))

5 changes: 5 additions & 0 deletions tests/baselines/reference/jsdocLinkTag5.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
=== /a.ts ===
/** {@link UNRESOLVED_LINK} */
No type information for this code.export interface A {}
No type information for this code.
No type information for this code.
9 changes: 9 additions & 0 deletions tests/cases/conformance/jsdoc/jsdocLinkTag1.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// @noUnusedLocals: true
// @filename: /a.ts
export interface A {}

// @filename: /b.ts
import type { A } from "./a";

/** {@link A} */
export interface B {}
15 changes: 15 additions & 0 deletions tests/cases/conformance/jsdoc/jsdocLinkTag2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// @noUnusedLocals: true
// @checkJs: true
// @allowJs: true
// @target: esnext
// @noEmit: true

// @filename: /a.js
export class A {}

// @filename: /b.js
import { A } from "./a";

/** {@link A} */
export class B {}

11 changes: 11 additions & 0 deletions tests/cases/conformance/jsdoc/jsdocLinkTag3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// @noUnusedLocals: true
// @filename: /a.ts
export interface A {}

// @filename: /b.ts
import type { A } from "./a";

/**
* @param {number} a - see {@link A}
*/
export function foo(a: string) {}
11 changes: 11 additions & 0 deletions tests/cases/conformance/jsdoc/jsdocLinkTag4.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// @noUnusedLocals: true
// @filename: /a.ts
export interface A {}

// @filename: /b.ts
import * as a from "./a";

/**
* @param {number} a - see {@link a.A}
*/
export function foo(a: string) {}
5 changes: 5 additions & 0 deletions tests/cases/conformance/jsdoc/jsdocLinkTag5.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// @noUnusedLocals: true
// @filename: /a.ts

/** {@link UNRESOLVED_LINK} */
export interface A {}