diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 246f3d15050..e3989b6fb2c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6354,7 +6354,8 @@ namespace ts { if ((symbol.flags & (SymbolFlags.ValueModule | SymbolFlags.NamespaceModule) && (!isConstMergedWithNS || isTypeOnlyNamespace(symbol))) || isConstMergedWithNSPrintableAsSignatureMerge) { serializeModule(symbol, symbolName, modifierFlags); } - if (symbol.flags & SymbolFlags.Interface) { + // The class meaning serialization should handle serializing all interface members + if (symbol.flags & SymbolFlags.Interface && !(symbol.flags & SymbolFlags.Class)) { serializeInterface(symbol, symbolName, modifierFlags); } if (symbol.flags & SymbolFlags.Alias) { @@ -7040,7 +7041,7 @@ namespace ts { } // This is an else/if as accessors and properties can't merge in TS, but might in JS // If this happens, we assume the accessor takes priority, as it imposes more constraints - else if (p.flags & (SymbolFlags.Property | SymbolFlags.Variable)) { + else if (p.flags & (SymbolFlags.Property | SymbolFlags.Variable | SymbolFlags.Accessor)) { return setTextRange(createProperty( /*decorators*/ undefined, factory.createModifiersFromModifierFlags((isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | flag), diff --git a/tests/baselines/reference/jsDeclarationsClassAccessor.js b/tests/baselines/reference/jsDeclarationsClassAccessor.js new file mode 100644 index 00000000000..b8c9ded0b50 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsClassAccessor.js @@ -0,0 +1,89 @@ +//// [tests/cases/conformance/jsdoc/declarations/jsDeclarationsClassAccessor.ts] //// + +//// [supplement.d.ts] +export { }; +declare module "./argument.js" { + interface Argument { + idlType: any; + default: null; + } +} +//// [base.js] +export class Base { + constructor() { } + + toJSON() { + const json = { type: undefined, name: undefined, inheritance: undefined }; + return json; + } +} +//// [argument.js] +import { Base } from "./base.js"; +export class Argument extends Base { + /** + * @param {*} tokeniser + */ + static parse(tokeniser) { + return; + } + + get type() { + return "argument"; + } + + /** + * @param {*} defs + */ + *validate(defs) { } +} + +//// [base.js] +export class Base { + constructor() { } + toJSON() { + const json = { type: undefined, name: undefined, inheritance: undefined }; + return json; + } +} +//// [argument.js] +import { Base } from "./base.js"; +export class Argument extends Base { + /** + * @param {*} tokeniser + */ + static parse(tokeniser) { + return; + } + get type() { + return "argument"; + } + /** + * @param {*} defs + */ + *validate(defs) { } +} + + +//// [base.d.ts] +export class Base { + toJSON(): { + type: any; + name: any; + inheritance: any; + }; +} +//// [argument.d.ts] +export class Argument extends Base { + /** + * @param {*} tokeniser + */ + static parse(tokeniser: any): void; + get type(): string; + /** + * @param {*} defs + */ + validate(defs: any): Generator; + idlType: any; + default: null; +} +import { Base } from "./base.js"; diff --git a/tests/baselines/reference/jsDeclarationsClassAccessor.symbols b/tests/baselines/reference/jsDeclarationsClassAccessor.symbols new file mode 100644 index 00000000000..75c7b1d6533 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsClassAccessor.symbols @@ -0,0 +1,68 @@ +=== tests/cases/conformance/jsdoc/declarations/supplement.d.ts === +export { }; +declare module "./argument.js" { +>"./argument.js" : Symbol("tests/cases/conformance/jsdoc/declarations/argument", Decl(argument.js, 0, 0), Decl(supplement.d.ts, 0, 11)) + + interface Argument { +>Argument : Symbol(Argument, Decl(argument.js, 0, 33), Decl(supplement.d.ts, 1, 32)) + + idlType: any; +>idlType : Symbol(Argument.idlType, Decl(supplement.d.ts, 2, 24)) + + default: null; +>default : Symbol(Argument.default, Decl(supplement.d.ts, 3, 21)) + } +} +=== tests/cases/conformance/jsdoc/declarations/base.js === +export class Base { +>Base : Symbol(Base, Decl(base.js, 0, 0)) + + constructor() { } + + toJSON() { +>toJSON : Symbol(Base.toJSON, Decl(base.js, 1, 21)) + + const json = { type: undefined, name: undefined, inheritance: undefined }; +>json : Symbol(json, Decl(base.js, 4, 13)) +>type : Symbol(type, Decl(base.js, 4, 22)) +>undefined : Symbol(undefined) +>name : Symbol(name, Decl(base.js, 4, 39)) +>undefined : Symbol(undefined) +>inheritance : Symbol(inheritance, Decl(base.js, 4, 56)) +>undefined : Symbol(undefined) + + return json; +>json : Symbol(json, Decl(base.js, 4, 13)) + } +} +=== tests/cases/conformance/jsdoc/declarations/argument.js === +import { Base } from "./base.js"; +>Base : Symbol(Base, Decl(argument.js, 0, 8)) + +export class Argument extends Base { +>Argument : Symbol(Argument, Decl(argument.js, 0, 33), Decl(supplement.d.ts, 1, 32)) +>Base : Symbol(Base, Decl(argument.js, 0, 8)) + + /** + * @param {*} tokeniser + */ + static parse(tokeniser) { +>parse : Symbol(Argument.parse, Decl(argument.js, 1, 36)) +>tokeniser : Symbol(tokeniser, Decl(argument.js, 5, 17)) + + return; + } + + get type() { +>type : Symbol(Argument.type, Decl(argument.js, 7, 5)) + + return "argument"; + } + + /** + * @param {*} defs + */ + *validate(defs) { } +>validate : Symbol(Argument.validate, Decl(argument.js, 11, 5)) +>defs : Symbol(defs, Decl(argument.js, 16, 14)) +} diff --git a/tests/baselines/reference/jsDeclarationsClassAccessor.types b/tests/baselines/reference/jsDeclarationsClassAccessor.types new file mode 100644 index 00000000000..45e29369f18 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsClassAccessor.types @@ -0,0 +1,69 @@ +=== tests/cases/conformance/jsdoc/declarations/supplement.d.ts === +export { }; +declare module "./argument.js" { +>"./argument.js" : typeof import("tests/cases/conformance/jsdoc/declarations/argument") + + interface Argument { + idlType: any; +>idlType : any + + default: null; +>default : null +>null : null + } +} +=== tests/cases/conformance/jsdoc/declarations/base.js === +export class Base { +>Base : Base + + constructor() { } + + toJSON() { +>toJSON : () => { type: any; name: any; inheritance: any; } + + const json = { type: undefined, name: undefined, inheritance: undefined }; +>json : { type: any; name: any; inheritance: any; } +>{ type: undefined, name: undefined, inheritance: undefined } : { type: undefined; name: undefined; inheritance: undefined; } +>type : undefined +>undefined : undefined +>name : undefined +>undefined : undefined +>inheritance : undefined +>undefined : undefined + + return json; +>json : { type: any; name: any; inheritance: any; } + } +} +=== tests/cases/conformance/jsdoc/declarations/argument.js === +import { Base } from "./base.js"; +>Base : typeof Base + +export class Argument extends Base { +>Argument : Argument +>Base : Base + + /** + * @param {*} tokeniser + */ + static parse(tokeniser) { +>parse : (tokeniser: any) => void +>tokeniser : any + + return; + } + + get type() { +>type : string + + return "argument"; +>"argument" : "argument" + } + + /** + * @param {*} defs + */ + *validate(defs) { } +>validate : (defs: any) => Generator +>defs : any +} diff --git a/tests/cases/conformance/jsdoc/declarations/jsDeclarationsClassAccessor.ts b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsClassAccessor.ts new file mode 100644 index 00000000000..2e5717ed05b --- /dev/null +++ b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsClassAccessor.ts @@ -0,0 +1,41 @@ +// @allowJs: true +// @checkJs: true +// @target: es2019 +// @outDir: ./out +// @declaration: true +// @filename: supplement.d.ts +export { }; +declare module "./argument.js" { + interface Argument { + idlType: any; + default: null; + } +} +// @filename: base.js +export class Base { + constructor() { } + + toJSON() { + const json = { type: undefined, name: undefined, inheritance: undefined }; + return json; + } +} +// @filename: argument.js +import { Base } from "./base.js"; +export class Argument extends Base { + /** + * @param {*} tokeniser + */ + static parse(tokeniser) { + return; + } + + get type() { + return "argument"; + } + + /** + * @param {*} defs + */ + *validate(defs) { } +} \ No newline at end of file