From 732fe0dc034c834aaf495aee04ec286786a54275 Mon Sep 17 00:00:00 2001 From: charburgx Date: Sun, 6 Nov 2022 17:45:51 -0600 Subject: [PATCH] fix(api): error getting signature type arguments closes #14 --- packages/api/src/typescript.ts | 6 ++++ packages/api/src/util.ts | 57 +++++++++++++--------------------- tests/other/map.spec.ts | 27 +++++++++++++--- tests/other/map2.ts | 4 +++ 4 files changed, 55 insertions(+), 39 deletions(-) create mode 100644 tests/other/map2.ts diff --git a/packages/api/src/typescript.ts b/packages/api/src/typescript.ts index 0d18642..7a30984 100644 --- a/packages/api/src/typescript.ts +++ b/packages/api/src/typescript.ts @@ -6,6 +6,11 @@ import { TypescriptContext } from "./types" */ export type SymbolName = ts.__String +/** + * @internal + */ +type TypeMapper = unknown + /** * @internal */ @@ -112,6 +117,7 @@ export type SignatureInternal = ts.Signature & { minArgumentCount: number resolvedMinArgumentCount?: number target?: SignatureInternal + mapper: TypeMapper } /** * @internal diff --git a/packages/api/src/util.ts b/packages/api/src/util.ts index 0985660..801430a 100644 --- a/packages/api/src/util.ts +++ b/packages/api/src/util.ts @@ -1,3 +1,4 @@ +import assert = require("assert") import * as ts from "typescript" import { wrapSafe, @@ -437,34 +438,12 @@ export function isObjectReference( return !!(getObjectFlags(ctx, type) & ts.ObjectFlags.Reference) } -type Mutable = { -readonly [k in keyof T]: T[k] } - export function getTypeFromTypeNode( - { ts, typeChecker }: TypescriptContext, + { typeChecker }: TypescriptContext, node: ts.TypeNode, enclosingDeclaration?: ts.Node ) { - if (!(node.flags & ts.NodeFlags.Synthesized)) { - return typeChecker.getTypeFromTypeNode(node) - } else { - node = cloneClassInstance(node) - - if (ts.isTypeReferenceNode(node)) { - if (node.typeName && enclosingDeclaration) { - ;(node as Mutable).typeName = - cloneClassInstance(node.typeName) - ;(node.typeName as Mutable).parent ??= - enclosingDeclaration - } - } - - ;(node as Mutable).flags &= ~ts.NodeFlags.Synthesized - ;(node as Mutable).parent ??= { - kind: ts.SyntaxKind.VariableStatement, - } as ts.Node - - return typeChecker.getTypeFromTypeNode(node) - } + return typeChecker.getTypeFromTypeNode(node) } export function getTypeArguments( @@ -723,19 +702,27 @@ export function getSignatureTypeArguments( ctx: TypescriptContext, signature: ts.Signature, enclosingDeclaration?: ts.Node -) { +): readonly ts.Type[] { const { typeChecker, ts } = ctx - return typeChecker - .signatureToSignatureDeclaration( - signature, - ts.SyntaxKind.CallSignature, - enclosingDeclaration, - ts.NodeBuilderFlags.WriteTypeArgumentsOfSignature - ) - ?.typeArguments?.map((t) => - getTypeFromTypeNode(ctx, t, enclosingDeclaration) - ) // TODO: error here... + const target = (signature as SignatureInternal).target + + if (!target) { + return [] + } + + // workaround to force instantiation of signature type arguments + return typeChecker.getTypeArguments({ + node: { + kind: ts.SyntaxKind.TypeReference, + }, + target: { + outerTypeParameters: target.typeParameters ?? [], + localTypeParameters: [], + }, + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + mapper: (signature as SignatureInternal).mapper, + } as unknown as ts.TypeReference) } export function getDescendantAtPosition( diff --git a/tests/other/map.spec.ts b/tests/other/map.spec.ts index e72a998..43db262 100644 --- a/tests/other/map.spec.ts +++ b/tests/other/map.spec.ts @@ -9,10 +9,7 @@ describe("map.ts", () => { it("doesn't error when retrieving outside", () => { const ctx = createTsContext(fileName) - const pos = { - line: 5, - character: 0, - } + const pos = { line: 5, character: 0 } getTypeInfoAtRange( ctx, @@ -27,3 +24,25 @@ describe("map.ts", () => { ) }) }) + +const fileName2 = path.join(__dirname, "map2.ts") + +describe("map2.ts", () => { + it("deosn't error when retrieving outside", () => { + const ctx = createTsContext(fileName2) + + const pos = { line: 3, character: 0 } + + getTypeInfoAtRange( + ctx, + { + fileName: fileName2, + range: { + start: pos, + end: pos, + }, + }, + apiConfig + ) + }) +}) diff --git a/tests/other/map2.ts b/tests/other/map2.ts new file mode 100644 index 0000000..445b98d --- /dev/null +++ b/tests/other/map2.ts @@ -0,0 +1,4 @@ +import * as ts from "typescript" +;([] as unknown as ts.NodeArray).map( + (x) => x as unknown as ts.Type +)