@@ -4916,8 +4916,8 @@ namespace ts {
49164916 }
49174917
49184918 function symbolTableToDeclarationStatements(symbolTable: SymbolTable, context: NodeBuilderContext, bundled?: boolean): Statement[] {
4919- const serializePropertySymbolForClass = makeSerializePropertySymbol<ClassElement>(createProperty, SyntaxKind.MethodDeclaration);
4920- const serializePropertySymbolForInterfaceWorker = makeSerializePropertySymbol<TypeElement>((_decorators, mods, name, question, type, initializer) => createPropertySignature(mods, name, question, type, initializer), SyntaxKind.MethodSignature);
4919+ const serializePropertySymbolForClass = makeSerializePropertySymbol<ClassElement>(createProperty, SyntaxKind.MethodDeclaration, /*useAcessors*/ true );
4920+ const serializePropertySymbolForInterfaceWorker = makeSerializePropertySymbol<TypeElement>((_decorators, mods, name, question, type, initializer) => createPropertySignature(mods, name, question, type, initializer), SyntaxKind.MethodSignature, /*useAcessors*/ false );
49214921
49224922 // TODO: Use `setOriginalNode` on original declaration names where possible so these declarations see some kind of
49234923 // declaration mapping
@@ -5734,7 +5734,23 @@ namespace ts {
57345734 questionOrExclamationToken: QuestionToken | undefined,
57355735 type: TypeNode | undefined,
57365736 initializer: Expression | undefined
5737- ) => T, methodKind: SyntaxKind): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | T[]) {
5737+ ) => T, methodKind: SyntaxKind, useAccessors: true): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | AccessorDeclaration | (T | AccessorDeclaration)[]);
5738+ function makeSerializePropertySymbol<T extends Node>(createProperty: (
5739+ decorators: readonly Decorator[] | undefined,
5740+ modifiers: readonly Modifier[] | undefined,
5741+ name: string | PropertyName,
5742+ questionOrExclamationToken: QuestionToken | undefined,
5743+ type: TypeNode | undefined,
5744+ initializer: Expression | undefined
5745+ ) => T, methodKind: SyntaxKind, useAccessors: false): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | T[]);
5746+ function makeSerializePropertySymbol<T extends Node>(createProperty: (
5747+ decorators: readonly Decorator[] | undefined,
5748+ modifiers: readonly Modifier[] | undefined,
5749+ name: string | PropertyName,
5750+ questionOrExclamationToken: QuestionToken | undefined,
5751+ type: TypeNode | undefined,
5752+ initializer: Expression | undefined
5753+ ) => T, methodKind: SyntaxKind, useAccessors: boolean): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | AccessorDeclaration | (T | AccessorDeclaration)[]) {
57385754 return function serializePropertySymbol(p: Symbol, isStatic: boolean, baseType: Type | undefined) {
57395755 if (isStatic && (p.flags & (SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias))) {
57405756 // Only value-only-meaning symbols can be correctly encoded as class statics, type/namespace/alias meaning symbols
@@ -5750,7 +5766,40 @@ namespace ts {
57505766 const staticFlag = isStatic ? ModifierFlags.Static : 0;
57515767 const rawName = unescapeLeadingUnderscores(p.escapedName);
57525768 const name = getPropertyNameNodeForSymbolFromNameType(p, context) || createIdentifier(rawName);
5753- if (p.flags & (SymbolFlags.Property | SymbolFlags.Accessor | SymbolFlags.Variable)) {
5769+ const firstPropertyLikeDecl = find(p.declarations, or(isPropertyDeclaration, isAccessor, isVariableDeclaration, isPropertySignature, isBinaryExpression, isPropertyAccessExpression));
5770+ if (p.flags & SymbolFlags.Accessor && useAccessors) {
5771+ const result: AccessorDeclaration[] = [];
5772+ if (p.flags & SymbolFlags.SetAccessor) {
5773+ result.push(setTextRange(createSetAccessor(
5774+ /*decorators*/ undefined,
5775+ createModifiersFromModifierFlags(staticFlag),
5776+ name,
5777+ [createParameter(
5778+ /*decorators*/ undefined,
5779+ /*modifiers*/ undefined,
5780+ /*dotDotDotToken*/ undefined,
5781+ "arg",
5782+ /*questionToken*/ undefined,
5783+ serializeTypeForDeclaration(getTypeOfSymbol(p), p)
5784+ )],
5785+ /*body*/ undefined
5786+ ), find(p.declarations, isSetAccessor) || firstPropertyLikeDecl));
5787+ }
5788+ if (p.flags & SymbolFlags.GetAccessor) {
5789+ result.push(setTextRange(createGetAccessor(
5790+ /*decorators*/ undefined,
5791+ createModifiersFromModifierFlags(staticFlag),
5792+ name,
5793+ [],
5794+ serializeTypeForDeclaration(getTypeOfSymbol(p), p),
5795+ /*body*/ undefined
5796+ ), find(p.declarations, isGetAccessor) || firstPropertyLikeDecl));
5797+ }
5798+ return result;
5799+ }
5800+ // This is an else/if as accessors and properties can't merge in TS, but might in JS
5801+ // If this happens, we assume the accessor takes priority, as it imposes more constraints
5802+ else if (p.flags & (SymbolFlags.Property | SymbolFlags.Variable)) {
57545803 return setTextRange(createProperty(
57555804 /*decorators*/ undefined,
57565805 createModifiersFromModifierFlags((isReadonlySymbol(p) ? ModifierFlags.Readonly : 0) | staticFlag),
@@ -5760,7 +5809,7 @@ namespace ts {
57605809 // TODO: https://github.com/microsoft/TypeScript/pull/32372#discussion_r328386357
57615810 // interface members can't have initializers, however class members _can_
57625811 /*initializer*/ undefined
5763- ), filter (p.declarations, d => isPropertyDeclaration(d) || isAccessor(d) || isVariableDeclaration(d) || isPropertySignature(d ) || isBinaryExpression(d) || isPropertyAccessExpression(d))[0] );
5812+ ), find (p.declarations, or(isPropertyDeclaration, isVariableDeclaration) ) || firstPropertyLikeDecl );
57645813 }
57655814 if (p.flags & (SymbolFlags.Method | SymbolFlags.Function)) {
57665815 const type = getTypeOfSymbol(p);
@@ -7340,7 +7389,7 @@ namespace ts {
73407389 }
73417390 }
73427391 else {
7343- Debug.assert(!!getter, "there must existed getter as we are current checking either setter or getter in this function");
7392+ Debug.assert(!!getter, "there must exist a getter as we are current checking either setter or getter in this function");
73447393 errorOrSuggestion(noImplicitAny, getter!, Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, symbolToString(symbol));
73457394 }
73467395 return anyType;
0 commit comments