-
Notifications
You must be signed in to change notification settings - Fork 238
Expand file tree
/
Copy pathExpressionWithTypeArgumentsNodeParser.ts
More file actions
52 lines (47 loc) · 2.28 KB
/
Copy pathExpressionWithTypeArgumentsNodeParser.ts
File metadata and controls
52 lines (47 loc) · 2.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import ts from "typescript";
import type { NodeParser } from "../NodeParser.js";
import { Context } from "../NodeParser.js";
import type { SubNodeParser } from "../SubNodeParser.js";
import type { BaseType } from "../Type/BaseType.js";
import { LogicError } from "../Error/Errors.js";
export class ExpressionWithTypeArgumentsNodeParser implements SubNodeParser {
public constructor(
protected typeChecker: ts.TypeChecker,
protected childNodeParser: NodeParser,
) {}
public supportsNode(node: ts.ExpressionWithTypeArguments): boolean {
return node.kind === ts.SyntaxKind.ExpressionWithTypeArguments;
}
public createType(node: ts.ExpressionWithTypeArguments, context: Context): BaseType {
const typeSymbol = this.typeChecker.getSymbolAtLocation(node.expression);
if (!typeSymbol) {
throw new LogicError(node, `Cannot resolve symbol for expression: ${node.expression.getText()}`);
}
if (typeSymbol.flags & ts.SymbolFlags.Alias) {
const aliasedSymbol = this.typeChecker.getAliasedSymbol(typeSymbol);
const declaration = aliasedSymbol.declarations?.[0];
if (!declaration) {
throw new LogicError(node, `No declaration found for aliased symbol: ${aliasedSymbol.name}`);
}
return this.childNodeParser.createType(declaration, this.createSubContext(node, context));
} else if (typeSymbol.flags & ts.SymbolFlags.TypeParameter) {
return context.getArgument(typeSymbol.name);
} else {
const declaration = typeSymbol.declarations?.[0];
if (!declaration) {
throw new LogicError(node, `No declaration found for symbol: ${typeSymbol.name}`);
}
return this.childNodeParser.createType(declaration, this.createSubContext(node, context));
}
}
protected createSubContext(node: ts.ExpressionWithTypeArguments, parentContext: Context): Context {
const subContext = new Context(node);
if (node.typeArguments?.length) {
node.typeArguments.forEach((typeArg) => {
const type = this.childNodeParser.createType(typeArg, parentContext);
subContext.pushArgument(type);
});
}
return subContext;
}
}