From fbc5966465441536ede196e6550a9c10fbfb9e68 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 21 Mar 2021 19:10:49 -0600 Subject: [PATCH] fix: Static properties of Error class incorrectly converted Closes #1541 Closes #572 --- src/lib/converter/context.ts | 6 + src/lib/converter/symbols.ts | 15 +- .../converter/inheritance/mergable-class.ts | 12 + src/test/converter/inheritance/specs.json | 796 ++++++++++++------ 4 files changed, 545 insertions(+), 284 deletions(-) create mode 100644 src/test/converter/inheritance/mergable-class.ts diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index 134e7c86b..7dcec2e40 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -83,6 +83,9 @@ export class Context { */ exportSymbol?: ts.Symbol; + /** @internal */ + shouldBeStatic = false; + private convertingTypeNode = false; /** @@ -190,6 +193,9 @@ export class Context { nameOverride ?? exportSymbol?.name ?? symbol?.name ?? "unknown" ); const reflection = new DeclarationReflection(name, kind, this.scope); + if (this.shouldBeStatic) { + reflection.setFlag(ReflectionFlag.Static); + } reflection.escapedName = symbol?.escapedName; this.addChild(reflection); diff --git a/src/lib/converter/symbols.ts b/src/lib/converter/symbols.ts index 8efd88565..023121154 100644 --- a/src/lib/converter/symbols.ts +++ b/src/lib/converter/symbols.ts @@ -424,6 +424,7 @@ function convertClassOrInterface( classDeclaration ); + reflectionContext.shouldBeStatic = true; for (const prop of context.checker.getPropertiesOfType(staticType)) { // Don't convert namespace members, or the prototype here. if ( @@ -433,6 +434,7 @@ function convertClassOrInterface( continue; convertSymbol(reflectionContext, prop); } + reflectionContext.shouldBeStatic = false; const constructMember = new DeclarationReflection( "constructor", @@ -918,16 +920,7 @@ function setModifiers( ReflectionFlag.Abstract, hasAllFlags(modifiers, ts.ModifierFlags.Abstract) ); - reflection.setFlag( - ReflectionFlag.Static, - hasAllFlags(modifiers, ts.ModifierFlags.Static) - ); - // JS users can create "classes" by adding properties to functions. See GH1481. - if ( - reflection.parent?.kind == ReflectionKind.Class && - ts.isPropertyAccessExpression(declaration) - ) { - reflection.setFlag(ReflectionFlag.Static); - } + // ReflectionFlag.Static happens when constructing the reflection. + // We don't have sufficient information here to determine if it ought to be static. } diff --git a/src/test/converter/inheritance/mergable-class.ts b/src/test/converter/inheritance/mergable-class.ts new file mode 100644 index 000000000..b950b5e4b --- /dev/null +++ b/src/test/converter/inheritance/mergable-class.ts @@ -0,0 +1,12 @@ +export interface MyCtor { + staticProp: 1; + new (): My; +} + +export interface My { + instanceProp: 1; +} + +export declare const My: MyCtor; + +export class MySubClass extends My {} diff --git a/src/test/converter/inheritance/specs.json b/src/test/converter/inheritance/specs.json index f2755ef85..2975d4283 100644 --- a/src/test/converter/inheritance/specs.json +++ b/src/test/converter/inheritance/specs.json @@ -2,168 +2,387 @@ "id": 0, "name": "typedoc", "kind": 0, - "kindString": "Project", "flags": {}, "children": [ { - "id": 13, - "name": "InterfaceSource", - "kind": 256, - "kindString": "Interface", + "id": 1, + "name": "inherit-doc", + "kind": 1, + "kindString": "Module", "flags": {}, - "comment": { - "shortText": "Source interface summary" - }, "children": [ { "id": 14, - "name": "property", - "kind": 1024, - "kindString": "Property", + "name": "InterfaceSource", + "kind": 256, + "kindString": "Interface", "flags": {}, "comment": { - "shortText": "Source interface property description", - "tags": [ - { - "tag": "typeparam", - "text": "Source interface type parameter\n", - "param": "T" + "shortText": "Source interface summary" + }, + "children": [ + { + "id": 15, + "name": "property", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "comment": { + "shortText": "Source interface property description", + "tags": [ + { + "tag": "typeparam", + "text": "Source interface type parameter\n", + "param": "T" + } + ] + }, + "type": { + "type": "reference", + "name": "T" + } + }, + { + "id": 16, + "name": "someMethod", + "kind": 2048, + "kindString": "Method", + "flags": {}, + "signatures": [ + { + "id": 17, + "name": "someMethod", + "kind": 4096, + "kindString": "Call signature", + "flags": {}, + "comment": { + "shortText": "Source interface method description" + }, + "parameters": [ + { + "id": 18, + "name": "arg", + "kind": 32768, + "kindString": "Parameter", + "flags": {}, + "comment": { + "text": "\n" + }, + "type": { + "type": "intrinsic", + "name": "number" + } + } + ], + "type": { + "type": "reference", + "name": "T" + } + } + ] + } + ], + "groups": [ + { + "title": "Properties", + "kind": 1024, + "children": [ + 15 + ] + }, + { + "title": "Methods", + "kind": 2048, + "children": [ + 16 + ] + } + ], + "typeParameter": [ + { + "id": 19, + "name": "T", + "kind": 131072, + "kindString": "Type parameter", + "flags": {}, + "comment": { + "shortText": "Source interface type parameter\n" } - ] + } + ] + }, + { + "id": 20, + "name": "InterfaceTarget", + "kind": 256, + "kindString": "Interface", + "flags": {}, + "comment": { + "shortText": "Source interface summary" }, - "type": { - "type": "reference", - "name": "T" - } + "children": [ + { + "id": 21, + "name": "property", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "comment": { + "shortText": "Source interface property description" + }, + "type": { + "type": "reference", + "name": "T" + } + }, + { + "id": 22, + "name": "someMethod", + "kind": 2048, + "kindString": "Method", + "flags": {}, + "signatures": [ + { + "id": 23, + "name": "someMethod", + "kind": 4096, + "kindString": "Call signature", + "flags": {}, + "comment": { + "shortText": "Source interface method description" + }, + "parameters": [ + { + "id": 18, + "name": "arg", + "kind": 32768, + "kindString": "Parameter", + "flags": {}, + "comment": { + "text": "\n" + }, + "type": { + "type": "intrinsic", + "name": "number" + } + } + ], + "type": { + "type": "reference", + "name": "T" + } + } + ] + } + ], + "groups": [ + { + "title": "Properties", + "kind": 1024, + "children": [ + 21 + ] + }, + { + "title": "Methods", + "kind": 2048, + "children": [ + 22 + ] + } + ], + "typeParameter": [ + { + "id": 19, + "name": "T", + "kind": 131072, + "kindString": "Type parameter", + "flags": {}, + "comment": { + "shortText": "Source interface type parameter\n" + } + } + ] }, { - "id": 15, - "name": "someMethod", - "kind": 2048, - "kindString": "Method", + "id": 2, + "name": "functionSource", + "kind": 64, + "kindString": "Function", "flags": {}, "signatures": [ { - "id": 16, - "name": "someMethod", + "id": 3, + "name": "functionSource", "kind": 4096, "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Source interface method description" + "shortText": "Function summary", + "text": "This part of the commentary will be inherited by other entities\n", + "returns": "Stringified sum or concatenation of numeric arguments\n", + "tags": [ + { + "tag": "remarks", + "text": "\n\nRemarks will be inherited\n" + }, + { + "tag": "example", + "text": "\n\nThis part of the commentary will not be inherited\n" + } + ] }, + "typeParameter": [ + { + "id": 4, + "name": "T", + "kind": 131072, + "kindString": "Type parameter", + "flags": {}, + "comment": { + "text": "Type of arguments" + } + } + ], "parameters": [ { - "id": 17, - "name": "arg", + "id": 5, + "name": "arg1", "kind": 32768, "kindString": "Parameter", "flags": {}, "comment": { - "text": "\n" + "text": "First argument" }, "type": { - "type": "intrinsic", - "name": "number" + "type": "reference", + "name": "T" + } + }, + { + "id": 6, + "name": "arg2", + "kind": 32768, + "kindString": "Parameter", + "flags": {}, + "comment": { + "text": "Second argument" + }, + "type": { + "type": "reference", + "name": "T" } } ], "type": { - "type": "reference", - "name": "T" + "type": "intrinsic", + "name": "string" } } ] - } - ], - "groups": [ - { - "title": "Properties", - "kind": 1024, - "children": [ - 14 - ] }, { - "title": "Methods", - "kind": 2048, - "children": [ - 15 - ] - } - ], - "typeParameter": [ - { - "id": 18, - "name": "T", - "kind": 131072, - "kindString": "Type parameter", - "flags": {}, - "comment": { - "shortText": "Source interface type parameter\n" - } - } - ] - }, - { - "id": 19, - "name": "InterfaceTarget", - "kind": 256, - "kindString": "Interface", - "flags": {}, - "comment": { - "shortText": "Source interface summary" - }, - "children": [ - { - "id": 20, - "name": "property", - "kind": 1024, - "kindString": "Property", + "id": 7, + "name": "functionTargetGlobal", + "kind": 64, + "kindString": "Function", "flags": {}, - "comment": { - "shortText": "Source interface property description" - }, - "type": { - "type": "reference", - "name": "T" - } + "signatures": [ + { + "id": 8, + "name": "functionTargetGlobal", + "kind": 4096, + "kindString": "Call signature", + "flags": {}, + "comment": { + "tags": [ + { + "tag": "inheritdoc", + "text": "\n", + "param": "SubClassA.printName" + } + ] + }, + "type": { + "type": "intrinsic", + "name": "string" + } + } + ] }, { - "id": 21, - "name": "someMethod", - "kind": 2048, - "kindString": "Method", + "id": 9, + "name": "functionTargetLocal", + "kind": 64, + "kindString": "Function", "flags": {}, "signatures": [ { - "id": 22, - "name": "someMethod", + "id": 10, + "name": "functionTargetLocal", "kind": 4096, "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Source interface method description" + "shortText": "Function summary", + "text": "This part of the commentary will be inherited by other entities\n", + "returns": "This will be inherited\n\n", + "tags": [ + { + "tag": "example", + "text": "\n\nThis function inherited commentary from the `functionSource` function\n" + }, + { + "tag": "remarks", + "text": "\n\nRemarks will be inherited\n" + } + ] }, + "typeParameter": [ + { + "id": 4, + "name": "T", + "kind": 131072, + "kindString": "Type parameter", + "flags": {}, + "comment": { + "text": "Type of arguments" + } + } + ], "parameters": [ { - "id": 17, - "name": "arg", + "id": 5, + "name": "arg1", + "kind": 32768, + "kindString": "Parameter", + "flags": {}, + "comment": { + "text": "First argument" + }, + "type": { + "type": "reference", + "name": "T" + } + }, + { + "id": 6, + "name": "arg2", "kind": 32768, "kindString": "Parameter", "flags": {}, "comment": { - "text": "\n" + "text": "Second argument" }, "type": { - "type": "intrinsic", - "name": "number" + "type": "reference", + "name": "T" } } ], "type": { - "type": "reference", - "name": "T" + "type": "intrinsic", + "name": "string" } } ] @@ -171,233 +390,264 @@ ], "groups": [ { - "title": "Properties", - "kind": 1024, + "title": "Interfaces", + "kind": 256, "children": [ + 14, 20 ] }, { - "title": "Methods", - "kind": 2048, + "title": "Functions", + "kind": 64, "children": [ - 21 + 2, + 7, + 9 ] } - ], - "typeParameter": [ - { - "id": 18, - "name": "T", - "kind": 131072, - "kindString": "Type parameter", - "flags": {}, - "comment": { - "shortText": "Source interface type parameter\n" - } - } ] }, { - "id": 1, - "name": "functionSource", - "kind": 64, - "kindString": "Function", + "id": 26, + "name": "mergable-class", + "kind": 1, + "kindString": "Module", "flags": {}, - "signatures": [ + "children": [ { - "id": 2, - "name": "functionSource", - "kind": 4096, - "kindString": "Call signature", + "id": 34, + "name": "MySubClass", + "kind": 128, + "kindString": "Class", "flags": {}, - "comment": { - "shortText": "Function summary", - "text": "This part of the commentary will be inherited by other entities\n", - "returns": "Stringified sum or concatenation of numeric arguments\n", - "tags": [ - { - "tag": "remarks", - "text": "\n\nRemarks will be inherited\n" - }, - { - "tag": "example", - "text": "\n\nThis part of the commentary will not be inherited\n" - } - ] - }, - "typeParameter": [ + "children": [ { - "id": 3, - "name": "T", - "kind": 131072, - "kindString": "Type parameter", + "id": 36, + "name": "constructor", + "kind": 512, + "kindString": "Constructor", "flags": {}, - "comment": { - "text": "Type of arguments" + "signatures": [ + { + "id": 37, + "name": "new MySubClass", + "kind": 16384, + "kindString": "Constructor signature", + "flags": {}, + "type": { + "type": "reference", + "id": 34, + "name": "MySubClass" + }, + "inheritedFrom": { + "type": "reference", + "name": "My.constructor" + } + } + ], + "inheritedFrom": { + "type": "reference", + "name": "My.constructor" } - } - ], - "parameters": [ + }, { - "id": 4, - "name": "arg1", - "kind": 32768, - "kindString": "Parameter", + "id": 38, + "name": "instanceProp", + "kind": 1024, + "kindString": "Property", "flags": {}, - "comment": { - "text": "First argument" - }, "type": { + "type": "literal", + "value": 1 + }, + "inheritedFrom": { "type": "reference", - "name": "T" + "name": "My.instanceProp" } }, { - "id": 5, - "name": "arg2", - "kind": 32768, - "kindString": "Parameter", - "flags": {}, - "comment": { - "text": "Second argument" + "id": 35, + "name": "staticProp", + "kind": 1024, + "kindString": "Property", + "flags": { + "isStatic": true }, "type": { + "type": "literal", + "value": 1 + }, + "inheritedFrom": { "type": "reference", - "name": "T" + "name": "My.staticProp" } } ], - "type": { - "type": "intrinsic", - "name": "string" - } - } - ] - }, - { - "id": 6, - "name": "functionTargetGlobal", - "kind": 64, - "kindString": "Function", - "flags": {}, - "signatures": [ - { - "id": 7, - "name": "functionTargetGlobal", - "kind": 4096, - "kindString": "Call signature", - "flags": {}, - "comment": { - "tags": [ - { - "tag": "inheritdoc", - "text": "\n", - "param": "SubClassA.printName" - } - ] - }, - "type": { - "type": "intrinsic", - "name": "string" - } - } - ] - }, - { - "id": 8, - "name": "functionTargetLocal", - "kind": 64, - "kindString": "Function", - "flags": {}, - "signatures": [ + "groups": [ + { + "title": "Constructors", + "kind": 512, + "children": [ + 36 + ] + }, + { + "title": "Properties", + "kind": 1024, + "children": [ + 38, + 35 + ] + } + ], + "extendedTypes": [ + { + "type": "reference", + "id": 31, + "name": "My" + } + ] + }, { - "id": 9, - "name": "functionTargetLocal", - "kind": 4096, - "kindString": "Call signature", + "id": 32, + "name": "My", + "kind": 256, + "kindString": "Interface", "flags": {}, - "comment": { - "shortText": "Function summary", - "text": "This part of the commentary will be inherited by other entities\n", - "returns": "This will be inherited\n\n", - "tags": [ - { - "tag": "example", - "text": "\n\nThis function inherited commentary from the `functionSource` function\n" - }, - { - "tag": "remarks", - "text": "\n\nRemarks will be inherited\n" - } - ] - }, - "typeParameter": [ + "children": [ { - "id": 3, - "name": "T", - "kind": 131072, - "kindString": "Type parameter", + "id": 33, + "name": "instanceProp", + "kind": 1024, + "kindString": "Property", "flags": {}, - "comment": { - "text": "Type of arguments" + "type": { + "type": "literal", + "value": 1 } } ], - "parameters": [ + "groups": [ { - "id": 4, - "name": "arg1", - "kind": 32768, - "kindString": "Parameter", + "title": "Properties", + "kind": 1024, + "children": [ + 33 + ] + } + ] + }, + { + "id": 27, + "name": "MyCtor", + "kind": 256, + "kindString": "Interface", + "flags": {}, + "children": [ + { + "id": 29, + "name": "constructor", + "kind": 512, + "kindString": "Constructor", "flags": {}, - "comment": { - "text": "First argument" - }, - "type": { - "type": "reference", - "name": "T" - } + "signatures": [ + { + "id": 30, + "name": "new MyCtor", + "kind": 16384, + "kindString": "Constructor signature", + "flags": {}, + "type": { + "type": "reference", + "id": 31, + "name": "My" + } + } + ] }, { - "id": 5, - "name": "arg2", - "kind": 32768, - "kindString": "Parameter", + "id": 28, + "name": "staticProp", + "kind": 1024, + "kindString": "Property", "flags": {}, - "comment": { - "text": "Second argument" - }, "type": { - "type": "reference", - "name": "T" + "type": "literal", + "value": 1 } } ], + "groups": [ + { + "title": "Constructors", + "kind": 512, + "children": [ + 29 + ] + }, + { + "title": "Properties", + "kind": 1024, + "children": [ + 28 + ] + } + ] + }, + { + "id": 31, + "name": "My", + "kind": 32, + "kindString": "Variable", + "flags": {}, "type": { - "type": "intrinsic", - "name": "string" - } + "type": "reference", + "id": 27, + "name": "MyCtor" + }, + "extendedBy": [ + { + "type": "reference", + "id": 34, + "name": "MySubClass" + } + ] + } + ], + "groups": [ + { + "title": "Classes", + "kind": 128, + "children": [ + 34 + ] + }, + { + "title": "Interfaces", + "kind": 256, + "children": [ + 32, + 27 + ] + }, + { + "title": "Variables", + "kind": 32, + "children": [ + 31 + ] } ] } ], "groups": [ { - "title": "Interfaces", - "kind": 256, - "children": [ - 13, - 19 - ] - }, - { - "title": "Functions", - "kind": 64, + "title": "Modules", + "kind": 1, "children": [ 1, - 6, - 8 + 26 ] } ]