diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b97245f84e0..fb31e3dbdc5 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -7835,12 +7835,12 @@ namespace Parser { function parseClassElement(): ClassElement { const pos = getNodePos(); + const hasJSDoc = hasPrecedingJSDocComment(); if (token() === SyntaxKind.SemicolonToken) { nextToken(); - return finishNode(factory.createSemicolonClassElement(), pos); + return withJSDoc(finishNode(factory.createSemicolonClassElement(), pos), hasJSDoc); } - const hasJSDoc = hasPrecedingJSDocComment(); const modifiers = parseModifiers(/*allowDecorators*/ true, /*permitConstAsModifier*/ true, /*stopOnStartOfClassStaticBlock*/ true); if (token() === SyntaxKind.StaticKeyword && lookAhead(nextTokenIsOpenBrace)) { return parseClassStaticBlockDeclaration(pos, hasJSDoc, modifiers); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a651f955078..c97bbaffa28 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1219,6 +1219,7 @@ export type HasJSDoc = | PropertyDeclaration | PropertySignature | ReturnStatement + | SemicolonClassElement | ShorthandPropertyAssignment | SpreadAssignment | SwitchStatement @@ -2101,7 +2102,7 @@ export interface ConstructorDeclaration extends FunctionLikeDeclarationBase, Cla } /** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */ -export interface SemicolonClassElement extends ClassElement { +export interface SemicolonClassElement extends ClassElement, JSDocContainer { readonly kind: SyntaxKind.SemicolonClassElement; readonly parent: ClassLikeDeclaration; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index aa69702d062..fde771ab80d 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4180,6 +4180,7 @@ export function canHaveJSDoc(node: Node): node is HasJSDoc { case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: case SyntaxKind.ReturnStatement: + case SyntaxKind.SemicolonClassElement: case SyntaxKind.SetAccessor: case SyntaxKind.ShorthandPropertyAssignment: case SyntaxKind.SpreadAssignment: diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 5fac0f6c817..ee5fed651ed 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4597,7 +4597,7 @@ declare namespace ts { interface FlowContainer extends Node { _flowContainerBrand: any; } - type HasJSDoc = AccessorDeclaration | ArrowFunction | BinaryExpression | Block | BreakStatement | CallSignatureDeclaration | CaseClause | ClassLikeDeclaration | ClassStaticBlockDeclaration | ConstructorDeclaration | ConstructorTypeNode | ConstructSignatureDeclaration | ContinueStatement | DebuggerStatement | DoStatement | ElementAccessExpression | EmptyStatement | EndOfFileToken | EnumDeclaration | EnumMember | ExportAssignment | ExportDeclaration | ExportSpecifier | ExpressionStatement | ForInStatement | ForOfStatement | ForStatement | FunctionDeclaration | FunctionExpression | FunctionTypeNode | Identifier | IfStatement | ImportDeclaration | ImportEqualsDeclaration | IndexSignatureDeclaration | InterfaceDeclaration | JSDocFunctionType | JSDocSignature | LabeledStatement | MethodDeclaration | MethodSignature | ModuleDeclaration | NamedTupleMember | NamespaceExportDeclaration | ObjectLiteralExpression | ParameterDeclaration | ParenthesizedExpression | PropertyAccessExpression | PropertyAssignment | PropertyDeclaration | PropertySignature | ReturnStatement | ShorthandPropertyAssignment | SpreadAssignment | SwitchStatement | ThrowStatement | TryStatement | TypeAliasDeclaration | TypeParameterDeclaration | VariableDeclaration | VariableStatement | WhileStatement | WithStatement; + type HasJSDoc = AccessorDeclaration | ArrowFunction | BinaryExpression | Block | BreakStatement | CallSignatureDeclaration | CaseClause | ClassLikeDeclaration | ClassStaticBlockDeclaration | ConstructorDeclaration | ConstructorTypeNode | ConstructSignatureDeclaration | ContinueStatement | DebuggerStatement | DoStatement | ElementAccessExpression | EmptyStatement | EndOfFileToken | EnumDeclaration | EnumMember | ExportAssignment | ExportDeclaration | ExportSpecifier | ExpressionStatement | ForInStatement | ForOfStatement | ForStatement | FunctionDeclaration | FunctionExpression | FunctionTypeNode | Identifier | IfStatement | ImportDeclaration | ImportEqualsDeclaration | IndexSignatureDeclaration | InterfaceDeclaration | JSDocFunctionType | JSDocSignature | LabeledStatement | MethodDeclaration | MethodSignature | ModuleDeclaration | NamedTupleMember | NamespaceExportDeclaration | ObjectLiteralExpression | ParameterDeclaration | ParenthesizedExpression | PropertyAccessExpression | PropertyAssignment | PropertyDeclaration | PropertySignature | ReturnStatement | SemicolonClassElement | ShorthandPropertyAssignment | SpreadAssignment | SwitchStatement | ThrowStatement | TryStatement | TypeAliasDeclaration | TypeParameterDeclaration | VariableDeclaration | VariableStatement | WhileStatement | WithStatement; type HasType = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertySignature | PropertyDeclaration | TypePredicateNode | ParenthesizedTypeNode | TypeOperatorNode | MappedTypeNode | AssertionExpression | TypeAliasDeclaration | JSDocTypeExpression | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType | JSDocVariadicType; type HasTypeArguments = CallExpression | NewExpression | TaggedTemplateExpression | JsxOpeningElement | JsxSelfClosingElement; type HasInitializer = HasExpressionInitializer | ForStatement | ForInStatement | ForOfStatement | JsxAttribute; @@ -4876,7 +4876,7 @@ declare namespace ts { readonly body?: FunctionBody | undefined; } /** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */ - interface SemicolonClassElement extends ClassElement { + interface SemicolonClassElement extends ClassElement, JSDocContainer { readonly kind: SyntaxKind.SemicolonClassElement; readonly parent: ClassLikeDeclaration; } diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2f02032e7af..debe70be320 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -550,7 +550,7 @@ declare namespace ts { interface FlowContainer extends Node { _flowContainerBrand: any; } - type HasJSDoc = AccessorDeclaration | ArrowFunction | BinaryExpression | Block | BreakStatement | CallSignatureDeclaration | CaseClause | ClassLikeDeclaration | ClassStaticBlockDeclaration | ConstructorDeclaration | ConstructorTypeNode | ConstructSignatureDeclaration | ContinueStatement | DebuggerStatement | DoStatement | ElementAccessExpression | EmptyStatement | EndOfFileToken | EnumDeclaration | EnumMember | ExportAssignment | ExportDeclaration | ExportSpecifier | ExpressionStatement | ForInStatement | ForOfStatement | ForStatement | FunctionDeclaration | FunctionExpression | FunctionTypeNode | Identifier | IfStatement | ImportDeclaration | ImportEqualsDeclaration | IndexSignatureDeclaration | InterfaceDeclaration | JSDocFunctionType | JSDocSignature | LabeledStatement | MethodDeclaration | MethodSignature | ModuleDeclaration | NamedTupleMember | NamespaceExportDeclaration | ObjectLiteralExpression | ParameterDeclaration | ParenthesizedExpression | PropertyAccessExpression | PropertyAssignment | PropertyDeclaration | PropertySignature | ReturnStatement | ShorthandPropertyAssignment | SpreadAssignment | SwitchStatement | ThrowStatement | TryStatement | TypeAliasDeclaration | TypeParameterDeclaration | VariableDeclaration | VariableStatement | WhileStatement | WithStatement; + type HasJSDoc = AccessorDeclaration | ArrowFunction | BinaryExpression | Block | BreakStatement | CallSignatureDeclaration | CaseClause | ClassLikeDeclaration | ClassStaticBlockDeclaration | ConstructorDeclaration | ConstructorTypeNode | ConstructSignatureDeclaration | ContinueStatement | DebuggerStatement | DoStatement | ElementAccessExpression | EmptyStatement | EndOfFileToken | EnumDeclaration | EnumMember | ExportAssignment | ExportDeclaration | ExportSpecifier | ExpressionStatement | ForInStatement | ForOfStatement | ForStatement | FunctionDeclaration | FunctionExpression | FunctionTypeNode | Identifier | IfStatement | ImportDeclaration | ImportEqualsDeclaration | IndexSignatureDeclaration | InterfaceDeclaration | JSDocFunctionType | JSDocSignature | LabeledStatement | MethodDeclaration | MethodSignature | ModuleDeclaration | NamedTupleMember | NamespaceExportDeclaration | ObjectLiteralExpression | ParameterDeclaration | ParenthesizedExpression | PropertyAccessExpression | PropertyAssignment | PropertyDeclaration | PropertySignature | ReturnStatement | SemicolonClassElement | ShorthandPropertyAssignment | SpreadAssignment | SwitchStatement | ThrowStatement | TryStatement | TypeAliasDeclaration | TypeParameterDeclaration | VariableDeclaration | VariableStatement | WhileStatement | WithStatement; type HasType = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertySignature | PropertyDeclaration | TypePredicateNode | ParenthesizedTypeNode | TypeOperatorNode | MappedTypeNode | AssertionExpression | TypeAliasDeclaration | JSDocTypeExpression | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType | JSDocVariadicType; type HasTypeArguments = CallExpression | NewExpression | TaggedTemplateExpression | JsxOpeningElement | JsxSelfClosingElement; type HasInitializer = HasExpressionInitializer | ForStatement | ForInStatement | ForOfStatement | JsxAttribute; @@ -829,7 +829,7 @@ declare namespace ts { readonly body?: FunctionBody | undefined; } /** For when we encounter a semicolon in a class declaration. ES6 allows these as class elements. */ - interface SemicolonClassElement extends ClassElement { + interface SemicolonClassElement extends ClassElement, JSDocContainer { readonly kind: SyntaxKind.SemicolonClassElement; readonly parent: ClassLikeDeclaration; } diff --git a/tests/baselines/reference/typedefOnSemicolonClassElement.js b/tests/baselines/reference/typedefOnSemicolonClassElement.js new file mode 100644 index 00000000000..1511bf2ef51 --- /dev/null +++ b/tests/baselines/reference/typedefOnSemicolonClassElement.js @@ -0,0 +1,30 @@ +//// [typedefOnSemicolonClassElement.js] +export class Preferences { + /** @typedef {string} A */ + ; + /** @type {A} */ + a = 'ok' +} + + +//// [typedefOnSemicolonClassElement.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Preferences = void 0; +var Preferences = /** @class */ (function () { + function Preferences() { + /** @type {A} */ + this.a = 'ok'; + } + /** @typedef {string} A */ + ; + return Preferences; +}()); +exports.Preferences = Preferences; + + +//// [typedefOnSemicolonClassElement.d.ts] +export class Preferences { + /** @type {A} */ + a: string; +} diff --git a/tests/baselines/reference/typedefOnSemicolonClassElement.symbols b/tests/baselines/reference/typedefOnSemicolonClassElement.symbols new file mode 100644 index 00000000000..9f31c574c58 --- /dev/null +++ b/tests/baselines/reference/typedefOnSemicolonClassElement.symbols @@ -0,0 +1,11 @@ +=== tests/cases/conformance/jsdoc/typedefOnSemicolonClassElement.js === +export class Preferences { +>Preferences : Symbol(Preferences, Decl(typedefOnSemicolonClassElement.js, 0, 0)) + + /** @typedef {string} A */ + ; + /** @type {A} */ + a = 'ok' +>a : Symbol(Preferences.a, Decl(typedefOnSemicolonClassElement.js, 2, 3)) +} + diff --git a/tests/baselines/reference/typedefOnSemicolonClassElement.types b/tests/baselines/reference/typedefOnSemicolonClassElement.types new file mode 100644 index 00000000000..e1abbf63ab5 --- /dev/null +++ b/tests/baselines/reference/typedefOnSemicolonClassElement.types @@ -0,0 +1,12 @@ +=== tests/cases/conformance/jsdoc/typedefOnSemicolonClassElement.js === +export class Preferences { +>Preferences : Preferences + + /** @typedef {string} A */ + ; + /** @type {A} */ + a = 'ok' +>a : string +>'ok' : "ok" +} + diff --git a/tests/cases/conformance/jsdoc/typedefOnSemicolonClassElement.ts b/tests/cases/conformance/jsdoc/typedefOnSemicolonClassElement.ts new file mode 100644 index 00000000000..9d0ca2e79c6 --- /dev/null +++ b/tests/cases/conformance/jsdoc/typedefOnSemicolonClassElement.ts @@ -0,0 +1,10 @@ +// @filename: typedefOnSemicolonClassElement.js +// @checkJs: true +// @outdir: dist +// @declaration: true +export class Preferences { + /** @typedef {string} A */ + ; + /** @type {A} */ + a = 'ok' +}