diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 80b61edd3657a..b4d2a5c447318 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -319,6 +319,7 @@ import { getJSDocDeprecatedTag, getJSDocEnumTag, getJSDocHost, + getJSDocIgnoreTag, getJSDocOverloadTags, getJSDocParameterTags, getJSDocRoot, @@ -34747,7 +34748,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @param property the accessed property's symbol. */ function isValidPropertyAccessForCompletions(node: PropertyAccessExpression | ImportTypeNode | QualifiedName, type: Type, property: Symbol): boolean { - return isPropertyAccessible(node, node.kind === SyntaxKind.PropertyAccessExpression && node.expression.kind === SyntaxKind.SuperKeyword, /*isWrite*/ false, type, property); + return isPropertyAccessible(node, node.kind === SyntaxKind.PropertyAccessExpression && node.expression.kind === SyntaxKind.SuperKeyword, /*isWrite*/ false, type, property) + && (!property.declarations || some(property.declarations, decl => !getJSDocIgnoreTag(decl))); // Previously we validated the 'this' type of methods but this adversely affected performance. See #31377 for more context. } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 01a96579861f4..d36ff98c25cd7 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1851,6 +1851,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return emitJSDocHeritageTag(node as JSDocImplementsTag | JSDocAugmentsTag); case SyntaxKind.JSDocAuthorTag: case SyntaxKind.JSDocDeprecatedTag: + case SyntaxKind.JSDocIgnoreTag: return; // SyntaxKind.JSDocClassTag (see JSDocTag, above) case SyntaxKind.JSDocPublicTag: diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index 694262eeeb54a..162f6d00bf260 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -225,6 +225,7 @@ import { JSDocDeprecatedTag, JSDocEnumTag, JSDocFunctionType, + JSDocIgnoreTag, JSDocImplementsTag, JSDocImportTag, JSDocLink, @@ -939,6 +940,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode get updateJSDocDeprecatedTag() { return getJSDocSimpleTagUpdateFunction(SyntaxKind.JSDocDeprecatedTag); }, + get createJSDocIgnoreTag() { + return getJSDocSimpleTagCreateFunction(SyntaxKind.JSDocIgnoreTag); + }, + get updateJSDocIgnoreTag() { + return getJSDocSimpleTagUpdateFunction(SyntaxKind.JSDocIgnoreTag); + }, get createJSDocThrowsTag() { return getJSDocTypeLikeTagCreateFunction(SyntaxKind.JSDocThrowsTag); }, @@ -5457,6 +5464,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // createJSDocProtectedTag // createJSDocReadonlyTag // createJSDocDeprecatedTag + // createJSDocIgnoreTag function createJSDocSimpleTagWorker(kind: T["kind"], tagName: Identifier | undefined, comment?: string | NodeArray) { const node = createBaseJSDocTag(kind, tagName ?? createIdentifier(getDefaultTagNameForKind(kind)), comment); return node; @@ -5470,6 +5478,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // updateJSDocProtectedTag // updateJSDocReadonlyTag // updateJSDocDeprecatedTag + // updateJSDocIgnoreTag function updateJSDocSimpleTagWorker(kind: T["kind"], node: T, tagName: Identifier = getDefaultTagName(node), comment: string | NodeArray | undefined) { return node.tagName !== tagName || node.comment !== comment diff --git a/src/compiler/factory/nodeTests.ts b/src/compiler/factory/nodeTests.ts index 8aa4bb02e83d2..f354ade7ee3fa 100644 --- a/src/compiler/factory/nodeTests.ts +++ b/src/compiler/factory/nodeTests.ts @@ -90,6 +90,7 @@ import { JSDocDeprecatedTag, JSDocEnumTag, JSDocFunctionType, + JSDocIgnoreTag, JSDocImplementsTag, JSDocImportTag, JSDocLink, @@ -1137,6 +1138,10 @@ export function isJSDocDeprecatedTag(node: Node): node is JSDocDeprecatedTag { return node.kind === SyntaxKind.JSDocDeprecatedTag; } +export function isJSDocIgnoreTag(node: Node): node is JSDocIgnoreTag { + return node.kind === SyntaxKind.JSDocIgnoreTag; +} + export function isJSDocSeeTag(node: Node): node is JSDocSeeTag { return node.kind === SyntaxKind.JSDocSeeTag; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 59ad1f030220f..eba4d91b00cc6 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -176,6 +176,7 @@ import { JSDocDeprecatedTag, JSDocEnumTag, JSDocFunctionType, + JSDocIgnoreTag, JSDocImplementsTag, JSDocImportTag, JSDocLink, @@ -1129,6 +1130,7 @@ const forEachChildTable: ForEachChildTable = { [SyntaxKind.JSDocProtectedTag]: forEachChildInJSDocTag, [SyntaxKind.JSDocReadonlyTag]: forEachChildInJSDocTag, [SyntaxKind.JSDocDeprecatedTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocIgnoreTag]: forEachChildInJSDocTag, [SyntaxKind.JSDocOverrideTag]: forEachChildInJSDocTag, [SyntaxKind.JSDocImportTag]: forEachChildInJSDocImportTag, [SyntaxKind.PartiallyEmittedExpression]: forEachChildInPartiallyEmittedExpression, @@ -1215,7 +1217,7 @@ function forEachChildInJSDocLinkCodeOrPlain(node: JSDocLink | JSDocLinkCode | return visitNode(cbNode, node.name); } -function forEachChildInJSDocTag(node: JSDocUnknownTag | JSDocClassTag | JSDocPublicTag | JSDocPrivateTag | JSDocProtectedTag | JSDocReadonlyTag | JSDocDeprecatedTag | JSDocOverrideTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { +function forEachChildInJSDocTag(node: JSDocUnknownTag | JSDocClassTag | JSDocPublicTag | JSDocPrivateTag | JSDocProtectedTag | JSDocReadonlyTag | JSDocDeprecatedTag | JSDocIgnoreTag | JSDocOverrideTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tagName) || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); } @@ -9096,6 +9098,9 @@ namespace Parser { hasDeprecatedTag = true; tag = parseSimpleTag(start, factory.createJSDocDeprecatedTag, tagName, margin, indentText); break; + case "ignore": + tag = parseSimpleTag(start, factory.createJSDocIgnoreTag, tagName, margin, indentText); + break; case "this": tag = parseThisTag(start, tagName, margin, indentText); break; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 49938f0fc8249..92d3f7e0e61f0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -419,6 +419,7 @@ export const enum SyntaxKind { JSDocImplementsTag, JSDocAuthorTag, JSDocDeprecatedTag, + JSDocIgnoreTag, JSDocClassTag, JSDocPublicTag, JSDocPrivateTag, @@ -1047,6 +1048,7 @@ export type ForEachChildNodes = | JSDocProtectedTag | JSDocReadonlyTag | JSDocDeprecatedTag + | JSDocIgnoreTag | JSDocThrowsTag | JSDocOverrideTag | JSDocSatisfiesTag @@ -3999,6 +4001,10 @@ export interface JSDocDeprecatedTag extends JSDocTag { kind: SyntaxKind.JSDocDeprecatedTag; } +export interface JSDocIgnoreTag extends JSDocTag { + kind: SyntaxKind.JSDocIgnoreTag; +} + export interface JSDocClassTag extends JSDocTag { readonly kind: SyntaxKind.JSDocClassTag; } @@ -9138,6 +9144,8 @@ export interface NodeFactory { updateJSDocUnknownTag(node: JSDocUnknownTag, tagName: Identifier, comment: string | NodeArray | undefined): JSDocUnknownTag; createJSDocDeprecatedTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocDeprecatedTag; updateJSDocDeprecatedTag(node: JSDocDeprecatedTag, tagName: Identifier | undefined, comment?: string | NodeArray): JSDocDeprecatedTag; + createJSDocIgnoreTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocIgnoreTag; + updateJSDocIgnoreTag(node: JSDocIgnoreTag, tagName: Identifier | undefined, comment?: string | NodeArray): JSDocIgnoreTag; createJSDocOverrideTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocOverrideTag; updateJSDocOverrideTag(node: JSDocOverrideTag, tagName: Identifier | undefined, comment?: string | NodeArray): JSDocOverrideTag; createJSDocThrowsTag(tagName: Identifier, typeExpression: JSDocTypeExpression | undefined, comment?: string | NodeArray): JSDocThrowsTag; diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 02623678a0cf0..fd505e1e7072c 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -140,6 +140,7 @@ import { isJSDocDeprecatedTag, isJSDocEnumTag, isJSDocFunctionType, + isJSDocIgnoreTag, isJSDocImplementsTag, isJSDocOverloadTag, isJSDocOverrideTag, @@ -183,6 +184,7 @@ import { JSDocContainer, JSDocDeprecatedTag, JSDocEnumTag, + JSDocIgnoreTag, JSDocImplementsTag, JSDocLink, JSDocLinkCode, @@ -1174,6 +1176,11 @@ export function getJSDocDeprecatedTagNoCache(node: Node): JSDocDeprecatedTag | u return getFirstJSDocTag(node, isJSDocDeprecatedTag, /*noCache*/ true); } +/** Gets the JSDoc ignore tag for the node if present */ +export function getJSDocIgnoreTag(node: Node): JSDocIgnoreTag | undefined { + return getFirstJSDocTag(node, isJSDocIgnoreTag); +} + /** Gets the JSDoc enum tag for the node if present */ export function getJSDocEnumTag(node: Node): JSDocEnumTag | undefined { return getFirstJSDocTag(node, isJSDocEnumTag); diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 4b4404634fdaa..599913e6eba57 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4008,33 +4008,34 @@ declare namespace ts { JSDocImplementsTag = 329, JSDocAuthorTag = 330, JSDocDeprecatedTag = 331, - JSDocClassTag = 332, - JSDocPublicTag = 333, - JSDocPrivateTag = 334, - JSDocProtectedTag = 335, - JSDocReadonlyTag = 336, - JSDocOverrideTag = 337, - JSDocCallbackTag = 338, - JSDocOverloadTag = 339, - JSDocEnumTag = 340, - JSDocParameterTag = 341, - JSDocReturnTag = 342, - JSDocThisTag = 343, - JSDocTypeTag = 344, - JSDocTemplateTag = 345, - JSDocTypedefTag = 346, - JSDocSeeTag = 347, - JSDocPropertyTag = 348, - JSDocThrowsTag = 349, - JSDocSatisfiesTag = 350, - JSDocImportTag = 351, - SyntaxList = 352, - NotEmittedStatement = 353, - NotEmittedTypeElement = 354, - PartiallyEmittedExpression = 355, - CommaListExpression = 356, - SyntheticReferenceExpression = 357, - Count = 358, + JSDocIgnoreTag = 332, + JSDocClassTag = 333, + JSDocPublicTag = 334, + JSDocPrivateTag = 335, + JSDocProtectedTag = 336, + JSDocReadonlyTag = 337, + JSDocOverrideTag = 338, + JSDocCallbackTag = 339, + JSDocOverloadTag = 340, + JSDocEnumTag = 341, + JSDocParameterTag = 342, + JSDocReturnTag = 343, + JSDocThisTag = 344, + JSDocTypeTag = 345, + JSDocTemplateTag = 346, + JSDocTypedefTag = 347, + JSDocSeeTag = 348, + JSDocPropertyTag = 349, + JSDocThrowsTag = 350, + JSDocSatisfiesTag = 351, + JSDocImportTag = 352, + SyntaxList = 353, + NotEmittedStatement = 354, + NotEmittedTypeElement = 355, + PartiallyEmittedExpression = 356, + CommaListExpression = 357, + SyntheticReferenceExpression = 358, + Count = 359, FirstAssignment = 64, LastAssignment = 79, FirstCompoundAssignment = 65, @@ -4063,9 +4064,9 @@ declare namespace ts { LastStatement = 259, FirstNode = 166, FirstJSDocNode = 309, - LastJSDocNode = 351, + LastJSDocNode = 352, FirstJSDocTagNode = 327, - LastJSDocTagNode = 351, + LastJSDocTagNode = 352, } type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; @@ -5774,6 +5775,9 @@ declare namespace ts { interface JSDocDeprecatedTag extends JSDocTag { kind: SyntaxKind.JSDocDeprecatedTag; } + interface JSDocIgnoreTag extends JSDocTag { + kind: SyntaxKind.JSDocIgnoreTag; + } interface JSDocClassTag extends JSDocTag { readonly kind: SyntaxKind.JSDocClassTag; } @@ -7815,6 +7819,8 @@ declare namespace ts { updateJSDocUnknownTag(node: JSDocUnknownTag, tagName: Identifier, comment: string | NodeArray | undefined): JSDocUnknownTag; createJSDocDeprecatedTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocDeprecatedTag; updateJSDocDeprecatedTag(node: JSDocDeprecatedTag, tagName: Identifier | undefined, comment?: string | NodeArray): JSDocDeprecatedTag; + createJSDocIgnoreTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocIgnoreTag; + updateJSDocIgnoreTag(node: JSDocIgnoreTag, tagName: Identifier | undefined, comment?: string | NodeArray): JSDocIgnoreTag; createJSDocOverrideTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocOverrideTag; updateJSDocOverrideTag(node: JSDocOverrideTag, tagName: Identifier | undefined, comment?: string | NodeArray): JSDocOverrideTag; createJSDocThrowsTag(tagName: Identifier, typeExpression: JSDocTypeExpression | undefined, comment?: string | NodeArray): JSDocThrowsTag; @@ -8670,6 +8676,8 @@ declare namespace ts { function getJSDocOverrideTagNoCache(node: Node): JSDocOverrideTag | undefined; /** Gets the JSDoc deprecated tag for the node if present */ function getJSDocDeprecatedTag(node: Node): JSDocDeprecatedTag | undefined; + /** Gets the JSDoc ignore tag for the node if present */ + function getJSDocIgnoreTag(node: Node): JSDocIgnoreTag | undefined; /** Gets the JSDoc enum tag for the node if present */ function getJSDocEnumTag(node: Node): JSDocEnumTag | undefined; /** Gets the JSDoc this tag for the node if present */ @@ -9116,6 +9124,7 @@ declare namespace ts { function isJSDocOverrideTag(node: Node): node is JSDocOverrideTag; function isJSDocOverloadTag(node: Node): node is JSDocOverloadTag; function isJSDocDeprecatedTag(node: Node): node is JSDocDeprecatedTag; + function isJSDocIgnoreTag(node: Node): node is JSDocIgnoreTag; function isJSDocSeeTag(node: Node): node is JSDocSeeTag; function isJSDocEnumTag(node: Node): node is JSDocEnumTag; function isJSDocParameterTag(node: Node): node is JSDocParameterTag; diff --git a/tests/cases/fourslash/completionsIgnoreTagOnProperty1.ts b/tests/cases/fourslash/completionsIgnoreTagOnProperty1.ts new file mode 100644 index 0000000000000..a422d329e3f87 --- /dev/null +++ b/tests/cases/fourslash/completionsIgnoreTagOnProperty1.ts @@ -0,0 +1,16 @@ +/// + +//// type Foo = { +//// /** @ignore */ +//// a: string; +//// b: number; +//// }; +//// +//// declare const foo: Foo; +//// foo./**/ + +verify.completions({ + marker: "", + exact: "b", + isNewIdentifierLocation: false, +});