Skip to content

Commit a6da8d9

Browse files
Copilotweswigham
andauthored
Create serializable synthetic call-signature declarations
Co-authored-by: weswigham <[email protected]>
1 parent 869dce4 commit a6da8d9

5 files changed

Lines changed: 61 additions & 6 deletions

File tree

‎packages/typescript/test/async/api.test.ts‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4967,7 +4967,17 @@ describe("Checker - getContextualType", { concurrency }, () => {
49674967
const signatures = await project.checker.getSignaturesOfType(type, SignatureKind.Call);
49684968
assert.equal(signatures.length, 1);
49694969
assert.deepEqual((await signatures[0].getParameters()).map(parameter => parameter.name), ["target", "context"]);
4970-
assert.equal(signatures[0].declaration, undefined);
4970+
const declarationHandle = signatures[0].declaration;
4971+
assert.ok(declarationHandle);
4972+
assert.equal(declarationHandle.kind, SyntaxKind.FunctionType);
4973+
const declaration = await declarationHandle.resolve();
4974+
assert.ok(declaration);
4975+
assert.ok(isSignatureDeclaration(declaration));
4976+
assert.equal(declaration.kind, SyntaxKind.FunctionType);
4977+
const declarationSignature = await project.checker.getSignatureFromDeclaration(declaration);
4978+
assert.ok(declarationSignature);
4979+
assert.strictEqual(declarationSignature.declaration, declarationHandle);
4980+
assert.deepEqual(await project.program.getSourceFileNames(), ["/src/main.ts"]);
49714981
});
49724982

49734983
test("contextual type from function parameter", async () => {

‎packages/typescript/test/sync/api.test.ts‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4792,7 +4792,17 @@ describe("Checker - getContextualType", { concurrency }, () => {
47924792
const signatures = project.checker.getSignaturesOfType(type, SignatureKind.Call);
47934793
assert.equal(signatures.length, 1);
47944794
assert.deepEqual((signatures[0].getParameters()).map(parameter => parameter.name), ["target", "context"]);
4795-
assert.equal(signatures[0].declaration, undefined);
4795+
const declarationHandle = signatures[0].declaration;
4796+
assert.ok(declarationHandle);
4797+
assert.equal(declarationHandle.kind, SyntaxKind.FunctionType);
4798+
const declaration = declarationHandle.resolve();
4799+
assert.ok(declaration);
4800+
assert.ok(isSignatureDeclaration(declaration));
4801+
assert.equal(declaration.kind, SyntaxKind.FunctionType);
4802+
const declarationSignature = project.checker.getSignatureFromDeclaration(declaration);
4803+
assert.ok(declarationSignature);
4804+
assert.strictEqual(declarationSignature.declaration, declarationHandle);
4805+
assert.deepEqual(project.program.getSourceFileNames(), ["/src/main.ts"]);
47964806
});
47974807

47984808
test("contextual type from function parameter", () => {

‎tsc/internal/api/session.go‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -501,8 +501,8 @@ func (sd *snapshotData) newSignatureResponse(projectID project.Handle, sig *chec
501501
Flags: uint32(sig.Flags()),
502502
}
503503

504-
if declaration := sig.Declaration(); declaration != nil && ast.GetSourceFileOfNode(declaration) != nil {
505-
resp.Declaration = sd.nodeHandleFrom(declaration)
504+
if sig.Declaration() != nil {
505+
resp.Declaration = sd.nodeHandleFrom(sig.Declaration())
506506
}
507507

508508
if len(sig.TypeParameters()) > 0 {
@@ -2362,7 +2362,11 @@ func (s *Session) handleGetSourceFile(ctx context.Context, params *GetSourceFile
23622362
return nil, err
23632363
}
23642364

2365-
return s.encodeSourceFileResponse(program.GetSourceFile(params.File.ToFileName(program.BaseDirectory())))
2365+
fileName := params.File.ToFileName(program.BaseDirectory())
2366+
if fileName == checker.SyntheticSignatureFileName {
2367+
return s.encodeSourceFileResponse(checker.GetSyntheticSignatureSourceFile())
2368+
}
2369+
return s.encodeSourceFileResponse(program.GetSourceFile(fileName))
23662370
}
23672371

23682372
// handleGetConfigFileNames returns tsconfig file names associated with the project's command line.
@@ -5029,6 +5033,12 @@ func (sd *snapshotData) resolveNodeHandle(program *compiler.Program, handle Node
50295033
return nil, fmt.Errorf("%w: invalid node handle %q", ErrClientError, handle)
50305034
}
50315035
sourceFile := program.GetSourceFileByNodeID(ast.NodeId(nodeID))
5036+
if sourceFile == nil {
5037+
syntheticFile := checker.GetSyntheticSignatureSourceFile()
5038+
if sourceFileNodeID(syntheticFile) == nodeID {
5039+
sourceFile = syntheticFile
5040+
}
5041+
}
50325042
if sourceFile == nil {
50335043
return nil, fmt.Errorf("%w: node handle %q could not be resolved (file may not be loaded or handle may be stale)", ErrClientError, handle)
50345044
}

‎tsc/internal/checker/checker.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31161,7 +31161,7 @@ func (c *Checker) newSetterFunctionType(t *Type) *Type {
3116131161

3116231162
// Creates a synthetic `Signature` corresponding to a call signature.
3116331163
func (c *Checker) newCallSignature(typeParameters []*Type, thisParameter *ast.Symbol, parameters []*ast.Symbol, returnType *Type) *Signature {
31164-
decl := c.factory.NewFunctionTypeNode(nil, nil, c.factory.NewKeywordTypeNode(ast.KindAnyKeyword))
31164+
decl := GetSyntheticSignatureSourceFile().Statements.Nodes[0].Type()
3116531165
return c.newSignature(SignatureFlagsNone, decl, typeParameters, thisParameter, parameters, returnType, nil, len(parameters))
3116631166
}
3116731167

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package checker
2+
3+
import (
4+
"sync"
5+
6+
"github.com/microsoft/TypeScript/tsc/internal/ast"
7+
"github.com/microsoft/TypeScript/tsc/internal/core"
8+
"github.com/microsoft/TypeScript/tsc/internal/parser"
9+
"github.com/microsoft/TypeScript/tsc/internal/tspath"
10+
)
11+
12+
const SyntheticSignatureFileName tspath.RootedFilePath = "tsgo://synthetic/signatures.d.ts"
13+
14+
var syntheticSignatureSourceFile = sync.OnceValue(func() *ast.SourceFile {
15+
return parser.ParseSourceFile(ast.SourceFileParseOptions{
16+
FileName: SyntheticSignatureFileName,
17+
PathKey: tspath.CaseSensitive.PathKey(tspath.RootedPath(SyntheticSignatureFileName)),
18+
}, "type SyntheticSignature = () => any;", core.ScriptKindTS)
19+
})
20+
21+
// GetSyntheticSignatureSourceFile provides an immutable, shared AST for synthetic
22+
// call-signature declarations. It is not an input file of any program.
23+
func GetSyntheticSignatureSourceFile() *ast.SourceFile {
24+
return syntheticSignatureSourceFile()
25+
}

0 commit comments

Comments
 (0)