From 960d6192260a0229453d75b8564aee8dc7f9e178 Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Thu, 31 Dec 2020 10:06:36 +0200 Subject: [PATCH] feat(17227): add abstract JSDoc tag --- src/compiler/checker.ts | 18 ++++-- src/compiler/factory/nodeFactory.ts | 3 + src/compiler/factory/nodeTests.ts | 4 ++ src/compiler/parser.ts | 4 ++ src/compiler/types.ts | 7 +++ src/compiler/utilities.ts | 1 + src/compiler/utilitiesPublic.ts | 4 ++ .../reference/api/tsserverlibrary.d.ts | 62 +++++++++++-------- tests/baselines/reference/api/typescript.d.ts | 62 +++++++++++-------- .../reference/jsdocAbstract1.errors.txt | 11 ++++ .../reference/jsdocAbstract1.symbols | 8 +++ .../baselines/reference/jsdocAbstract1.types | 9 +++ .../reference/jsdocAbstract2.symbols | 24 +++++++ .../baselines/reference/jsdocAbstract2.types | 25 ++++++++ .../reference/jsdocAbstract3.errors.txt | 25 ++++++++ .../reference/jsdocAbstract3.symbols | 24 +++++++ .../baselines/reference/jsdocAbstract3.types | 25 ++++++++ .../reference/jsdocAbstract4.errors.txt | 11 ++++ .../reference/jsdocAbstract4.symbols | 9 +++ .../baselines/reference/jsdocAbstract4.types | 9 +++ .../cases/conformance/jsdoc/jsdocAbstract1.ts | 11 ++++ .../cases/conformance/jsdoc/jsdocAbstract2.ts | 21 +++++++ .../cases/conformance/jsdoc/jsdocAbstract3.ts | 21 +++++++ .../cases/conformance/jsdoc/jsdocAbstract4.ts | 11 ++++ 24 files changed, 351 insertions(+), 58 deletions(-) create mode 100644 tests/baselines/reference/jsdocAbstract1.errors.txt create mode 100644 tests/baselines/reference/jsdocAbstract1.symbols create mode 100644 tests/baselines/reference/jsdocAbstract1.types create mode 100644 tests/baselines/reference/jsdocAbstract2.symbols create mode 100644 tests/baselines/reference/jsdocAbstract2.types create mode 100644 tests/baselines/reference/jsdocAbstract3.errors.txt create mode 100644 tests/baselines/reference/jsdocAbstract3.symbols create mode 100644 tests/baselines/reference/jsdocAbstract3.types create mode 100644 tests/baselines/reference/jsdocAbstract4.errors.txt create mode 100644 tests/baselines/reference/jsdocAbstract4.symbols create mode 100644 tests/baselines/reference/jsdocAbstract4.types create mode 100644 tests/cases/conformance/jsdoc/jsdocAbstract1.ts create mode 100644 tests/cases/conformance/jsdoc/jsdocAbstract2.ts create mode 100644 tests/cases/conformance/jsdoc/jsdocAbstract3.ts create mode 100644 tests/cases/conformance/jsdoc/jsdocAbstract4.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a3b147f25e71b..e8cd03d085134 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6800,6 +6800,7 @@ namespace ts { ...!length(baseTypes) ? [] : [factory.createHeritageClause(SyntaxKind.ExtendsKeyword, map(baseTypes, b => serializeBaseType(b, staticBaseType, localName)))], ...!length(implementsExpressions) ? [] : [factory.createHeritageClause(SyntaxKind.ImplementsKeyword, implementsExpressions)] ]; + const modifiers = originalDecl && hasEffectiveModifier(originalDecl, ModifierFlags.Abstract) ? factory.createModifiersFromModifierFlags(ModifierFlags.Abstract) : undefined; const symbolProps = getNonInterhitedProperties(classType, baseTypes, getPropertiesOfType(classType)); const publicSymbolProps = filter(symbolProps, s => { // `valueDeclaration` could be undefined if inherited from @@ -6846,7 +6847,7 @@ namespace ts { context.enclosingDeclaration = oldEnclosing; addResult(setTextRange(factory.createClassDeclaration( /*decorators*/ undefined, - /*modifiers*/ undefined, + modifiers, localName, typeParamDecls, heritageClauses, @@ -28036,7 +28037,7 @@ namespace ts { // In the case of a merged class-module or class-interface declaration, // only the class declaration node will have the Abstract flag set. const valueDecl = expressionType.symbol && getClassLikeDeclarationOfSymbol(expressionType.symbol); - if (valueDecl && hasSyntacticModifier(valueDecl, ModifierFlags.Abstract)) { + if (valueDecl && hasEffectiveModifier(valueDecl, ModifierFlags.Abstract)) { error(node, Diagnostics.Cannot_create_an_instance_of_an_abstract_class); return resolveErrorCall(node); } @@ -29531,7 +29532,7 @@ namespace ts { if (type && type.flags & TypeFlags.Never) { error(getEffectiveReturnTypeNode(func), Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point); } - else if (type && !hasExplicitReturn) { + else if (type && !hasExplicitReturn && !hasEffectiveModifier(func, ModifierFlags.Abstract)) { // minimal check: function has syntactic return type annotation and no explicit return statements in the body // this function does not conform to the specification. // NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present @@ -31899,7 +31900,7 @@ namespace ts { // Abstract methods cannot have an implementation. // Extra checks are to avoid reporting multiple errors relating to the "abstractness" of the node. - if (hasSyntacticModifier(node, ModifierFlags.Abstract) && node.kind === SyntaxKind.MethodDeclaration && node.body) { + if (hasSyntacticModifier(node, ModifierFlags.Abstract) && node.kind === SyntaxKind.MethodDeclaration && node.body && !isInJSFile(node)) { error(node, Diagnostics.Method_0_cannot_have_an_implementation_because_it_is_marked_abstract, declarationNameToString(node.name)); } } @@ -33277,6 +33278,13 @@ namespace ts { checkSignatureDeclaration(node); } + function checkJSDocAbstractTag(node: JSDocAbstractTag): void { + const host = getEffectiveJSDocHost(node); + if (host && isClassElement(host) && !hasEffectiveModifier(host.parent, ModifierFlags.Abstract)) { + error(host, Diagnostics.Abstract_methods_can_only_appear_within_an_abstract_class); + } + } + function checkJSDocImplementsTag(node: JSDocImplementsTag): void { const classLike = getEffectiveJSDocHost(node); if (!classLike || !isClassDeclaration(classLike) && !isClassExpression(classLike)) { @@ -36969,6 +36977,8 @@ namespace ts { return checkImportType(node); case SyntaxKind.NamedTupleMember: return checkNamedTupleMember(node); + case SyntaxKind.JSDocAbstractTag: + return checkJSDocAbstractTag(node); case SyntaxKind.JSDocAugmentsTag: return checkJSDocAugmentsTag(node as JSDocAugmentsTag); case SyntaxKind.JSDocImplementsTag: diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index 176c9154dcd38..1d16d52c357cd 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -354,6 +354,8 @@ namespace ts { get updateJSDocThisTag() { return getJSDocTypeLikeTagUpdateFunction(SyntaxKind.JSDocThisTag); }, get createJSDocEnumTag() { return getJSDocTypeLikeTagCreateFunction(SyntaxKind.JSDocEnumTag); }, get updateJSDocEnumTag() { return getJSDocTypeLikeTagUpdateFunction(SyntaxKind.JSDocEnumTag); }, + get createJSDocAbstractTag() { return getJSDocSimpleTagCreateFunction(SyntaxKind.JSDocAbstractTag); }, + get updateJSDocAbstractTag() { return getJSDocSimpleTagUpdateFunction(SyntaxKind.JSDocAbstractTag); }, get createJSDocAuthorTag() { return getJSDocSimpleTagCreateFunction(SyntaxKind.JSDocAuthorTag); }, get updateJSDocAuthorTag() { return getJSDocSimpleTagUpdateFunction(SyntaxKind.JSDocAuthorTag); }, get createJSDocClassTag() { return getJSDocSimpleTagCreateFunction(SyntaxKind.JSDocClassTag); }, @@ -5859,6 +5861,7 @@ namespace ts { case SyntaxKind.JSDocReturnTag: return "returns"; case SyntaxKind.JSDocThisTag: return "this"; case SyntaxKind.JSDocEnumTag: return "enum"; + case SyntaxKind.JSDocAbstractTag: return "abstract"; case SyntaxKind.JSDocAuthorTag: return "author"; case SyntaxKind.JSDocClassTag: return "class"; case SyntaxKind.JSDocPublicTag: return "public"; diff --git a/src/compiler/factory/nodeTests.ts b/src/compiler/factory/nodeTests.ts index 71b329e46d65c..f37c36134edea 100644 --- a/src/compiler/factory/nodeTests.ts +++ b/src/compiler/factory/nodeTests.ts @@ -757,6 +757,10 @@ namespace ts { return node.kind === SyntaxKind.JSDocAugmentsTag; } + export function isJSDocAbstractTag(node: Node): node is JSDocAbstractTag { + return node.kind === SyntaxKind.JSDocAbstractTag; + } + export function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag { return node.kind === SyntaxKind.JSDocAuthorTag; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b3ae9b9f7b638..404e3041700cc 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -532,6 +532,7 @@ namespace ts { case SyntaxKind.JSDocTypeLiteral: return forEach((node as JSDocTypeLiteral).jsDocPropertyTags, cbNode); case SyntaxKind.JSDocTag: + case SyntaxKind.JSDocAbstractTag: case SyntaxKind.JSDocClassTag: case SyntaxKind.JSDocPublicTag: case SyntaxKind.JSDocPrivateTag: @@ -7443,6 +7444,9 @@ namespace ts { let tag: JSDocTag | undefined; switch (tagName.escapedText) { + case "abstract": + tag = parseSimpleTag(start, factory.createJSDocAbstractTag, tagName, margin, indentText); + break; case "author": tag = parseAuthorTag(start, tagName, margin, indentText); break; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 81181164a7971..57af96debfe18 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -378,6 +378,7 @@ namespace ts { JSDocTag, JSDocAugmentsTag, JSDocImplementsTag, + JSDocAbstractTag, JSDocAuthorTag, JSDocDeprecatedTag, JSDocClassTag, @@ -3166,6 +3167,10 @@ namespace ts { readonly class: ExpressionWithTypeArguments & { readonly expression: Identifier | PropertyAccessEntityNameExpression }; } + export interface JSDocAbstractTag extends JSDocTag { + readonly kind: SyntaxKind.JSDocAbstractTag; + } + export interface JSDocAuthorTag extends JSDocTag { readonly kind: SyntaxKind.JSDocAuthorTag; } @@ -7160,6 +7165,8 @@ namespace ts { updateJSDocAugmentsTag(node: JSDocAugmentsTag, tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment: string | undefined): JSDocAugmentsTag; createJSDocImplementsTag(tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment?: string): JSDocImplementsTag; updateJSDocImplementsTag(node: JSDocImplementsTag, tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment: string | undefined): JSDocImplementsTag; + createJSDocAbstractTag(tagName: Identifier | undefined, comment?: string): JSDocAbstractTag; + updateJSDocAbstractTag(node: JSDocAbstractTag, tagName: Identifier | undefined, comment: string | undefined): JSDocAbstractTag; createJSDocAuthorTag(tagName: Identifier | undefined, comment?: string): JSDocAuthorTag; updateJSDocAuthorTag(node: JSDocAuthorTag, tagName: Identifier | undefined, comment: string | undefined): JSDocAuthorTag; createJSDocClassTag(tagName: Identifier | undefined, comment?: string): JSDocClassTag; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 12b815995cfa7..016476a78fbeb 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4719,6 +4719,7 @@ namespace ts { if (getJSDocPrivateTagNoCache(node)) flags |= ModifierFlags.Private; if (getJSDocProtectedTagNoCache(node)) flags |= ModifierFlags.Protected; if (getJSDocReadonlyTagNoCache(node)) flags |= ModifierFlags.Readonly; + if (getJSDocAbstractTagNoCache(node)) flags |= ModifierFlags.Abstract; } if (getJSDocDeprecatedTagNoCache(node)) flags |= ModifierFlags.Deprecated; } diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 6722e7ad5be1f..149e90303c4fe 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -767,6 +767,10 @@ namespace ts { return getFirstJSDocTag(node, isJSDocReadonlyTag, /*noCache*/ true); } + export function getJSDocAbstractTagNoCache(node: Node): JSDocAbstractTag | undefined { + return getFirstJSDocTag(node, isJSDocAbstractTag, /*noCache*/ true); + } + /** Gets the JSDoc deprecated tag for the node if present */ export function getJSDocDeprecatedTag(node: Node): JSDocDeprecatedTag | undefined { return getFirstJSDocTag(node, isJSDocDeprecatedTag); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index f2795baa971fd..a0378982c956f 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -421,31 +421,32 @@ declare namespace ts { JSDocTag = 314, JSDocAugmentsTag = 315, JSDocImplementsTag = 316, - JSDocAuthorTag = 317, - JSDocDeprecatedTag = 318, - JSDocClassTag = 319, - JSDocPublicTag = 320, - JSDocPrivateTag = 321, - JSDocProtectedTag = 322, - JSDocReadonlyTag = 323, - JSDocCallbackTag = 324, - JSDocEnumTag = 325, - JSDocParameterTag = 326, - JSDocReturnTag = 327, - JSDocThisTag = 328, - JSDocTypeTag = 329, - JSDocTemplateTag = 330, - JSDocTypedefTag = 331, - JSDocSeeTag = 332, - JSDocPropertyTag = 333, - SyntaxList = 334, - NotEmittedStatement = 335, - PartiallyEmittedExpression = 336, - CommaListExpression = 337, - MergeDeclarationMarker = 338, - EndOfDeclarationMarker = 339, - SyntheticReferenceExpression = 340, - Count = 341, + JSDocAbstractTag = 317, + JSDocAuthorTag = 318, + JSDocDeprecatedTag = 319, + JSDocClassTag = 320, + JSDocPublicTag = 321, + JSDocPrivateTag = 322, + JSDocProtectedTag = 323, + JSDocReadonlyTag = 324, + JSDocCallbackTag = 325, + JSDocEnumTag = 326, + JSDocParameterTag = 327, + JSDocReturnTag = 328, + JSDocThisTag = 329, + JSDocTypeTag = 330, + JSDocTemplateTag = 331, + JSDocTypedefTag = 332, + JSDocSeeTag = 333, + JSDocPropertyTag = 334, + SyntaxList = 335, + NotEmittedStatement = 336, + PartiallyEmittedExpression = 337, + CommaListExpression = 338, + MergeDeclarationMarker = 339, + EndOfDeclarationMarker = 340, + SyntheticReferenceExpression = 341, + Count = 342, FirstAssignment = 62, LastAssignment = 77, FirstCompoundAssignment = 63, @@ -474,9 +475,9 @@ declare namespace ts { LastStatement = 248, FirstNode = 157, FirstJSDocNode = 301, - LastJSDocNode = 333, + LastJSDocNode = 334, FirstJSDocTagNode = 314, - LastJSDocTagNode = 333, + LastJSDocTagNode = 334, } export type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; export type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; @@ -1768,6 +1769,9 @@ declare namespace ts { readonly expression: Identifier | PropertyAccessEntityNameExpression; }; } + export interface JSDocAbstractTag extends JSDocTag { + readonly kind: SyntaxKind.JSDocAbstractTag; + } export interface JSDocAuthorTag extends JSDocTag { readonly kind: SyntaxKind.JSDocAuthorTag; } @@ -3479,6 +3483,8 @@ declare namespace ts { updateJSDocAugmentsTag(node: JSDocAugmentsTag, tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment: string | undefined): JSDocAugmentsTag; createJSDocImplementsTag(tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment?: string): JSDocImplementsTag; updateJSDocImplementsTag(node: JSDocImplementsTag, tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment: string | undefined): JSDocImplementsTag; + createJSDocAbstractTag(tagName: Identifier | undefined, comment?: string): JSDocAbstractTag; + updateJSDocAbstractTag(node: JSDocAbstractTag, tagName: Identifier | undefined, comment: string | undefined): JSDocAbstractTag; createJSDocAuthorTag(tagName: Identifier | undefined, comment?: string): JSDocAuthorTag; updateJSDocAuthorTag(node: JSDocAuthorTag, tagName: Identifier | undefined, comment: string | undefined): JSDocAuthorTag; createJSDocClassTag(tagName: Identifier | undefined, comment?: string): JSDocClassTag; @@ -4141,6 +4147,7 @@ declare namespace ts { function getJSDocProtectedTag(node: Node): JSDocProtectedTag | undefined; /** Gets the JSDoc protected tag for the node if present */ function getJSDocReadonlyTag(node: Node): JSDocReadonlyTag | undefined; + function getJSDocAbstractTagNoCache(node: Node): JSDocAbstractTag | undefined; /** Gets the JSDoc deprecated tag for the node if present */ function getJSDocDeprecatedTag(node: Node): JSDocDeprecatedTag | undefined; /** Gets the JSDoc enum tag for the node if present */ @@ -4499,6 +4506,7 @@ declare namespace ts { function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral; function isJSDocSignature(node: Node): node is JSDocSignature; function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag; + function isJSDocAbstractTag(node: Node): node is JSDocAbstractTag; function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag; function isJSDocClassTag(node: Node): node is JSDocClassTag; function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 0f9c37e24b4ce..81662258e5251 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -421,31 +421,32 @@ declare namespace ts { JSDocTag = 314, JSDocAugmentsTag = 315, JSDocImplementsTag = 316, - JSDocAuthorTag = 317, - JSDocDeprecatedTag = 318, - JSDocClassTag = 319, - JSDocPublicTag = 320, - JSDocPrivateTag = 321, - JSDocProtectedTag = 322, - JSDocReadonlyTag = 323, - JSDocCallbackTag = 324, - JSDocEnumTag = 325, - JSDocParameterTag = 326, - JSDocReturnTag = 327, - JSDocThisTag = 328, - JSDocTypeTag = 329, - JSDocTemplateTag = 330, - JSDocTypedefTag = 331, - JSDocSeeTag = 332, - JSDocPropertyTag = 333, - SyntaxList = 334, - NotEmittedStatement = 335, - PartiallyEmittedExpression = 336, - CommaListExpression = 337, - MergeDeclarationMarker = 338, - EndOfDeclarationMarker = 339, - SyntheticReferenceExpression = 340, - Count = 341, + JSDocAbstractTag = 317, + JSDocAuthorTag = 318, + JSDocDeprecatedTag = 319, + JSDocClassTag = 320, + JSDocPublicTag = 321, + JSDocPrivateTag = 322, + JSDocProtectedTag = 323, + JSDocReadonlyTag = 324, + JSDocCallbackTag = 325, + JSDocEnumTag = 326, + JSDocParameterTag = 327, + JSDocReturnTag = 328, + JSDocThisTag = 329, + JSDocTypeTag = 330, + JSDocTemplateTag = 331, + JSDocTypedefTag = 332, + JSDocSeeTag = 333, + JSDocPropertyTag = 334, + SyntaxList = 335, + NotEmittedStatement = 336, + PartiallyEmittedExpression = 337, + CommaListExpression = 338, + MergeDeclarationMarker = 339, + EndOfDeclarationMarker = 340, + SyntheticReferenceExpression = 341, + Count = 342, FirstAssignment = 62, LastAssignment = 77, FirstCompoundAssignment = 63, @@ -474,9 +475,9 @@ declare namespace ts { LastStatement = 248, FirstNode = 157, FirstJSDocNode = 301, - LastJSDocNode = 333, + LastJSDocNode = 334, FirstJSDocTagNode = 314, - LastJSDocTagNode = 333, + LastJSDocTagNode = 334, } export type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; export type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; @@ -1768,6 +1769,9 @@ declare namespace ts { readonly expression: Identifier | PropertyAccessEntityNameExpression; }; } + export interface JSDocAbstractTag extends JSDocTag { + readonly kind: SyntaxKind.JSDocAbstractTag; + } export interface JSDocAuthorTag extends JSDocTag { readonly kind: SyntaxKind.JSDocAuthorTag; } @@ -3479,6 +3483,8 @@ declare namespace ts { updateJSDocAugmentsTag(node: JSDocAugmentsTag, tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment: string | undefined): JSDocAugmentsTag; createJSDocImplementsTag(tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment?: string): JSDocImplementsTag; updateJSDocImplementsTag(node: JSDocImplementsTag, tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment: string | undefined): JSDocImplementsTag; + createJSDocAbstractTag(tagName: Identifier | undefined, comment?: string): JSDocAbstractTag; + updateJSDocAbstractTag(node: JSDocAbstractTag, tagName: Identifier | undefined, comment: string | undefined): JSDocAbstractTag; createJSDocAuthorTag(tagName: Identifier | undefined, comment?: string): JSDocAuthorTag; updateJSDocAuthorTag(node: JSDocAuthorTag, tagName: Identifier | undefined, comment: string | undefined): JSDocAuthorTag; createJSDocClassTag(tagName: Identifier | undefined, comment?: string): JSDocClassTag; @@ -4141,6 +4147,7 @@ declare namespace ts { function getJSDocProtectedTag(node: Node): JSDocProtectedTag | undefined; /** Gets the JSDoc protected tag for the node if present */ function getJSDocReadonlyTag(node: Node): JSDocReadonlyTag | undefined; + function getJSDocAbstractTagNoCache(node: Node): JSDocAbstractTag | undefined; /** Gets the JSDoc deprecated tag for the node if present */ function getJSDocDeprecatedTag(node: Node): JSDocDeprecatedTag | undefined; /** Gets the JSDoc enum tag for the node if present */ @@ -4499,6 +4506,7 @@ declare namespace ts { function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral; function isJSDocSignature(node: Node): node is JSDocSignature; function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag; + function isJSDocAbstractTag(node: Node): node is JSDocAbstractTag; function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag; function isJSDocClassTag(node: Node): node is JSDocClassTag; function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag; diff --git a/tests/baselines/reference/jsdocAbstract1.errors.txt b/tests/baselines/reference/jsdocAbstract1.errors.txt new file mode 100644 index 0000000000000..a4f6aeb282df9 --- /dev/null +++ b/tests/baselines/reference/jsdocAbstract1.errors.txt @@ -0,0 +1,11 @@ +tests/cases/conformance/jsdoc/jsdocAbstract1.js(4,1): error TS2511: Cannot create an instance of an abstract class. + + +==== tests/cases/conformance/jsdoc/jsdocAbstract1.js (1 errors) ==== + /** @abstract */ + class A { + } + new A() + ~~~~~~~ +!!! error TS2511: Cannot create an instance of an abstract class. + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocAbstract1.symbols b/tests/baselines/reference/jsdocAbstract1.symbols new file mode 100644 index 0000000000000..e7f7a3f13f832 --- /dev/null +++ b/tests/baselines/reference/jsdocAbstract1.symbols @@ -0,0 +1,8 @@ +=== tests/cases/conformance/jsdoc/jsdocAbstract1.js === +/** @abstract */ +class A { +>A : Symbol(A, Decl(jsdocAbstract1.js, 0, 0)) +} +new A() +>A : Symbol(A, Decl(jsdocAbstract1.js, 0, 0)) + diff --git a/tests/baselines/reference/jsdocAbstract1.types b/tests/baselines/reference/jsdocAbstract1.types new file mode 100644 index 0000000000000..507cbe62409a3 --- /dev/null +++ b/tests/baselines/reference/jsdocAbstract1.types @@ -0,0 +1,9 @@ +=== tests/cases/conformance/jsdoc/jsdocAbstract1.js === +/** @abstract */ +class A { +>A : A +} +new A() +>new A() : any +>A : typeof A + diff --git a/tests/baselines/reference/jsdocAbstract2.symbols b/tests/baselines/reference/jsdocAbstract2.symbols new file mode 100644 index 0000000000000..97170773784ef --- /dev/null +++ b/tests/baselines/reference/jsdocAbstract2.symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/jsdoc/jsdocAbstract2.js === +/** @abstract */ +class A { +>A : Symbol(A, Decl(jsdocAbstract2.js, 0, 0)) + + /** + * @abstract + * @returns {number} + */ + foo() {} +>foo : Symbol(A.foo, Decl(jsdocAbstract2.js, 1, 9)) +} + +class B extends A { +>B : Symbol(B, Decl(jsdocAbstract2.js, 7, 1)) +>A : Symbol(A, Decl(jsdocAbstract2.js, 0, 0)) + + foo() { +>foo : Symbol(B.foo, Decl(jsdocAbstract2.js, 9, 19)) + + return 1; + } +} + diff --git a/tests/baselines/reference/jsdocAbstract2.types b/tests/baselines/reference/jsdocAbstract2.types new file mode 100644 index 0000000000000..25a1b8bd6c2e8 --- /dev/null +++ b/tests/baselines/reference/jsdocAbstract2.types @@ -0,0 +1,25 @@ +=== tests/cases/conformance/jsdoc/jsdocAbstract2.js === +/** @abstract */ +class A { +>A : A + + /** + * @abstract + * @returns {number} + */ + foo() {} +>foo : () => number +} + +class B extends A { +>B : B +>A : A + + foo() { +>foo : () => number + + return 1; +>1 : 1 + } +} + diff --git a/tests/baselines/reference/jsdocAbstract3.errors.txt b/tests/baselines/reference/jsdocAbstract3.errors.txt new file mode 100644 index 0000000000000..a142e51936a8f --- /dev/null +++ b/tests/baselines/reference/jsdocAbstract3.errors.txt @@ -0,0 +1,25 @@ +tests/cases/conformance/jsdoc/jsdocAbstract3.js(11,5): error TS2416: Property 'foo' in type 'B' is not assignable to the same property in base type 'A'. + Type '() => string' is not assignable to type '() => number'. + Type 'string' is not assignable to type 'number'. + + +==== tests/cases/conformance/jsdoc/jsdocAbstract3.js (1 errors) ==== + /** @abstract */ + class A { + /** + * @abstract + * @returns {number} + */ + foo() {} + } + + class B extends A { + foo() { + ~~~ +!!! error TS2416: Property 'foo' in type 'B' is not assignable to the same property in base type 'A'. +!!! error TS2416: Type '() => string' is not assignable to type '() => number'. +!!! error TS2416: Type 'string' is not assignable to type 'number'. + return ""; + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocAbstract3.symbols b/tests/baselines/reference/jsdocAbstract3.symbols new file mode 100644 index 0000000000000..39d42d605cdaf --- /dev/null +++ b/tests/baselines/reference/jsdocAbstract3.symbols @@ -0,0 +1,24 @@ +=== tests/cases/conformance/jsdoc/jsdocAbstract3.js === +/** @abstract */ +class A { +>A : Symbol(A, Decl(jsdocAbstract3.js, 0, 0)) + + /** + * @abstract + * @returns {number} + */ + foo() {} +>foo : Symbol(A.foo, Decl(jsdocAbstract3.js, 1, 9)) +} + +class B extends A { +>B : Symbol(B, Decl(jsdocAbstract3.js, 7, 1)) +>A : Symbol(A, Decl(jsdocAbstract3.js, 0, 0)) + + foo() { +>foo : Symbol(B.foo, Decl(jsdocAbstract3.js, 9, 19)) + + return ""; + } +} + diff --git a/tests/baselines/reference/jsdocAbstract3.types b/tests/baselines/reference/jsdocAbstract3.types new file mode 100644 index 0000000000000..42a3f9f50e17d --- /dev/null +++ b/tests/baselines/reference/jsdocAbstract3.types @@ -0,0 +1,25 @@ +=== tests/cases/conformance/jsdoc/jsdocAbstract3.js === +/** @abstract */ +class A { +>A : A + + /** + * @abstract + * @returns {number} + */ + foo() {} +>foo : () => number +} + +class B extends A { +>B : B +>A : A + + foo() { +>foo : () => string + + return ""; +>"" : "" + } +} + diff --git a/tests/baselines/reference/jsdocAbstract4.errors.txt b/tests/baselines/reference/jsdocAbstract4.errors.txt new file mode 100644 index 0000000000000..9cd4e45df0c0a --- /dev/null +++ b/tests/baselines/reference/jsdocAbstract4.errors.txt @@ -0,0 +1,11 @@ +tests/cases/conformance/jsdoc/jsdocAbstract4.js(3,5): error TS1244: Abstract methods can only appear within an abstract class. + + +==== tests/cases/conformance/jsdoc/jsdocAbstract4.js (1 errors) ==== + class Foo { + /** @abstract */ + foo() {} + ~~~ +!!! error TS1244: Abstract methods can only appear within an abstract class. + } + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocAbstract4.symbols b/tests/baselines/reference/jsdocAbstract4.symbols new file mode 100644 index 0000000000000..e3e8a6f00708d --- /dev/null +++ b/tests/baselines/reference/jsdocAbstract4.symbols @@ -0,0 +1,9 @@ +=== tests/cases/conformance/jsdoc/jsdocAbstract4.js === +class Foo { +>Foo : Symbol(Foo, Decl(jsdocAbstract4.js, 0, 0)) + + /** @abstract */ + foo() {} +>foo : Symbol(Foo.foo, Decl(jsdocAbstract4.js, 0, 11)) +} + diff --git a/tests/baselines/reference/jsdocAbstract4.types b/tests/baselines/reference/jsdocAbstract4.types new file mode 100644 index 0000000000000..8c863c17a5fa7 --- /dev/null +++ b/tests/baselines/reference/jsdocAbstract4.types @@ -0,0 +1,9 @@ +=== tests/cases/conformance/jsdoc/jsdocAbstract4.js === +class Foo { +>Foo : Foo + + /** @abstract */ + foo() {} +>foo : () => void +} + diff --git a/tests/cases/conformance/jsdoc/jsdocAbstract1.ts b/tests/cases/conformance/jsdoc/jsdocAbstract1.ts new file mode 100644 index 0000000000000..deb5e35fe970f --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocAbstract1.ts @@ -0,0 +1,11 @@ +// @allowJs: true +// @checkJs: true +// @target: esnext +// @declaration: true +// @emitDeclarationOnly: true +// @Filename: jsdocAbstract1.js + +/** @abstract */ +class A { +} +new A() diff --git a/tests/cases/conformance/jsdoc/jsdocAbstract2.ts b/tests/cases/conformance/jsdoc/jsdocAbstract2.ts new file mode 100644 index 0000000000000..15c7eda55437e --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocAbstract2.ts @@ -0,0 +1,21 @@ +// @allowJs: true +// @checkJs: true +// @target: esnext +// @declaration: true +// @emitDeclarationOnly: true +// @Filename: jsdocAbstract2.js + +/** @abstract */ +class A { + /** + * @abstract + * @returns {number} + */ + foo() {} +} + +class B extends A { + foo() { + return 1; + } +} diff --git a/tests/cases/conformance/jsdoc/jsdocAbstract3.ts b/tests/cases/conformance/jsdoc/jsdocAbstract3.ts new file mode 100644 index 0000000000000..4376f5f4725c6 --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocAbstract3.ts @@ -0,0 +1,21 @@ +// @allowJs: true +// @checkJs: true +// @target: esnext +// @declaration: true +// @emitDeclarationOnly: true +// @Filename: jsdocAbstract3.js + +/** @abstract */ +class A { + /** + * @abstract + * @returns {number} + */ + foo() {} +} + +class B extends A { + foo() { + return ""; + } +} diff --git a/tests/cases/conformance/jsdoc/jsdocAbstract4.ts b/tests/cases/conformance/jsdoc/jsdocAbstract4.ts new file mode 100644 index 0000000000000..5f949db702c40 --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocAbstract4.ts @@ -0,0 +1,11 @@ +// @allowJs: true +// @checkJs: true +// @target: esnext +// @declaration: true +// @emitDeclarationOnly: true +// @Filename: jsdocAbstract4.js + +class Foo { + /** @abstract */ + foo() {} +}