diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dfd479127202c..4a89dda6472cb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -321,6 +321,7 @@ import { getJSDocDeprecatedTag, getJSDocEnumTag, getJSDocHost, + getJSDocIgnoreTag, getJSDocOverloadTags, getJSDocParameterTags, getJSDocRoot, @@ -35339,7 +35340,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 000861e55dd44..ee0fb5870cbc8 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1852,6 +1852,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 e31d925fadd8f..d945e98cff037 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -226,6 +226,7 @@ import { JSDocDeprecatedTag, JSDocEnumTag, JSDocFunctionType, + JSDocIgnoreTag, JSDocImplementsTag, JSDocImportTag, JSDocLink, @@ -940,6 +941,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); }, @@ -5465,6 +5472,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; @@ -5478,6 +5486,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 68133ac5f1e40..33c1ef4d67f7d 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -177,6 +177,7 @@ import { JSDocDeprecatedTag, JSDocEnumTag, JSDocFunctionType, + JSDocIgnoreTag, JSDocImplementsTag, JSDocImportTag, JSDocLink, @@ -1130,6 +1131,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, @@ -1216,7 +1218,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)); } @@ -9135,6 +9137,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 cdba2e880afc3..d0e211bcbc046 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -421,6 +421,7 @@ export const enum SyntaxKind { JSDocImplementsTag, JSDocAuthorTag, JSDocDeprecatedTag, + JSDocIgnoreTag, JSDocClassTag, JSDocPublicTag, JSDocPrivateTag, @@ -1051,6 +1052,7 @@ export type ForEachChildNodes = | JSDocProtectedTag | JSDocReadonlyTag | JSDocDeprecatedTag + | JSDocIgnoreTag | JSDocThrowsTag | JSDocOverrideTag | JSDocSatisfiesTag @@ -4012,6 +4014,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; } @@ -9192,6 +9198,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 36eba18db07ba..9b7eecd4c9515 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 ba6404355b3c3..f1a2c52a1ca38 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4014,33 +4014,34 @@ declare namespace ts { JSDocImplementsTag = 330, JSDocAuthorTag = 331, JSDocDeprecatedTag = 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, + JSDocIgnoreTag = 333, + JSDocClassTag = 334, + JSDocPublicTag = 335, + JSDocPrivateTag = 336, + JSDocProtectedTag = 337, + JSDocReadonlyTag = 338, + JSDocOverrideTag = 339, + JSDocCallbackTag = 340, + JSDocOverloadTag = 341, + JSDocEnumTag = 342, + JSDocParameterTag = 343, + JSDocReturnTag = 344, + JSDocThisTag = 345, + JSDocTypeTag = 346, + JSDocTemplateTag = 347, + JSDocTypedefTag = 348, + JSDocSeeTag = 349, + JSDocPropertyTag = 350, + JSDocThrowsTag = 351, + JSDocSatisfiesTag = 352, + JSDocImportTag = 353, + SyntaxList = 354, + NotEmittedStatement = 355, + NotEmittedTypeElement = 356, + PartiallyEmittedExpression = 357, + CommaListExpression = 358, + SyntheticReferenceExpression = 359, + Count = 360, FirstAssignment = 64, LastAssignment = 79, FirstCompoundAssignment = 65, @@ -4069,9 +4070,9 @@ declare namespace ts { LastStatement = 260, FirstNode = 167, FirstJSDocNode = 310, - LastJSDocNode = 352, + LastJSDocNode = 353, FirstJSDocTagNode = 328, - LastJSDocTagNode = 352, + LastJSDocTagNode = 353, } 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; @@ -5790,6 +5791,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; } @@ -7848,6 +7852,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; @@ -8709,6 +8715,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 */ @@ -9155,6 +9163,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, +});