1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | var ts = require("typescript");
|
4 | var typescript_helpers_1 = require("./typescript-helpers");
|
5 | var TypesUsageEvaluator = (function () {
|
6 | function TypesUsageEvaluator(files, typeChecker) {
|
7 | this.nodesParentsMap = new Map();
|
8 | this.typeChecker = typeChecker;
|
9 | this.computeUsages(files);
|
10 | }
|
11 | TypesUsageEvaluator.prototype.isTypeUsedBySymbol = function (typeNode, by) {
|
12 | if (typeNode.name === undefined) {
|
13 |
|
14 | return false;
|
15 | }
|
16 | return this.isSymbolUsedBySymbol(this.getSymbol(typeNode.name), by);
|
17 | };
|
18 | TypesUsageEvaluator.prototype.isSymbolUsedBySymbol = function (symbol, by) {
|
19 | return this.isSymbolUsedBySymbolImpl(this.getActualSymbol(symbol), this.getActualSymbol(by), new Set());
|
20 | };
|
21 | TypesUsageEvaluator.prototype.getSymbolsUsingNode = function (typeNode) {
|
22 | if (typeNode.name === undefined) {
|
23 | return null;
|
24 | }
|
25 | return this.nodesParentsMap.get(this.getSymbol(typeNode.name)) || null;
|
26 | };
|
27 | TypesUsageEvaluator.prototype.isSymbolUsedBySymbolImpl = function (fromSymbol, toSymbol, visitedSymbols) {
|
28 | if (fromSymbol === toSymbol) {
|
29 | return true;
|
30 | }
|
31 | var reachableNodes = this.nodesParentsMap.get(fromSymbol);
|
32 | if (reachableNodes) {
|
33 | for (var _i = 0, _a = Array.from(reachableNodes); _i < _a.length; _i++) {
|
34 | var symbol = _a[_i];
|
35 | if (visitedSymbols.has(symbol)) {
|
36 | continue;
|
37 | }
|
38 | visitedSymbols.add(symbol);
|
39 | if (this.isSymbolUsedBySymbolImpl(symbol, toSymbol, visitedSymbols)) {
|
40 | return true;
|
41 | }
|
42 | }
|
43 | }
|
44 | visitedSymbols.add(fromSymbol);
|
45 | return false;
|
46 | };
|
47 | TypesUsageEvaluator.prototype.computeUsages = function (files) {
|
48 | this.nodesParentsMap.clear();
|
49 | for (var _i = 0, files_1 = files; _i < files_1.length; _i++) {
|
50 | var file = files_1[_i];
|
51 | ts.forEachChild(file, this.computeUsageForNode.bind(this));
|
52 | }
|
53 | };
|
54 | TypesUsageEvaluator.prototype.computeUsageForNode = function (node) {
|
55 | if (typescript_helpers_1.isNodeNamedDeclaration(node) && node.name) {
|
56 | var childSymbol = this.getSymbol(node.name);
|
57 | this.computeUsagesRecursively(node, childSymbol);
|
58 | }
|
59 | else if (ts.isVariableStatement(node)) {
|
60 | for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) {
|
61 | var varDeclaration = _a[_i];
|
62 | this.computeUsageForNode(varDeclaration);
|
63 | }
|
64 | }
|
65 | };
|
66 | TypesUsageEvaluator.prototype.computeUsagesRecursively = function (parent, parentSymbol) {
|
67 | var queue = parent.getChildren();
|
68 | for (var _i = 0, queue_1 = queue; _i < queue_1.length; _i++) {
|
69 | var child = queue_1[_i];
|
70 | if (child.kind === ts.SyntaxKind.JSDocComment) {
|
71 | continue;
|
72 | }
|
73 | queue.push.apply(queue, child.getChildren());
|
74 | if (ts.isIdentifier(child)) {
|
75 | var childSymbol = this.getSymbol(child);
|
76 | var symbols = this.nodesParentsMap.get(childSymbol);
|
77 | if (symbols === undefined) {
|
78 | symbols = new Set();
|
79 | this.nodesParentsMap.set(childSymbol, symbols);
|
80 | }
|
81 |
|
82 | if (childSymbol !== parentSymbol) {
|
83 | symbols.add(parentSymbol);
|
84 | }
|
85 | }
|
86 | }
|
87 | };
|
88 | TypesUsageEvaluator.prototype.getSymbol = function (node) {
|
89 | var nodeSymbol = this.typeChecker.getSymbolAtLocation(node);
|
90 | if (nodeSymbol === undefined) {
|
91 | throw new Error("Cannot find symbol for node: " + node.getText());
|
92 | }
|
93 | return this.getActualSymbol(nodeSymbol);
|
94 | };
|
95 | TypesUsageEvaluator.prototype.getActualSymbol = function (symbol) {
|
96 | return typescript_helpers_1.getActualSymbol(symbol, this.typeChecker);
|
97 | };
|
98 | return TypesUsageEvaluator;
|
99 | }());
|
100 | exports.TypesUsageEvaluator = TypesUsageEvaluator;
|