Add regression test for decorator contextual signature panic

Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]andRyanCavanaugh authored and GitHub committed 2026-10-21 17:32:27 +00:00
1 parent ff5ebb9c3a
commit dc4fa253ef
2 files changed
+58

No files matched your search

@@ -10,6 +10,7 @@ import {
InternalSymbolName,
isCallExpression,
isClassDeclaration,
isDecorator,
isExpressionStatement,
isFunctionDeclaration,
isIdentifier,
@@ -4941,6 +4942,34 @@ describe("Checker - getBaseTypeOfLiteralType", { concurrency }, () => {
});
describe("Checker - getContextualType", { concurrency }, () => {
test("signatures of a decorator contextual type", async () => {
await using api = spawnAPI({
"/tsconfig.json": JSON.stringify({ compilerOptions: { noLib: true } }),
"/src/main.ts": "class C { @((target, context) => target) get value(): number { return 1; } }",
});
const snapshot = await api.createSnapshot({ openProjects: ["/tsconfig.json"] });
const project = snapshot.getConfiguredProject("/tsconfig.json")!;
const sourceFile = await project.program.getSourceFile("/src/main.ts");
assert.ok(sourceFile);
let expression: Expression | undefined;
sourceFile.forEachChild(function visit(node) {
if (isDecorator(node)) {
expression = node.expression;
}
node.forEachChild(visit);
});
assert.ok(expression);
const type = await project.checker.getContextualType(expression);
assert.ok(type);
const signatures = await project.checker.getSignaturesOfType(type, SignatureKind.Call);
assert.equal(signatures.length, 1);
assert.deepEqual((await signatures[0].getParameters()).map(parameter => parameter.name), ["target", "context"]);
assert.equal(signatures[0].declaration, undefined);
});
test("contextual type from function parameter", async () => {
await using api = spawnAPI({
"/tsconfig.json": JSON.stringify({ compilerOptions: { strict: true } }),
+29
View File
@@ -18,6 +18,7 @@ import {
InternalSymbolName,
isCallExpression,
isClassDeclaration,
isDecorator,
isExpressionStatement,
isFunctionDeclaration,
isIdentifier,
@@ -4766,6 +4767,34 @@ describe("Checker - getBaseTypeOfLiteralType", { concurrency }, () => {
});
describe("Checker - getContextualType", { concurrency }, () => {
test("signatures of a decorator contextual type", () => {
using api = spawnAPI({
"/tsconfig.json": JSON.stringify({ compilerOptions: { noLib: true } }),
"/src/main.ts": "class C { @((target, context) => target) get value(): number { return 1; } }",
});
const snapshot = api.createSnapshot({ openProjects: ["/tsconfig.json"] });
const project = snapshot.getConfiguredProject("/tsconfig.json")!;
const sourceFile = project.program.getSourceFile("/src/main.ts");
assert.ok(sourceFile);
let expression: Expression | undefined;
sourceFile.forEachChild(function visit(node) {
if (isDecorator(node)) {
expression = node.expression;
}
node.forEachChild(visit);
});
assert.ok(expression);
const type = project.checker.getContextualType(expression);
assert.ok(type);
const signatures = project.checker.getSignaturesOfType(type, SignatureKind.Call);
assert.equal(signatures.length, 1);
assert.deepEqual((signatures[0].getParameters()).map(parameter => parameter.name), ["target", "context"]);
assert.equal(signatures[0].declaration, undefined);
});
test("contextual type from function parameter", () => {
using api = spawnAPI({
"/tsconfig.json": JSON.stringify({ compilerOptions: { strict: true } }),