Skip to content

Commit

Permalink
feat: #541 - Add TypeChecker#getResolvedSignature()
Browse files Browse the repository at this point in the history
  • Loading branch information
schiller-manuel authored and dsherret committed Feb 21, 2019
1 parent d2bc498 commit cf5104d
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 2 deletions.
8 changes: 8 additions & 0 deletions docs/navigation/type-checker.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,11 @@ const tsTypeChecker = typeChecker.compilerObject;
### Use

Generally you won't need to use the type checker because most of the functionality is exposed as methods on other objects.

### Signature Resolution

Get the resolved signature of a call-like expression node (ex. call expression):

```ts
const resolvedSignature = typeChecker.getResolvedSignature(callLikeExpression);
```
21 changes: 21 additions & 0 deletions src/compiler/tools/TypeChecker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { Node } from "../ast/common";
import { EnumMember } from "../ast/enum";
import { Expression } from "../ast/expression";
import { ExportSpecifier } from "../ast/module";
import { CallLikeExpression } from "../ast/aliases";
import * as errors from "../../errors";

/**
* Wrapper around the TypeChecker.
Expand Down Expand Up @@ -179,6 +181,25 @@ export class TypeChecker {
return symbol == null ? undefined : this._context.compilerFactory.getSymbol(symbol);
}

/**
* Gets the resolved signature from a node or returns undefined if the signature can't be resolved.
* @param node - Node to get the signature from.
*/
getResolvedSignature(node: CallLikeExpression) {
const resolvedSignature = this.compilerObject.getResolvedSignature(node.compilerNode);
if (!resolvedSignature || !resolvedSignature.declaration)
return undefined;
return this._context.compilerFactory.getSignature(resolvedSignature);
}

/**
* Gets the resolved signature from a node or throws if the signature cannot be resolved.
* @param node - Node to get the signature from.
*/
getResolvedSignatureOrThrow(node: CallLikeExpression) {
return errors.throwIfNullOrUndefined(this.getResolvedSignature(node), "Signature could not be resolved.");
}

/**
* Gets the base type of a literal type.
*
Expand Down
45 changes: 43 additions & 2 deletions src/tests/compiler/tools/typeCheckerTests.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { expect } from "chai";
import { TypeChecker } from "../../../compiler";
import { getInfoFromText } from "../testHelpers";
import { CallExpression, TypeChecker, NamedNode } from "../../../compiler";
import { InvalidOperationError } from "../../../errors";
import { SyntaxKind } from "../../../typescript";
import { getInfoFromText, getInfoFromTextWithDescendant } from "../testHelpers";

describe(nameof(TypeChecker), () => {
describe(nameof<TypeChecker>(p => p.getAmbientModules), () => {
Expand Down Expand Up @@ -29,4 +31,43 @@ describe(nameof(TypeChecker), () => {
expect(project.getTypeChecker().getAmbientModules().length).to.equal(0);
});
});

describe(nameof<TypeChecker>(p => p.getResolvedSignature), () => {
function doTest(text: string, declarationName: string | undefined) {
const { descendant, project } = getInfoFromTextWithDescendant<CallExpression>(text, SyntaxKind.CallExpression);
const result = project.getTypeChecker().getResolvedSignature(descendant);
if (declarationName == null)
expect(result).to.be.undefined;
else
expect((result!.getDeclaration() as NamedNode).getName()).to.equal(declarationName);
}

it("should not resolve unknown signature", () => {
doTest("foo();", undefined);
});

it("should resolve signature in same file", () => {
doTest("function foo(){}; foo();", "foo");
});
});

describe(nameof<TypeChecker>(p => p.getResolvedSignatureOrThrow), () => {
function doTest(text: string, declarationName: string | undefined) {
const { descendant, project } = getInfoFromTextWithDescendant<CallExpression>(text, SyntaxKind.CallExpression);
if (declarationName == null)
expect(() => project.getTypeChecker().getResolvedSignatureOrThrow(descendant)).to.throw();
else {
const result = project.getTypeChecker().getResolvedSignatureOrThrow(descendant);
expect((result.getDeclaration() as NamedNode).getName()).to.equal(declarationName);
}
}

it("should not resolve unknown signature", () => {
doTest("foo();", undefined);
});

it("should resolve signature in same file", () => {
doTest("function foo(){}; foo();", "foo");
});
});
});

0 comments on commit cf5104d

Please sign in to comment.