tdepend 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +212 -116
- package/dist/api/analyze.d.ts +8 -68
- package/dist/api/analyze.js +33 -108
- package/dist/api/analyze.js.map +1 -1
- package/dist/api/explain.d.ts +22 -0
- package/dist/api/explain.js +38 -0
- package/dist/api/explain.js.map +1 -0
- package/dist/api/export.d.ts +4 -47
- package/dist/api/export.js +6 -45
- package/dist/api/export.js.map +1 -1
- package/dist/api/serialization.d.ts +6 -26
- package/dist/api/serialization.js +68 -58
- package/dist/api/serialization.js.map +1 -1
- package/dist/cli/index.js +11 -129
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/run.d.ts +12 -0
- package/dist/cli/run.js +112 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/config/loadConfig.d.ts +10 -10
- package/dist/config/loadConfig.js +73 -36
- package/dist/config/loadConfig.js.map +1 -1
- package/dist/config/schema.d.ts +59 -29
- package/dist/config/schema.js +45 -51
- package/dist/config/schema.js.map +1 -1
- package/dist/errors.d.ts +9 -0
- package/dist/errors.js +21 -0
- package/dist/errors.js.map +1 -0
- package/dist/files/collectFiles.d.ts +21 -0
- package/dist/files/collectFiles.js +189 -0
- package/dist/files/collectFiles.js.map +1 -0
- package/dist/fs.d.ts +16 -0
- package/dist/fs.js +50 -0
- package/dist/fs.js.map +1 -0
- package/dist/graph/buildFileGraph.d.ts +33 -0
- package/dist/graph/buildFileGraph.js +163 -0
- package/dist/graph/buildFileGraph.js.map +1 -0
- package/dist/graph/fileGraph.d.ts +20 -0
- package/dist/graph/fileGraph.js +75 -0
- package/dist/graph/fileGraph.js.map +1 -0
- package/dist/index.d.ts +10 -21
- package/dist/index.js +6 -29
- package/dist/index.js.map +1 -1
- package/dist/output/analyzeText.d.ts +7 -0
- package/dist/output/analyzeText.js +91 -0
- package/dist/output/analyzeText.js.map +1 -0
- package/dist/parser/extractSites.d.ts +3 -0
- package/dist/parser/extractSites.js +704 -0
- package/dist/parser/extractSites.js.map +1 -0
- package/dist/parser/loadsTarget.d.ts +10 -0
- package/dist/parser/loadsTarget.js +304 -0
- package/dist/parser/loadsTarget.js.map +1 -0
- package/dist/parser/types.d.ts +30 -0
- package/dist/{types/graph.js → parser/types.js} +1 -1
- package/dist/parser/types.js.map +1 -0
- package/dist/project/discoverProject.d.ts +2 -0
- package/dist/project/discoverProject.js +477 -0
- package/dist/project/discoverProject.js.map +1 -0
- package/dist/project/gitignore.d.ts +13 -0
- package/dist/project/gitignore.js +138 -0
- package/dist/project/gitignore.js.map +1 -0
- package/dist/project/types.d.ts +44 -0
- package/dist/{types/parser.js → project/types.js} +1 -1
- package/dist/project/types.js.map +1 -0
- package/dist/resolver/createResolver.d.ts +4 -0
- package/dist/resolver/createResolver.js +276 -0
- package/dist/resolver/createResolver.js.map +1 -0
- package/dist/resolver/types.d.ts +28 -0
- package/dist/resolver/types.js +3 -0
- package/dist/resolver/types.js.map +1 -0
- package/dist/resolver/workspaceHost.d.ts +12 -0
- package/dist/resolver/workspaceHost.js +253 -0
- package/dist/resolver/workspaceHost.js.map +1 -0
- package/dist/types/api.d.ts +71 -64
- package/package.json +24 -25
- package/dist/analysis/reporter.d.ts +0 -22
- package/dist/analysis/reporter.js +0 -116
- package/dist/analysis/reporter.js.map +0 -1
- package/dist/graph/cycleDetector.d.ts +0 -2
- package/dist/graph/cycleDetector.js +0 -56
- package/dist/graph/cycleDetector.js.map +0 -1
- package/dist/graph/dependencyGraph.d.ts +0 -10
- package/dist/graph/dependencyGraph.js +0 -41
- package/dist/graph/dependencyGraph.js.map +0 -1
- package/dist/metrics/abstractness.d.ts +0 -2
- package/dist/metrics/abstractness.js +0 -10
- package/dist/metrics/abstractness.js.map +0 -1
- package/dist/metrics/distance.d.ts +0 -1
- package/dist/metrics/distance.js +0 -7
- package/dist/metrics/distance.js.map +0 -1
- package/dist/metrics/index.d.ts +0 -4
- package/dist/metrics/index.js +0 -30
- package/dist/metrics/index.js.map +0 -1
- package/dist/metrics/instability.d.ts +0 -1
- package/dist/metrics/instability.js +0 -8
- package/dist/metrics/instability.js.map +0 -1
- package/dist/parser/fileScanner.d.ts +0 -8
- package/dist/parser/fileScanner.js +0 -22
- package/dist/parser/fileScanner.js.map +0 -1
- package/dist/parser/tsParser.d.ts +0 -18
- package/dist/parser/tsParser.js +0 -158
- package/dist/parser/tsParser.js.map +0 -1
- package/dist/types/graph.d.ts +0 -14
- package/dist/types/graph.js.map +0 -1
- package/dist/types/parser.d.ts +0 -26
- package/dist/types/parser.js.map +0 -1
- package/dist/utils/deepMerge.d.ts +0 -1
- package/dist/utils/deepMerge.js +0 -23
- package/dist/utils/deepMerge.js.map +0 -1
- package/dist/utils/log.d.ts +0 -2
- package/dist/utils/log.js +0 -9
- package/dist/utils/log.js.map +0 -1
- package/dist/utils/pathUtils.d.ts +0 -12
- package/dist/utils/pathUtils.js +0 -27
- package/dist/utils/pathUtils.js.map +0 -1
|
@@ -0,0 +1,704 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.parseFile = parseFile;
|
|
37
|
+
const ts = __importStar(require("typescript"));
|
|
38
|
+
// `absolutePath` lets TypeScript find the nearest package.json for the implied
|
|
39
|
+
// module format; a root-relative path would be read against the process cwd.
|
|
40
|
+
function parseFile(file, text, options, absolutePath = file) {
|
|
41
|
+
const sourceFile = createSourceFile(file, text, options, absolutePath);
|
|
42
|
+
return {
|
|
43
|
+
file,
|
|
44
|
+
sourceFile,
|
|
45
|
+
sites: extractSites(sourceFile),
|
|
46
|
+
directives: collectDirectives(sourceFile),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function createSourceFile(file, text, options, absolutePath) {
|
|
50
|
+
return ts.createSourceFile(file, text, {
|
|
51
|
+
languageVersion: ts.ScriptTarget.Latest,
|
|
52
|
+
impliedNodeFormat: impliedNodeFormatFor(absolutePath, options),
|
|
53
|
+
}, true, scriptKindFor(file));
|
|
54
|
+
}
|
|
55
|
+
function impliedNodeFormatFor(file, options) {
|
|
56
|
+
try {
|
|
57
|
+
return ts.getImpliedNodeFormatForFile(file, undefined, ts.sys, options);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function scriptKindFor(file) {
|
|
64
|
+
const lower = file.toLowerCase();
|
|
65
|
+
if (lower.endsWith('.tsx'))
|
|
66
|
+
return ts.ScriptKind.TSX;
|
|
67
|
+
if (lower.endsWith('.jsx'))
|
|
68
|
+
return ts.ScriptKind.JSX;
|
|
69
|
+
if (lower.endsWith('.js') || lower.endsWith('.mjs') || lower.endsWith('.cjs')) {
|
|
70
|
+
return ts.ScriptKind.JS;
|
|
71
|
+
}
|
|
72
|
+
return ts.ScriptKind.TS;
|
|
73
|
+
}
|
|
74
|
+
function extractSites(sourceFile) {
|
|
75
|
+
const sites = [];
|
|
76
|
+
const scopeInfo = sourceFile.text.includes('require') ? buildScopeInfo(sourceFile) : null;
|
|
77
|
+
const add = (draft, anchor) => {
|
|
78
|
+
const start = anchor.getStart(sourceFile);
|
|
79
|
+
const at = sourceFile.getLineAndCharacterOfPosition(start);
|
|
80
|
+
sites.push({ ...draft, line: at.line + 1, column: at.character + 1 });
|
|
81
|
+
};
|
|
82
|
+
const addImportDeclaration = (decl) => {
|
|
83
|
+
const specifier = decl.moduleSpecifier;
|
|
84
|
+
if (!ts.isStringLiteral(specifier))
|
|
85
|
+
return;
|
|
86
|
+
const clause = decl.importClause;
|
|
87
|
+
if (clause === undefined) {
|
|
88
|
+
add({
|
|
89
|
+
specifier: specifier.text,
|
|
90
|
+
kind: 'side-effect',
|
|
91
|
+
form: 'declaration',
|
|
92
|
+
bindings: [],
|
|
93
|
+
node: specifier,
|
|
94
|
+
}, specifier);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const bindings = importBindings(clause);
|
|
98
|
+
add({
|
|
99
|
+
specifier: specifier.text,
|
|
100
|
+
kind: importKind(clause),
|
|
101
|
+
form: 'declaration',
|
|
102
|
+
bindings,
|
|
103
|
+
node: specifier,
|
|
104
|
+
}, specifier);
|
|
105
|
+
};
|
|
106
|
+
const addExportDeclaration = (decl) => {
|
|
107
|
+
const specifier = decl.moduleSpecifier;
|
|
108
|
+
if (specifier === undefined || !ts.isStringLiteral(specifier))
|
|
109
|
+
return;
|
|
110
|
+
add({
|
|
111
|
+
specifier: specifier.text,
|
|
112
|
+
kind: exportKind(decl),
|
|
113
|
+
form: 'declaration',
|
|
114
|
+
bindings: exportBindings(decl),
|
|
115
|
+
node: specifier,
|
|
116
|
+
}, specifier);
|
|
117
|
+
};
|
|
118
|
+
const addImportEquals = (decl) => {
|
|
119
|
+
const reference = decl.moduleReference;
|
|
120
|
+
if (!ts.isExternalModuleReference(reference))
|
|
121
|
+
return;
|
|
122
|
+
const literal = reference.expression;
|
|
123
|
+
if (literal === undefined || !ts.isStringLiteral(literal))
|
|
124
|
+
return;
|
|
125
|
+
add({
|
|
126
|
+
specifier: literal.text,
|
|
127
|
+
kind: decl.isTypeOnly ? 'type' : 'require',
|
|
128
|
+
form: 'declaration',
|
|
129
|
+
bindings: [{ local: decl.name.text, imported: '*', typeOnly: decl.isTypeOnly }],
|
|
130
|
+
node: literal,
|
|
131
|
+
}, literal);
|
|
132
|
+
};
|
|
133
|
+
const addImportType = (node, fromJsDoc) => {
|
|
134
|
+
const argument = node.argument;
|
|
135
|
+
if (!ts.isLiteralTypeNode(argument) || !ts.isStringLiteral(argument.literal))
|
|
136
|
+
return;
|
|
137
|
+
add({
|
|
138
|
+
specifier: argument.literal.text,
|
|
139
|
+
kind: 'type',
|
|
140
|
+
form: 'type-context',
|
|
141
|
+
bindings: [],
|
|
142
|
+
unsupported: fromJsDoc ? 'jsdoc-import-type' : undefined,
|
|
143
|
+
node: argument.literal,
|
|
144
|
+
}, argument.literal);
|
|
145
|
+
};
|
|
146
|
+
const addCall = (node) => {
|
|
147
|
+
const isDynamic = node.expression.kind === ts.SyntaxKind.ImportKeyword;
|
|
148
|
+
const isRequire = ts.isIdentifier(node.expression) && node.expression.text === 'require';
|
|
149
|
+
if (!isDynamic && !isRequire)
|
|
150
|
+
return;
|
|
151
|
+
const kind = isDynamic ? 'dynamic' : 'require';
|
|
152
|
+
const argument = node.arguments[0];
|
|
153
|
+
if (argument === undefined || !isLiteralSpecifier(argument)) {
|
|
154
|
+
const anchor = argument ?? node;
|
|
155
|
+
const draft = {
|
|
156
|
+
specifier: argument === undefined ? '' : argument.getText(sourceFile),
|
|
157
|
+
kind,
|
|
158
|
+
form: 'declaration',
|
|
159
|
+
bindings: [],
|
|
160
|
+
unsupported: 'non-literal',
|
|
161
|
+
node: anchor,
|
|
162
|
+
};
|
|
163
|
+
if (isDynamic)
|
|
164
|
+
draft.deferred = isDeferred(node);
|
|
165
|
+
add(draft, anchor);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const draft = {
|
|
169
|
+
specifier: argument.text,
|
|
170
|
+
kind,
|
|
171
|
+
form: 'declaration',
|
|
172
|
+
bindings: [],
|
|
173
|
+
node: argument,
|
|
174
|
+
};
|
|
175
|
+
if (isDynamic)
|
|
176
|
+
draft.deferred = isDeferred(node);
|
|
177
|
+
if (isRequire && scopeInfo !== null && isRequireShadowed(scopeInfo, node)) {
|
|
178
|
+
draft.unsupported = 'shadowed-require';
|
|
179
|
+
}
|
|
180
|
+
add(draft, argument);
|
|
181
|
+
};
|
|
182
|
+
const addJsDocImportTag = (tag) => {
|
|
183
|
+
const specifier = tag.moduleSpecifier;
|
|
184
|
+
if (!ts.isStringLiteral(specifier))
|
|
185
|
+
return;
|
|
186
|
+
add({
|
|
187
|
+
specifier: specifier.text,
|
|
188
|
+
kind: 'type',
|
|
189
|
+
form: 'type-context',
|
|
190
|
+
bindings: [],
|
|
191
|
+
unsupported: 'jsdoc-import-type',
|
|
192
|
+
node: specifier,
|
|
193
|
+
}, specifier);
|
|
194
|
+
};
|
|
195
|
+
const visitJsDoc = (node) => {
|
|
196
|
+
if (ts.isImportTypeNode(node)) {
|
|
197
|
+
addImportType(node, true);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (ts.isJSDocImportTag(node)) {
|
|
201
|
+
addJsDocImportTag(node);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
node.forEachChild(visitJsDoc);
|
|
205
|
+
};
|
|
206
|
+
const visit = (node) => {
|
|
207
|
+
if (ts.isImportDeclaration(node))
|
|
208
|
+
return addImportDeclaration(node);
|
|
209
|
+
if (ts.isExportDeclaration(node))
|
|
210
|
+
return addExportDeclaration(node);
|
|
211
|
+
if (ts.isImportEqualsDeclaration(node))
|
|
212
|
+
return addImportEquals(node);
|
|
213
|
+
if (ts.isImportTypeNode(node))
|
|
214
|
+
return addImportType(node, false);
|
|
215
|
+
if (ts.isCallExpression(node))
|
|
216
|
+
addCall(node);
|
|
217
|
+
node.forEachChild(visit);
|
|
218
|
+
for (const doc of jsDocsOf(node))
|
|
219
|
+
visitJsDoc(doc);
|
|
220
|
+
};
|
|
221
|
+
visit(sourceFile);
|
|
222
|
+
sites.sort((a, b) => a.line - b.line || a.column - b.column);
|
|
223
|
+
return sites;
|
|
224
|
+
}
|
|
225
|
+
function importBindings(clause) {
|
|
226
|
+
const bindings = [];
|
|
227
|
+
if (clause.name !== undefined) {
|
|
228
|
+
bindings.push({ local: clause.name.text, imported: 'default', typeOnly: clause.isTypeOnly });
|
|
229
|
+
}
|
|
230
|
+
const named = clause.namedBindings;
|
|
231
|
+
if (named === undefined)
|
|
232
|
+
return bindings;
|
|
233
|
+
if (ts.isNamespaceImport(named)) {
|
|
234
|
+
bindings.push({ local: named.name.text, imported: '*', typeOnly: clause.isTypeOnly });
|
|
235
|
+
return bindings;
|
|
236
|
+
}
|
|
237
|
+
for (const element of named.elements) {
|
|
238
|
+
bindings.push({
|
|
239
|
+
local: element.name.text,
|
|
240
|
+
imported: element.propertyName?.text ?? element.name.text,
|
|
241
|
+
typeOnly: clause.isTypeOnly || element.isTypeOnly,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
return bindings;
|
|
245
|
+
}
|
|
246
|
+
function importKind(clause) {
|
|
247
|
+
if (clause.isTypeOnly)
|
|
248
|
+
return 'type';
|
|
249
|
+
if (clause.name !== undefined)
|
|
250
|
+
return 'static';
|
|
251
|
+
const named = clause.namedBindings;
|
|
252
|
+
if (named !== undefined &&
|
|
253
|
+
ts.isNamedImports(named) &&
|
|
254
|
+
named.elements.length > 0 &&
|
|
255
|
+
named.elements.every((element) => element.isTypeOnly)) {
|
|
256
|
+
return 'type';
|
|
257
|
+
}
|
|
258
|
+
return 'static';
|
|
259
|
+
}
|
|
260
|
+
function exportBindings(decl) {
|
|
261
|
+
const clause = decl.exportClause;
|
|
262
|
+
if (clause === undefined)
|
|
263
|
+
return [];
|
|
264
|
+
if (ts.isNamespaceExport(clause)) {
|
|
265
|
+
return [{ local: clause.name.text, imported: '*', typeOnly: decl.isTypeOnly }];
|
|
266
|
+
}
|
|
267
|
+
const bindings = [];
|
|
268
|
+
for (const element of clause.elements) {
|
|
269
|
+
bindings.push({
|
|
270
|
+
local: element.name.text,
|
|
271
|
+
imported: element.propertyName?.text ?? element.name.text,
|
|
272
|
+
typeOnly: decl.isTypeOnly || element.isTypeOnly,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
return bindings;
|
|
276
|
+
}
|
|
277
|
+
function exportKind(decl) {
|
|
278
|
+
if (decl.isTypeOnly)
|
|
279
|
+
return 'type';
|
|
280
|
+
const clause = decl.exportClause;
|
|
281
|
+
if (clause !== undefined &&
|
|
282
|
+
ts.isNamedExports(clause) &&
|
|
283
|
+
clause.elements.length > 0 &&
|
|
284
|
+
clause.elements.every((element) => element.isTypeOnly)) {
|
|
285
|
+
return 'type';
|
|
286
|
+
}
|
|
287
|
+
return 're-export';
|
|
288
|
+
}
|
|
289
|
+
function isLiteralSpecifier(node) {
|
|
290
|
+
return ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node);
|
|
291
|
+
}
|
|
292
|
+
// Code that runs in place, such as an immediately invoked function or a static
|
|
293
|
+
// initialiser, delays nothing itself, so the walk goes on to whatever encloses it.
|
|
294
|
+
function isDeferred(call) {
|
|
295
|
+
let child = call;
|
|
296
|
+
for (let parent = child.parent; parent !== undefined; parent = parent.parent) {
|
|
297
|
+
if (ts.isFunctionLike(parent) && !isImmediatelyInvoked(parent))
|
|
298
|
+
return true;
|
|
299
|
+
if (isInstanceInitializer(parent, child))
|
|
300
|
+
return true;
|
|
301
|
+
child = parent;
|
|
302
|
+
}
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
function isInstanceInitializer(node, child) {
|
|
306
|
+
return (ts.isPropertyDeclaration(node) &&
|
|
307
|
+
node.initializer !== undefined &&
|
|
308
|
+
containsNode(node.initializer, child) &&
|
|
309
|
+
!isStaticModifier(node));
|
|
310
|
+
}
|
|
311
|
+
function isStaticModifier(node) {
|
|
312
|
+
return (ts.canHaveModifiers(node) &&
|
|
313
|
+
(ts.getModifiers(node)?.some((modifier) => modifier.kind === ts.SyntaxKind.StaticKeyword) ??
|
|
314
|
+
false));
|
|
315
|
+
}
|
|
316
|
+
function isImmediatelyInvoked(node) {
|
|
317
|
+
let callee = node;
|
|
318
|
+
let parent = callee.parent;
|
|
319
|
+
while (parent !== undefined && ts.isParenthesizedExpression(parent)) {
|
|
320
|
+
callee = parent;
|
|
321
|
+
parent = parent.parent;
|
|
322
|
+
}
|
|
323
|
+
return parent !== undefined && ts.isCallExpression(parent) && parent.expression === callee;
|
|
324
|
+
}
|
|
325
|
+
function containsNode(ancestor, node) {
|
|
326
|
+
return node.pos >= ancestor.pos && node.end <= ancestor.end;
|
|
327
|
+
}
|
|
328
|
+
function jsDocsOf(node) {
|
|
329
|
+
return node.jsDoc ?? [];
|
|
330
|
+
}
|
|
331
|
+
function collectDirectives(sourceFile) {
|
|
332
|
+
const directives = [];
|
|
333
|
+
for (const statement of sourceFile.statements) {
|
|
334
|
+
if (!ts.isExpressionStatement(statement) || !ts.isStringLiteral(statement.expression))
|
|
335
|
+
break;
|
|
336
|
+
directives.push(statement.expression.text);
|
|
337
|
+
}
|
|
338
|
+
return directives;
|
|
339
|
+
}
|
|
340
|
+
function buildScopeInfo(sourceFile) {
|
|
341
|
+
const scopeOf = new WeakMap();
|
|
342
|
+
const analysis = analyzeScopes(sourceFile);
|
|
343
|
+
const root = {
|
|
344
|
+
parent: null,
|
|
345
|
+
bindings: new Set(),
|
|
346
|
+
ownsVars: true,
|
|
347
|
+
strict: isStrictSource(sourceFile),
|
|
348
|
+
};
|
|
349
|
+
scopeOf.set(sourceFile, root);
|
|
350
|
+
const stack = [root];
|
|
351
|
+
const current = () => stack[stack.length - 1];
|
|
352
|
+
const enclosingScopeOf = (node) => {
|
|
353
|
+
for (let ancestor = node.parent; ancestor !== undefined; ancestor = ancestor.parent) {
|
|
354
|
+
const scope = scopeOf.get(ancestor);
|
|
355
|
+
if (scope !== undefined)
|
|
356
|
+
return scope;
|
|
357
|
+
}
|
|
358
|
+
return root;
|
|
359
|
+
};
|
|
360
|
+
const varScope = () => {
|
|
361
|
+
for (let index = stack.length - 1; index >= 0; index -= 1) {
|
|
362
|
+
if (stack[index].ownsVars)
|
|
363
|
+
return stack[index];
|
|
364
|
+
}
|
|
365
|
+
return root;
|
|
366
|
+
};
|
|
367
|
+
const push = (node, ownsVars, strict) => {
|
|
368
|
+
const scope = {
|
|
369
|
+
parent: enclosingScopeOf(node),
|
|
370
|
+
bindings: new Set(),
|
|
371
|
+
ownsVars,
|
|
372
|
+
strict,
|
|
373
|
+
};
|
|
374
|
+
scopeOf.set(node, scope);
|
|
375
|
+
stack.push(scope);
|
|
376
|
+
return scope;
|
|
377
|
+
};
|
|
378
|
+
const addBinding = (name, scope) => {
|
|
379
|
+
collectBindingNames(name, scope.bindings);
|
|
380
|
+
};
|
|
381
|
+
const inheritStrict = (node) => enclosingScopeOf(node).strict;
|
|
382
|
+
const visit = (node) => {
|
|
383
|
+
if (ts.isFunctionLike(node)) {
|
|
384
|
+
const enclosing = enclosingScopeOf(node);
|
|
385
|
+
if (ts.isFunctionDeclaration(node) && node.name !== undefined) {
|
|
386
|
+
const name = node.name.text;
|
|
387
|
+
enclosing.bindings.add(name);
|
|
388
|
+
if (!enclosing.strict &&
|
|
389
|
+
isPlainFunction(node) &&
|
|
390
|
+
!isHoistBlocked(node, name, analysis.lexicalNames)) {
|
|
391
|
+
varScope().bindings.add(name);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
if (node.name !== undefined && ts.isComputedPropertyName(node.name)) {
|
|
395
|
+
scopeOf.set(node.name, enclosing);
|
|
396
|
+
}
|
|
397
|
+
for (const decorator of decoratorsOf(node))
|
|
398
|
+
scopeOf.set(decorator, enclosing);
|
|
399
|
+
for (const parameter of node.parameters) {
|
|
400
|
+
for (const decorator of decoratorsOf(parameter))
|
|
401
|
+
scopeOf.set(decorator, enclosing);
|
|
402
|
+
}
|
|
403
|
+
const body = node.body;
|
|
404
|
+
const strict = enclosing.strict || (body !== undefined && ts.isBlock(body) && hasUseStrictPrologue(body));
|
|
405
|
+
const scope = push(node, false, strict);
|
|
406
|
+
if (ts.isFunctionExpression(node) && node.name !== undefined) {
|
|
407
|
+
scope.bindings.add(node.name.text);
|
|
408
|
+
}
|
|
409
|
+
for (const parameter of node.parameters)
|
|
410
|
+
addBinding(parameter.name, scope);
|
|
411
|
+
node.forEachChild(visit);
|
|
412
|
+
stack.pop();
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
if (ts.isClassStaticBlockDeclaration(node)) {
|
|
416
|
+
push(node, true, true);
|
|
417
|
+
node.forEachChild(visit);
|
|
418
|
+
stack.pop();
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
if (ts.isClassExpression(node)) {
|
|
422
|
+
const scope = push(node, false, true);
|
|
423
|
+
if (node.name !== undefined)
|
|
424
|
+
scope.bindings.add(node.name.text);
|
|
425
|
+
node.forEachChild(visit);
|
|
426
|
+
stack.pop();
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
if (ts.isClassDeclaration(node)) {
|
|
430
|
+
if (node.name !== undefined)
|
|
431
|
+
current().bindings.add(node.name.text);
|
|
432
|
+
push(node, false, true);
|
|
433
|
+
node.forEachChild(visit);
|
|
434
|
+
stack.pop();
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
if (ts.isModuleBlock(node)) {
|
|
438
|
+
push(node, true, inheritStrict(node));
|
|
439
|
+
node.forEachChild(visit);
|
|
440
|
+
stack.pop();
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
if (ts.isCaseBlock(node) ||
|
|
444
|
+
ts.isForStatement(node) ||
|
|
445
|
+
ts.isForInStatement(node) ||
|
|
446
|
+
ts.isForOfStatement(node)) {
|
|
447
|
+
push(node, false, inheritStrict(node));
|
|
448
|
+
node.forEachChild(visit);
|
|
449
|
+
stack.pop();
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
if (ts.isBlock(node)) {
|
|
453
|
+
push(node, isFunctionBody(node), inheritStrict(node));
|
|
454
|
+
node.forEachChild(visit);
|
|
455
|
+
stack.pop();
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
if (ts.isCatchClause(node)) {
|
|
459
|
+
const scope = push(node, false, inheritStrict(node));
|
|
460
|
+
if (node.variableDeclaration !== undefined)
|
|
461
|
+
addBinding(node.variableDeclaration.name, scope);
|
|
462
|
+
node.forEachChild(visit);
|
|
463
|
+
stack.pop();
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
if (ts.isVariableDeclarationList(node)) {
|
|
467
|
+
const target = (node.flags & ts.NodeFlags.BlockScoped) !== 0 ? current() : varScope();
|
|
468
|
+
for (const declaration of node.declarations)
|
|
469
|
+
addBinding(declaration.name, target);
|
|
470
|
+
node.forEachChild(visit);
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
if (ts.isEnumDeclaration(node)) {
|
|
474
|
+
current().bindings.add(node.name.text);
|
|
475
|
+
node.forEachChild(visit);
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
if (ts.isModuleDeclaration(node)) {
|
|
479
|
+
if (ts.isIdentifier(node.name) && namespaceHasValue(node)) {
|
|
480
|
+
current().bindings.add(node.name.text);
|
|
481
|
+
}
|
|
482
|
+
const scope = push(node, false, inheritStrict(node));
|
|
483
|
+
const exports = analysis.namespaceExports.get(qualifiedNamespaceName(node));
|
|
484
|
+
if (exports !== undefined)
|
|
485
|
+
for (const name of exports)
|
|
486
|
+
scope.bindings.add(name);
|
|
487
|
+
node.forEachChild(visit);
|
|
488
|
+
stack.pop();
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
if (ts.isImportEqualsDeclaration(node)) {
|
|
492
|
+
if (!node.isTypeOnly)
|
|
493
|
+
current().bindings.add(node.name.text);
|
|
494
|
+
node.forEachChild(visit);
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
if (ts.isImportDeclaration(node)) {
|
|
498
|
+
addImportBindings(node, current());
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
node.forEachChild(visit);
|
|
502
|
+
};
|
|
503
|
+
visit(sourceFile);
|
|
504
|
+
return { scopeOf };
|
|
505
|
+
}
|
|
506
|
+
function decoratorsOf(node) {
|
|
507
|
+
return ts.canHaveDecorators(node) ? (ts.getDecorators(node) ?? []) : [];
|
|
508
|
+
}
|
|
509
|
+
function hasUseStrictPrologue(node) {
|
|
510
|
+
for (const statement of node.statements) {
|
|
511
|
+
if (ts.isExpressionStatement(statement) && ts.isStringLiteral(statement.expression)) {
|
|
512
|
+
if (statement.expression.text === 'use strict')
|
|
513
|
+
return true;
|
|
514
|
+
}
|
|
515
|
+
else {
|
|
516
|
+
break;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return false;
|
|
520
|
+
}
|
|
521
|
+
function isStrictSource(sourceFile) {
|
|
522
|
+
return ts.isExternalModule(sourceFile) || hasUseStrictPrologue(sourceFile);
|
|
523
|
+
}
|
|
524
|
+
function isFunctionBody(block) {
|
|
525
|
+
const parent = block.parent;
|
|
526
|
+
return ts.isFunctionLike(parent) && parent.body === block;
|
|
527
|
+
}
|
|
528
|
+
function analyzeScopes(sourceFile) {
|
|
529
|
+
const lexicalNames = new Map();
|
|
530
|
+
const namespaceExports = new Map();
|
|
531
|
+
const visit = (node) => {
|
|
532
|
+
if (isLexicalScope(node))
|
|
533
|
+
lexicalNames.set(node, directLexicalNames(node));
|
|
534
|
+
if (ts.isModuleDeclaration(node)) {
|
|
535
|
+
const key = qualifiedNamespaceName(node);
|
|
536
|
+
const body = node.body;
|
|
537
|
+
if (body !== undefined &&
|
|
538
|
+
ts.isModuleBlock(body) &&
|
|
539
|
+
!hasModifier(node, ts.SyntaxKind.DeclareKeyword)) {
|
|
540
|
+
const names = namespaceExports.get(key) ?? new Set();
|
|
541
|
+
for (const statement of body.statements) {
|
|
542
|
+
for (const name of exportedValueNames(statement))
|
|
543
|
+
names.add(name);
|
|
544
|
+
}
|
|
545
|
+
namespaceExports.set(key, names);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
node.forEachChild(visit);
|
|
549
|
+
};
|
|
550
|
+
visit(sourceFile);
|
|
551
|
+
return { lexicalNames, namespaceExports };
|
|
552
|
+
}
|
|
553
|
+
function isLexicalScope(node) {
|
|
554
|
+
return (ts.isSourceFile(node) ||
|
|
555
|
+
ts.isBlock(node) ||
|
|
556
|
+
ts.isModuleBlock(node) ||
|
|
557
|
+
ts.isCaseBlock(node) ||
|
|
558
|
+
ts.isClassStaticBlockDeclaration(node));
|
|
559
|
+
}
|
|
560
|
+
function statementsOf(node) {
|
|
561
|
+
if (ts.isSourceFile(node) || ts.isBlock(node) || ts.isModuleBlock(node))
|
|
562
|
+
return node.statements;
|
|
563
|
+
if (ts.isClassStaticBlockDeclaration(node))
|
|
564
|
+
return node.body.statements;
|
|
565
|
+
return undefined;
|
|
566
|
+
}
|
|
567
|
+
function directLexicalNames(node) {
|
|
568
|
+
const names = new Set();
|
|
569
|
+
const statements = statementsOf(node);
|
|
570
|
+
if (statements === undefined)
|
|
571
|
+
return names;
|
|
572
|
+
for (const statement of statements) {
|
|
573
|
+
if (ts.isVariableStatement(statement) &&
|
|
574
|
+
(statement.declarationList.flags & ts.NodeFlags.BlockScoped) !== 0) {
|
|
575
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
576
|
+
collectBindingNames(declaration.name, names);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
else if (ts.isClassDeclaration(statement) && statement.name !== undefined) {
|
|
580
|
+
names.add(statement.name.text);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
return names;
|
|
584
|
+
}
|
|
585
|
+
function namespaceHasValue(node) {
|
|
586
|
+
if (hasModifier(node, ts.SyntaxKind.DeclareKeyword))
|
|
587
|
+
return false;
|
|
588
|
+
const body = node.body;
|
|
589
|
+
if (body === undefined)
|
|
590
|
+
return false;
|
|
591
|
+
if (ts.isModuleBlock(body))
|
|
592
|
+
return body.statements.some(statementHasValue);
|
|
593
|
+
if (ts.isModuleDeclaration(body))
|
|
594
|
+
return namespaceHasValue(body);
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
597
|
+
function statementHasValue(statement) {
|
|
598
|
+
if (ts.isVariableStatement(statement) ||
|
|
599
|
+
ts.isFunctionDeclaration(statement) ||
|
|
600
|
+
ts.isClassDeclaration(statement) ||
|
|
601
|
+
ts.isEnumDeclaration(statement) ||
|
|
602
|
+
ts.isImportEqualsDeclaration(statement)) {
|
|
603
|
+
return true;
|
|
604
|
+
}
|
|
605
|
+
if (ts.isModuleDeclaration(statement))
|
|
606
|
+
return namespaceHasValue(statement);
|
|
607
|
+
return false;
|
|
608
|
+
}
|
|
609
|
+
function exportedValueNames(statement) {
|
|
610
|
+
if (!hasModifier(statement, ts.SyntaxKind.ExportKeyword))
|
|
611
|
+
return [];
|
|
612
|
+
if (ts.isVariableStatement(statement)) {
|
|
613
|
+
const names = new Set();
|
|
614
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
615
|
+
collectBindingNames(declaration.name, names);
|
|
616
|
+
}
|
|
617
|
+
return [...names];
|
|
618
|
+
}
|
|
619
|
+
if (ts.isFunctionDeclaration(statement) ||
|
|
620
|
+
ts.isClassDeclaration(statement) ||
|
|
621
|
+
ts.isEnumDeclaration(statement) ||
|
|
622
|
+
ts.isModuleDeclaration(statement)) {
|
|
623
|
+
return statement.name !== undefined && ts.isIdentifier(statement.name)
|
|
624
|
+
? [statement.name.text]
|
|
625
|
+
: [];
|
|
626
|
+
}
|
|
627
|
+
if (ts.isImportEqualsDeclaration(statement))
|
|
628
|
+
return [statement.name.text];
|
|
629
|
+
return [];
|
|
630
|
+
}
|
|
631
|
+
function qualifiedNamespaceName(node) {
|
|
632
|
+
const parts = [];
|
|
633
|
+
for (let current = node; current !== undefined; current = current.parent) {
|
|
634
|
+
if (ts.isModuleDeclaration(current) && ts.isIdentifier(current.name)) {
|
|
635
|
+
parts.unshift(current.name.text);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return parts.join('.');
|
|
639
|
+
}
|
|
640
|
+
function hasModifier(node, kind) {
|
|
641
|
+
return (ts.canHaveModifiers(node) &&
|
|
642
|
+
(ts.getModifiers(node)?.some((modifier) => modifier.kind === kind) ?? false));
|
|
643
|
+
}
|
|
644
|
+
function isPlainFunction(node) {
|
|
645
|
+
return node.asteriskToken === undefined && !hasModifier(node, ts.SyntaxKind.AsyncKeyword);
|
|
646
|
+
}
|
|
647
|
+
function isHoistBlocked(node, name, lexicalNames) {
|
|
648
|
+
for (let ancestor = node.parent; ancestor !== undefined; ancestor = ancestor.parent) {
|
|
649
|
+
const names = lexicalNames.get(ancestor);
|
|
650
|
+
if (names !== undefined && names.has(name))
|
|
651
|
+
return true;
|
|
652
|
+
if (isVarBoundary(ancestor))
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
return false;
|
|
656
|
+
}
|
|
657
|
+
function isVarBoundary(node) {
|
|
658
|
+
return (ts.isSourceFile(node) ||
|
|
659
|
+
ts.isModuleBlock(node) ||
|
|
660
|
+
ts.isClassStaticBlockDeclaration(node) ||
|
|
661
|
+
(ts.isBlock(node) && isFunctionBody(node)));
|
|
662
|
+
}
|
|
663
|
+
function collectBindingNames(name, out) {
|
|
664
|
+
if (ts.isIdentifier(name)) {
|
|
665
|
+
out.add(name.text);
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
for (const element of name.elements) {
|
|
669
|
+
if (ts.isBindingElement(element))
|
|
670
|
+
collectBindingNames(element.name, out);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
function addImportBindings(decl, scope) {
|
|
674
|
+
const clause = decl.importClause;
|
|
675
|
+
if (clause === undefined || clause.isTypeOnly)
|
|
676
|
+
return;
|
|
677
|
+
if (clause.name !== undefined)
|
|
678
|
+
scope.bindings.add(clause.name.text);
|
|
679
|
+
const named = clause.namedBindings;
|
|
680
|
+
if (named === undefined)
|
|
681
|
+
return;
|
|
682
|
+
if (ts.isNamespaceImport(named)) {
|
|
683
|
+
scope.bindings.add(named.name.text);
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
686
|
+
for (const element of named.elements) {
|
|
687
|
+
if (!element.isTypeOnly)
|
|
688
|
+
scope.bindings.add(element.name.text);
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
function isRequireShadowed(info, node) {
|
|
692
|
+
for (let current = node; current !== undefined; current = current.parent) {
|
|
693
|
+
const scope = info.scopeOf.get(current);
|
|
694
|
+
if (scope === undefined)
|
|
695
|
+
continue;
|
|
696
|
+
for (let candidate = scope; candidate !== null; candidate = candidate.parent) {
|
|
697
|
+
if (candidate.bindings.has('require'))
|
|
698
|
+
return true;
|
|
699
|
+
}
|
|
700
|
+
return false;
|
|
701
|
+
}
|
|
702
|
+
return false;
|
|
703
|
+
}
|
|
704
|
+
//# sourceMappingURL=extractSites.js.map
|