Fixed serialization of param names in setters from JS files (#55393)

This commit is contained in:
Mateusz Burzyński 2023-08-22 18:54:09 +02:00 committed by GitHub
parent 5439c8111d
commit 97d8c83bce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 408 additions and 34 deletions

View File

@ -7594,11 +7594,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return typeParameterToDeclarationWithConstraint(type, context, constraintNode);
}
function symbolToParameterDeclaration(parameterSymbol: Symbol, context: NodeBuilderContext, preserveModifierFlags?: boolean, privateSymbolVisitor?: (s: Symbol) => void, bundledImports?: boolean): ParameterDeclaration {
let parameterDeclaration: ParameterDeclaration | JSDocParameterTag | undefined = getDeclarationOfKind<ParameterDeclaration>(parameterSymbol, SyntaxKind.Parameter);
if (!parameterDeclaration && !isTransientSymbol(parameterSymbol)) {
parameterDeclaration = getDeclarationOfKind<JSDocParameterTag>(parameterSymbol, SyntaxKind.JSDocParameterTag);
function getEffectiveParameterDeclaration(parameterSymbol: Symbol): ParameterDeclaration | JSDocParameterTag | undefined {
const parameterDeclaration: ParameterDeclaration | JSDocParameterTag | undefined = getDeclarationOfKind<ParameterDeclaration>(parameterSymbol, SyntaxKind.Parameter);
if (parameterDeclaration) {
return parameterDeclaration;
}
if (!isTransientSymbol(parameterSymbol)) {
return getDeclarationOfKind<JSDocParameterTag>(parameterSymbol, SyntaxKind.JSDocParameterTag);
}
}
function symbolToParameterDeclaration(parameterSymbol: Symbol, context: NodeBuilderContext, preserveModifierFlags?: boolean, privateSymbolVisitor?: (s: Symbol) => void, bundledImports?: boolean): ParameterDeclaration {
const parameterDeclaration = getEffectiveParameterDeclaration(parameterSymbol);
let parameterType = getTypeOfSymbol(parameterSymbol);
if (parameterDeclaration && isRequiredInitializedParameter(parameterDeclaration)) {
@ -7609,12 +7616,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const modifiers = !(context.flags & NodeBuilderFlags.OmitParameterModifiers) && preserveModifierFlags && parameterDeclaration && canHaveModifiers(parameterDeclaration) ? map(getModifiers(parameterDeclaration), factory.cloneNode) : undefined;
const isRest = parameterDeclaration && isRestParameter(parameterDeclaration) || getCheckFlags(parameterSymbol) & CheckFlags.RestParameter;
const dotDotDotToken = isRest ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined;
const name = parameterDeclaration ? parameterDeclaration.name ?
parameterDeclaration.name.kind === SyntaxKind.Identifier ? setEmitFlags(factory.cloneNode(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) :
parameterDeclaration.name.kind === SyntaxKind.QualifiedName ? setEmitFlags(factory.cloneNode(parameterDeclaration.name.right), EmitFlags.NoAsciiEscaping) :
cloneBindingName(parameterDeclaration.name) :
symbolName(parameterSymbol) :
symbolName(parameterSymbol);
const name = parameterToParameterDeclarationName(parameterSymbol, parameterDeclaration, context);
const isOptional = parameterDeclaration && isOptionalParameter(parameterDeclaration) || getCheckFlags(parameterSymbol) & CheckFlags.OptionalParameter;
const questionToken = isOptional ? factory.createToken(SyntaxKind.QuestionToken) : undefined;
const parameterNode = factory.createParameterDeclaration(
@ -7627,6 +7629,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
);
context.approximateLength += symbolName(parameterSymbol).length + 3;
return parameterNode;
}
function parameterToParameterDeclarationName(parameterSymbol: Symbol, parameterDeclaration: ParameterDeclaration | JSDocParameterTag | undefined, context: NodeBuilderContext) {
return parameterDeclaration ? parameterDeclaration.name ?
parameterDeclaration.name.kind === SyntaxKind.Identifier ? setEmitFlags(factory.cloneNode(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) :
parameterDeclaration.name.kind === SyntaxKind.QualifiedName ? setEmitFlags(factory.cloneNode(parameterDeclaration.name.right), EmitFlags.NoAsciiEscaping) :
cloneBindingName(parameterDeclaration.name) :
symbolName(parameterSymbol) :
symbolName(parameterSymbol);
function cloneBindingName(node: BindingName): BindingName {
return elideInitializerAndSetEmitFlags(node) as BindingName;
@ -9779,6 +9790,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (p.flags & SymbolFlags.Accessor && useAccessors) {
const result: AccessorDeclaration[] = [];
if (p.flags & SymbolFlags.SetAccessor) {
const setter = p.declarations && forEach(p.declarations, d => {
if (d.kind === SyntaxKind.SetAccessor) {
return d as SetAccessorDeclaration;
}
if (isCallExpression(d) && isBindableObjectDefinePropertyCall(d)) {
return forEach(d.arguments[2].properties, propDecl => {
const id = getNameOfDeclaration(propDecl);
if (!!id && isIdentifier(id) && idText(id) === "set") {
return propDecl;
}
});
}
});
Debug.assert(setter && isFunctionLikeDeclaration(setter));
const paramSymbol: Symbol | undefined = getSignatureFromDeclaration(setter).parameters[0];
result.push(setTextRange(
factory.createSetAccessorDeclaration(
factory.createModifiersFromModifierFlags(flag),
@ -9786,7 +9814,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
[factory.createParameterDeclaration(
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
"arg",
paramSymbol ? parameterToParameterDeclarationName(paramSymbol, getEffectiveParameterDeclaration(paramSymbol), context) : "value",
/*questionToken*/ undefined,
isPrivate ? undefined : serializeTypeForDeclaration(context, getTypeOfSymbol(p), p, enclosingDeclaration, includePrivateSymbol, bundled),
)],

View File

@ -0,0 +1,26 @@
//// [tests/cases/compiler/declarationEmitClassSetAccessorParamNameInJs.ts] ////
//// [foo.js]
// https://github.com/microsoft/TypeScript/issues/55391
export class Foo {
/**
* Bar.
*
* @param {string} baz Baz.
*/
set bar(baz) {}
}
//// [foo.d.ts]
export class Foo {
/**
* Bar.
*
* @param {string} baz Baz.
*/
set bar(baz: string);
}

View File

@ -0,0 +1,18 @@
//// [tests/cases/compiler/declarationEmitClassSetAccessorParamNameInJs.ts] ////
=== foo.js ===
// https://github.com/microsoft/TypeScript/issues/55391
export class Foo {
>Foo : Symbol(Foo, Decl(foo.js, 0, 0))
/**
* Bar.
*
* @param {string} baz Baz.
*/
set bar(baz) {}
>bar : Symbol(Foo.bar, Decl(foo.js, 2, 18))
>baz : Symbol(baz, Decl(foo.js, 8, 12))
}

View File

@ -0,0 +1,18 @@
//// [tests/cases/compiler/declarationEmitClassSetAccessorParamNameInJs.ts] ////
=== foo.js ===
// https://github.com/microsoft/TypeScript/issues/55391
export class Foo {
>Foo : Foo
/**
* Bar.
*
* @param {string} baz Baz.
*/
set bar(baz) {}
>bar : string
>baz : string
}

View File

@ -0,0 +1,26 @@
//// [tests/cases/compiler/declarationEmitClassSetAccessorParamNameInJs2.ts] ////
//// [foo.js]
export class Foo {
/**
* Bar.
*
* @param {{ prop: string }} baz Baz.
*/
set bar({}) {}
}
//// [foo.d.ts]
export class Foo {
/**
* Bar.
*
* @param {{ prop: string }} baz Baz.
*/
set bar({}: {
prop: string;
});
}

View File

@ -0,0 +1,15 @@
//// [tests/cases/compiler/declarationEmitClassSetAccessorParamNameInJs2.ts] ////
=== foo.js ===
export class Foo {
>Foo : Symbol(Foo, Decl(foo.js, 0, 0))
/**
* Bar.
*
* @param {{ prop: string }} baz Baz.
*/
set bar({}) {}
>bar : Symbol(Foo.bar, Decl(foo.js, 0, 18))
}

View File

@ -0,0 +1,15 @@
//// [tests/cases/compiler/declarationEmitClassSetAccessorParamNameInJs2.ts] ////
=== foo.js ===
export class Foo {
>Foo : Foo
/**
* Bar.
*
* @param {{ prop: string }} baz Baz.
*/
set bar({}) {}
>bar : { prop: string; }
}

View File

@ -0,0 +1,26 @@
//// [tests/cases/compiler/declarationEmitClassSetAccessorParamNameInJs3.ts] ////
//// [foo.js]
export class Foo {
/**
* Bar.
*
* @param {{ prop: string | undefined }} baz Baz.
*/
set bar({ prop = 'foo' }) {}
}
//// [foo.d.ts]
export class Foo {
/**
* Bar.
*
* @param {{ prop: string | undefined }} baz Baz.
*/
set bar({ prop }: {
prop: string | undefined;
});
}

View File

@ -0,0 +1,16 @@
//// [tests/cases/compiler/declarationEmitClassSetAccessorParamNameInJs3.ts] ////
=== foo.js ===
export class Foo {
>Foo : Symbol(Foo, Decl(foo.js, 0, 0))
/**
* Bar.
*
* @param {{ prop: string | undefined }} baz Baz.
*/
set bar({ prop = 'foo' }) {}
>bar : Symbol(Foo.bar, Decl(foo.js, 0, 18))
>prop : Symbol(prop, Decl(foo.js, 6, 13))
}

View File

@ -0,0 +1,17 @@
//// [tests/cases/compiler/declarationEmitClassSetAccessorParamNameInJs3.ts] ////
=== foo.js ===
export class Foo {
>Foo : Foo
/**
* Bar.
*
* @param {{ prop: string | undefined }} baz Baz.
*/
set bar({ prop = 'foo' }) {}
>bar : { prop: string | undefined; }
>prop : string
>'foo' : "foo"
}

View File

@ -53,7 +53,7 @@ new Box(3).value = 3;
declare class Box<T> {
/** @param {T} initialValue */
constructor(initialValue: T);
set value(arg: T);
set value(value: T);
/** @type {T} */
get value(): T;
#private;

View File

@ -487,7 +487,7 @@ export class E<T, U> {
/**
* @param {string} _p
*/
static set s1(arg: string);
static set s1(_p: string);
/**
* @return {string}
*/
@ -499,7 +499,7 @@ export class E<T, U> {
/**
* @param {string} _p
*/
static set s3(arg: string);
static set s3(_p: string);
/**
* @param {T} a
* @param {U} b
@ -518,7 +518,7 @@ export class E<T, U> {
/**
* @param {U} _p
*/
set f1(arg: U);
set f1(_p: U);
/**
* @return {U}
*/
@ -530,7 +530,7 @@ export class E<T, U> {
/**
* @param {U} _p
*/
set f3(arg: U);
set f3(_p: U);
}
/**
* @template T,U

View File

@ -189,12 +189,12 @@ export class Point2D {
/**
* @param {number} x
*/
set x(arg: number);
set x(x: number);
get x(): number;
/**
* @param {number} y
*/
set y(arg: number);
set y(y: number);
get y(): number;
__proto__: typeof Vec;
}

View File

@ -48,6 +48,19 @@ Object.defineProperty(F.prototype, "x", {
*/
set(_arg) {}
});
export class G {}
Object.defineProperty(G.prototype, "x", {
/**
* @param {number[]} args
*/
set(...args) {}
});
export class H {}
Object.defineProperty(H.prototype, "x", {
set() {}
});
//// [index.js]
@ -96,6 +109,19 @@ Object.defineProperty(F.prototype, "x", {
*/
set(_arg) { }
});
export class G {
}
Object.defineProperty(G.prototype, "x", {
/**
* @param {number[]} args
*/
set(...args) { }
});
export class H {
}
Object.defineProperty(H.prototype, "x", {
set() { }
});
//// [index.d.ts]
@ -106,19 +132,25 @@ export class B {
/**
* @param {number} _arg
*/
set x(arg: number);
set x(_arg: number);
}
export class C {
set x(arg: number);
set x(_arg: number);
get x(): number;
}
export class D {
get x(): number;
}
export class E {
set x(arg: number);
set x(_arg: number);
}
export class F {
set x(arg: number);
set x(_arg: number);
get x(): number;
}
export class G {
set x(args: number);
}
export class H {
set x(value: any);
}

View File

@ -103,3 +103,41 @@ Object.defineProperty(F.prototype, "x", {
});
export class G {}
>G : Symbol(G, Decl(index.js, 46, 3))
Object.defineProperty(G.prototype, "x", {
>Object.defineProperty : Symbol(ObjectConstructor.defineProperty, Decl(lib.es5.d.ts, --, --))
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>defineProperty : Symbol(ObjectConstructor.defineProperty, Decl(lib.es5.d.ts, --, --))
>G.prototype : Symbol(G.prototype)
>G : Symbol(G, Decl(index.js, 46, 3))
>prototype : Symbol(G.prototype)
>"x" : Symbol(G.x, Decl(index.js, 48, 17))
/**
* @param {number[]} args
*/
set(...args) {}
>set : Symbol(set, Decl(index.js, 49, 41))
>args : Symbol(args, Decl(index.js, 53, 8))
});
export class H {}
>H : Symbol(H, Decl(index.js, 54, 3))
Object.defineProperty(H.prototype, "x", {
>Object.defineProperty : Symbol(ObjectConstructor.defineProperty, Decl(lib.es5.d.ts, --, --))
>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>defineProperty : Symbol(ObjectConstructor.defineProperty, Decl(lib.es5.d.ts, --, --))
>H.prototype : Symbol(H.prototype)
>H : Symbol(H, Decl(index.js, 54, 3))
>prototype : Symbol(H.prototype)
>"x" : Symbol(H.x, Decl(index.js, 56, 17))
set() {}
>set : Symbol(set, Decl(index.js, 57, 41))
});

View File

@ -114,3 +114,45 @@ Object.defineProperty(F.prototype, "x", {
});
export class G {}
>G : G
Object.defineProperty(G.prototype, "x", {
>Object.defineProperty(G.prototype, "x", { /** * @param {number[]} args */ set(...args) {}}) : G
>Object.defineProperty : <T>(o: T, p: PropertyKey, attributes: PropertyDescriptor & ThisType<any>) => T
>Object : ObjectConstructor
>defineProperty : <T>(o: T, p: PropertyKey, attributes: PropertyDescriptor & ThisType<any>) => T
>G.prototype : G
>G : typeof G
>prototype : G
>"x" : "x"
>{ /** * @param {number[]} args */ set(...args) {}} : { set(...args: number[]): void; }
/**
* @param {number[]} args
*/
set(...args) {}
>set : (...args: number[]) => void
>args : number[]
});
export class H {}
>H : H
Object.defineProperty(H.prototype, "x", {
>Object.defineProperty(H.prototype, "x", { set() {}}) : H
>Object.defineProperty : <T>(o: T, p: PropertyKey, attributes: PropertyDescriptor & ThisType<any>) => T
>Object : ObjectConstructor
>defineProperty : <T>(o: T, p: PropertyKey, attributes: PropertyDescriptor & ThisType<any>) => T
>H.prototype : H
>H : typeof H
>prototype : H
>"x" : "x"
>{ set() {}} : { set(): void; }
set() {}
>set : () => void
});

View File

@ -211,29 +211,29 @@ declare class С2 {
}
declare class С3 {
/** @param {string=} value */
set p1(arg: string | undefined);
set p1(value: string | undefined);
/** @type {string=} */
get p1(): string | undefined;
/** @param {string | undefined} value */
set p2(arg: string | undefined);
set p2(value: string | undefined);
/** @type {string | undefined} */
get p2(): string | undefined;
/** @param {?string} value */
set p3(arg: string | null);
set p3(value: string | null);
/** @type {?string} */
get p3(): string | null;
/** @param {string | null} value */
set p4(arg: string | null);
set p4(value: string | null);
/** @type {string | null} */
get p4(): string | null;
}
declare class С4 {
/** @param {string=} value */
set p1(arg: string | undefined);
set p1(value: string | undefined);
/** @param {string | undefined} value */
set p2(arg: string | undefined);
set p2(value: string | undefined);
/** @param {?string} value */
set p3(arg: string | null);
set p3(value: string | null);
/** @param {string | null} value */
set p4(arg: string | null);
set p4(value: string | null);
}

View File

@ -86,7 +86,7 @@ declare class Protected {
/** @protected */
protected m(): any;
/** @protected */
protected set p(arg: any);
protected set p(value: any);
/** @protected */
protected get p(): any;
}
@ -98,7 +98,7 @@ declare class Private {
/** @private */
private m;
/** @private */
private set p(arg);
private set p(value);
/** @private */
private get p();
}

View File

@ -25,7 +25,7 @@ export class TextElement extends HTMLElement {
//// [thisPropertyAssignmentInherited.d.ts]
export class Element {
set textContent(arg: string);
set textContent(x: string);
/**
* @returns {String}
*/
@ -35,7 +35,7 @@ export class Element {
export class HTMLElement extends Element {
}
export class TextElement extends HTMLElement {
set innerHTML(arg: string);
set innerHTML(html: string);
get innerHTML(): string;
toString(): void;
}

View File

@ -0,0 +1,16 @@
// @declaration: true
// @emitDeclarationOnly: true
// @allowJs: true
// @filename: foo.js
// https://github.com/microsoft/TypeScript/issues/55391
export class Foo {
/**
* Bar.
*
* @param {string} baz Baz.
*/
set bar(baz) {}
}

View File

@ -0,0 +1,14 @@
// @declaration: true
// @emitDeclarationOnly: true
// @allowJs: true
// @filename: foo.js
export class Foo {
/**
* Bar.
*
* @param {{ prop: string }} baz Baz.
*/
set bar({}) {}
}

View File

@ -0,0 +1,14 @@
// @declaration: true
// @emitDeclarationOnly: true
// @allowJs: true
// @filename: foo.js
export class Foo {
/**
* Bar.
*
* @param {{ prop: string | undefined }} baz Baz.
*/
set bar({ prop = 'foo' }) {}
}

View File

@ -51,3 +51,16 @@ Object.defineProperty(F.prototype, "x", {
*/
set(_arg) {}
});
export class G {}
Object.defineProperty(G.prototype, "x", {
/**
* @param {number[]} args
*/
set(...args) {}
});
export class H {}
Object.defineProperty(H.prototype, "x", {
set() {}
});