@esportsplus/typescript 0.32.0 → 0.33.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.
Files changed (68) hide show
  1. package/README.md +34 -49
  2. package/build/cli/tsc.d.ts +3 -2
  3. package/build/cli/tsc.js +15 -97
  4. package/build/{probe → guard}/adapter.d.ts +1 -2
  5. package/build/{probe → guard}/adapter.js +1 -4
  6. package/build/{probe → guard}/async/channel.d.ts +1 -1
  7. package/build/{probe → guard}/async/channel.js +11 -191
  8. package/build/{probe → guard}/async/value.d.ts +1 -2
  9. package/build/{probe → guard}/async/value.js +1 -4
  10. package/build/guard/channels.d.ts +4 -0
  11. package/build/guard/channels.js +13 -0
  12. package/build/{probe → guard}/exceptions/channel.d.ts +3 -2
  13. package/build/{probe → guard}/exceptions/channel.js +167 -107
  14. package/build/guard/exceptions/derive.d.ts +49 -0
  15. package/build/guard/exceptions/derive.js +478 -0
  16. package/build/guard/exceptions/resolve-js.d.ts +2 -0
  17. package/build/guard/exceptions/resolve-js.js +26 -0
  18. package/build/{probe → guard}/exceptions/value.d.ts +3 -2
  19. package/build/{probe → guard}/exceptions/value.js +12 -4
  20. package/build/{probe → guard}/kernel/analyze.d.ts +2 -1
  21. package/build/guard/kernel/analyze.js +84 -0
  22. package/build/guard/kernel/ast.d.ts +13 -0
  23. package/build/{probe → guard}/kernel/ast.js +22 -15
  24. package/build/guard/kernel/config.js +93 -0
  25. package/build/guard/kernel/fixpoint.d.ts +6 -0
  26. package/build/{probe → guard}/kernel/fixpoint.js +8 -48
  27. package/build/guard/kernel/graph.d.ts +4 -0
  28. package/build/guard/kernel/graph.js +268 -0
  29. package/build/{probe → guard}/kernel/ids.d.ts +2 -3
  30. package/build/{probe → guard}/kernel/ids.js +1 -6
  31. package/build/{probe → guard}/kernel/types.d.ts +3 -32
  32. package/build/{probe → guard}/overlay/base/async.jsonc +1 -1
  33. package/build/{probe → guard}/overlay/base/exceptions.jsonc +16 -3
  34. package/build/{probe → guard}/overlay/base/resources.jsonc +7 -8
  35. package/build/{probe → guard}/overlay/load.d.ts +3 -7
  36. package/build/{probe → guard}/overlay/load.js +37 -120
  37. package/build/{probe → guard}/resources/channel.d.ts +1 -1
  38. package/build/{probe → guard}/resources/channel.js +81 -159
  39. package/build/{probe → guard}/resources/value.d.ts +1 -2
  40. package/build/{probe → guard}/resources/value.js +1 -14
  41. package/build/lsp/diagnostics.d.ts +2 -2
  42. package/build/lsp/diagnostics.js +2 -2
  43. package/build/lsp/server.js +41 -3
  44. package/build/lsp/workspace.d.ts +6 -3
  45. package/build/lsp/workspace.js +19 -5
  46. package/build/tsconfig.d.ts +2 -1
  47. package/build/tsconfig.js +44 -102
  48. package/package.json +2 -2
  49. package/tsconfig.base.json +12 -19
  50. package/tsconfig.package.json +6 -1
  51. package/build/probe/channels.d.ts +0 -4
  52. package/build/probe/channels.js +0 -16
  53. package/build/probe/kernel/analyze.js +0 -68
  54. package/build/probe/kernel/ast.d.ts +0 -11
  55. package/build/probe/kernel/config.js +0 -209
  56. package/build/probe/kernel/fixpoint.d.ts +0 -6
  57. package/build/probe/kernel/graph.d.ts +0 -4
  58. package/build/probe/kernel/graph.js +0 -507
  59. package/build/probe/overlay/presets/express.jsonc +0 -25
  60. package/build/probe/overlay/presets/node.jsonc +0 -17
  61. /package/build/{probe → guard}/exceptions/jsdoc.d.ts +0 -0
  62. /package/build/{probe → guard}/exceptions/jsdoc.js +0 -0
  63. /package/build/{probe → guard}/kernel/config.d.ts +0 -0
  64. /package/build/{probe → guard}/kernel/format.d.ts +0 -0
  65. /package/build/{probe → guard}/kernel/format.js +0 -0
  66. /package/build/{probe → guard}/kernel/program.d.ts +0 -0
  67. /package/build/{probe → guard}/kernel/program.js +0 -0
  68. /package/build/{probe → guard}/kernel/types.js +0 -0
@@ -2,26 +2,33 @@ import * as ts from '../adapter.js';
2
2
  function shouldUnwrap(expr, options) {
3
3
  return (ts.isParenthesizedExpression(expr) ||
4
4
  (options.assertions === true &&
5
- (ts.isAsExpression(expr) || ts.isNonNullExpression(expr))) ||
5
+ (ts.isAsExpression(expr) ||
6
+ ts.isNonNullExpression(expr) ||
7
+ ts.isSatisfiesExpression(expr))) ||
6
8
  (options.awaits === true && ts.isAwaitExpression(expr)));
7
9
  }
8
10
  const bodyOf = (node) => {
9
11
  return node.body;
10
12
  };
11
- const calleeSelectors = (callee) => {
12
- let selectors = new Set();
13
- if (ts.isIdentifier(callee)) {
14
- selectors.add(callee.text);
15
- }
16
- else if (ts.isPropertyAccessExpression(callee)) {
17
- let member = callee.name.text;
18
- selectors.add(member);
19
- if (ts.isIdentifier(callee.expression)) {
20
- selectors.add(`${callee.expression.text}.${member}`);
21
- selectors.add(`${callee.expression.text}#${member}`);
22
- }
13
+ const constituents = (type) => {
14
+ return ts.unionTypes(type) ?? [type];
15
+ };
16
+ const hasModifier = (node, kind) => {
17
+ const modifiers = node.modifiers;
18
+ return modifiers?.some((modifier) => modifier.kind === kind) ?? false;
19
+ };
20
+ const isAwaited = (call) => {
21
+ let child = call;
22
+ let parent = call.parent;
23
+ while (parent &&
24
+ (ts.isParenthesizedExpression(parent) ||
25
+ ts.isAsExpression(parent) ||
26
+ ts.isNonNullExpression(parent)) &&
27
+ parent.expression === child) {
28
+ child = parent;
29
+ parent = parent.parent;
23
30
  }
24
- return selectors;
31
+ return parent !== undefined && ts.isAwaitExpression(parent);
25
32
  };
26
33
  const paramSymbols = (checker, fn) => {
27
34
  let symbols = new Map();
@@ -46,4 +53,4 @@ const unwrap = (expr, options = {}) => {
46
53
  }
47
54
  return unwrapped;
48
55
  };
49
- export { bodyOf, calleeSelectors, paramSymbols, unwrap };
56
+ export { bodyOf, constituents, hasModifier, isAwaited, paramSymbols, unwrap };
@@ -0,0 +1,93 @@
1
+ import * as NodePath from 'node:path';
2
+ import { readGuardConfig } from '../../tsconfig.js';
3
+ import { stripJsonc } from '../../jsonc.js';
4
+ const CHANNEL_NAMES = ['exceptions', 'resources', 'async'];
5
+ const SEVERITIES = ['error', 'info', 'off', 'warn'];
6
+ const OPTION_KEYS = {
7
+ async: [],
8
+ exceptions: ['report'],
9
+ resources: [],
10
+ };
11
+ function fail(message) {
12
+ throw new Error(`analyze config: ${message}`);
13
+ }
14
+ function absent(value) {
15
+ return value === undefined || value === null;
16
+ }
17
+ function isPlainObject(value) {
18
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
19
+ }
20
+ function parseSeverity(value, channel) {
21
+ if (absent(value)) {
22
+ return 'error';
23
+ }
24
+ if (!SEVERITIES.includes(value)) {
25
+ fail(`${channel}.severity must be "error", "warn", "info", or "off"`);
26
+ }
27
+ return value;
28
+ }
29
+ function parseChannel(name, raw) {
30
+ if (!isPlainObject(raw)) {
31
+ fail(`${name} must be an object`);
32
+ }
33
+ const options = {};
34
+ for (const key of Object.keys(raw)) {
35
+ if (key === 'severity' || absent(raw[key])) {
36
+ continue;
37
+ }
38
+ if (!OPTION_KEYS[name].includes(key)) {
39
+ fail(`${name}.${key} is not a supported option`);
40
+ }
41
+ options[key] = raw[key];
42
+ }
43
+ return { severity: parseSeverity(raw['severity'], name), options };
44
+ }
45
+ function normalizeConfig(raw, projectRoot) {
46
+ if (!isPlainObject(raw)) {
47
+ fail(`root must be a JSON object`);
48
+ }
49
+ for (const key of Object.keys(raw)) {
50
+ if (absent(raw[key])) {
51
+ continue;
52
+ }
53
+ if (!CHANNEL_NAMES.includes(key)) {
54
+ fail(`unknown channel "${key}" (known: ${CHANNEL_NAMES.join(', ')})`);
55
+ }
56
+ }
57
+ const channels = {};
58
+ for (const name of CHANNEL_NAMES) {
59
+ channels[name] = absent(raw[name])
60
+ ? { severity: 'off', options: {} }
61
+ : parseChannel(name, raw[name]);
62
+ }
63
+ return {
64
+ projectRoot,
65
+ tsconfigPath: NodePath.join(projectRoot, 'tsconfig.json'),
66
+ channels,
67
+ };
68
+ }
69
+ function parseConfig(text, projectRoot) {
70
+ let parsed;
71
+ try {
72
+ parsed = JSON.parse(stripJsonc(text));
73
+ }
74
+ catch (error) {
75
+ fail(`invalid JSONC: ${error.message}`);
76
+ }
77
+ return normalizeConfig(parsed, projectRoot);
78
+ }
79
+ function configFromObject(raw, projectRoot) {
80
+ return normalizeConfig((raw ?? {}), projectRoot);
81
+ }
82
+ function loadConfigFromTsconfig(tsconfigPath) {
83
+ const resolved = NodePath.resolve(tsconfigPath);
84
+ const guard = readGuardConfig(resolved);
85
+ if (!guard) {
86
+ return undefined;
87
+ }
88
+ return {
89
+ ...configFromObject(guard, NodePath.dirname(resolved)),
90
+ tsconfigPath: resolved,
91
+ };
92
+ }
93
+ export { configFromObject, loadConfigFromTsconfig, parseConfig };
@@ -0,0 +1,6 @@
1
+ import type { Analysis, Channel, Diagnostic, SummaryStore } from './types.js';
2
+ declare function runChannel<V>(analysis: Analysis, channel: Channel<V>, channelConfig: unknown, peers: ReadonlyMap<string, SummaryStore<unknown>>): {
3
+ store: SummaryStore<V>;
4
+ diagnostics: Diagnostic[];
5
+ };
6
+ export { runChannel };
@@ -66,14 +66,10 @@ function tarjanSccs(nodes, successors) {
66
66
  }
67
67
  return sccs;
68
68
  }
69
- function runChannel(analysis, channel, dispatch, channelConfig, peers) {
69
+ function runChannel(analysis, channel, channelConfig, peers) {
70
70
  const graph = analysis.graph;
71
71
  const reached = graph.reachedFunctions();
72
- const reachedById = new Map();
73
- for (const fn of reached) {
74
- reachedById.set(fn.id, fn);
75
- }
76
- const calleesOf = (fn) => graph.calleesOf(fn).filter((c) => reachedById.has(c.id));
72
+ const calleesOf = graph.calleesOf;
77
73
  const summaries = new Map();
78
74
  const bottomSummary = () => ({
79
75
  value: channel.bottom(),
@@ -83,9 +79,6 @@ function runChannel(analysis, channel, dispatch, channelConfig, peers) {
83
79
  const makeTransferContext = (fn) => ({
84
80
  checker: analysis.checker,
85
81
  fn,
86
- dispatch,
87
- channelConfig,
88
- sinks: analysis.config.sinks,
89
82
  summaryOf,
90
83
  resolveCall: (call) => graph.resolveCall(call, channel.name),
91
84
  resolveCallFor: (peerChannel, call) => graph.resolveCall(call, peerChannel),
@@ -96,6 +89,12 @@ function runChannel(analysis, channel, dispatch, channelConfig, peers) {
96
89
  for (const fn of scc) {
97
90
  summaries.set(fn.id, bottomSummary());
98
91
  }
92
+ if (scc.length === 1 &&
93
+ !calleesOf(scc[0]).some((callee) => callee.id === scc[0].id)) {
94
+ const fn = scc[0];
95
+ summaries.set(fn.id, channel.transfer(makeTransferContext(fn)));
96
+ continue;
97
+ }
99
98
  let round = 0;
100
99
  for (;;) {
101
100
  round += 1;
@@ -136,41 +135,6 @@ function runChannel(analysis, channel, dispatch, channelConfig, peers) {
136
135
  }
137
136
  }
138
137
  }
139
- const boundaries = graph.boundaries();
140
- const pathToBoundary = (fn) => {
141
- if (boundaries.has(fn.id)) {
142
- return [fn];
143
- }
144
- const parent = new Map();
145
- const visited = new Set([fn.id]);
146
- const queue = [fn];
147
- let head = 0;
148
- while (head < queue.length) {
149
- const cur = queue[head];
150
- head += 1;
151
- for (const caller of reverse.get(cur.id) ?? []) {
152
- if (visited.has(caller.id)) {
153
- continue;
154
- }
155
- visited.add(caller.id);
156
- parent.set(caller.id, cur);
157
- if (boundaries.has(caller.id)) {
158
- const rev = [];
159
- let node = caller;
160
- while (node) {
161
- rev.push(node);
162
- if (node.id === fn.id) {
163
- break;
164
- }
165
- node = parent.get(node.id);
166
- }
167
- return rev.toReversed();
168
- }
169
- queue.push(caller);
170
- }
171
- }
172
- return [fn];
173
- };
174
138
  const roots = reached.filter((fn) => (reverse.get(fn.id) ?? []).length === 0);
175
139
  const diagnostics = [];
176
140
  const seen = new Set();
@@ -178,15 +142,11 @@ function runChannel(analysis, channel, dispatch, channelConfig, peers) {
178
142
  const ctx = {
179
143
  checker: analysis.checker,
180
144
  fn,
181
- dispatch,
182
145
  channelConfig,
183
- sinks: analysis.config.sinks,
184
- isBoundary: boundaries.has(fn.id),
185
146
  summaryOf,
186
147
  resolveCall: (call) => graph.resolveCall(call, channel.name),
187
148
  resolveCallFor: (peerChannel, call) => graph.resolveCall(call, peerChannel),
188
149
  peerSummaryValue: (peerChannel, fnId) => peers.get(peerChannel)?.get(fnId).value,
189
- pathToBoundary,
190
150
  roots: () => roots,
191
151
  };
192
152
  for (const d of channel.diagnose(ctx)) {
@@ -0,0 +1,4 @@
1
+ import * as ts from '../adapter.js';
2
+ import type { CallGraph, OverlaySet } from './types.js';
3
+ declare function buildCallGraph(program: ts.Program, checker: ts.TypeChecker, overlays: OverlaySet): CallGraph;
4
+ export { buildCallGraph };
@@ -0,0 +1,268 @@
1
+ import * as ts from '../adapter.js';
2
+ import { hasModifier, unwrap } from './ast.js';
3
+ import { isFunctionLike, makeFunctionInfo } from './ids.js';
4
+ function buildCallGraph(program, checker, overlays) {
5
+ const sourceFiles = ts.getSourceFiles(program);
6
+ const analyzableFiles = new Set(entryFiles());
7
+ const reached = new Map();
8
+ const worklist = [];
9
+ const coreCache = new Map();
10
+ const resolutionCache = new Map();
11
+ const callsCache = new Map();
12
+ const calleesCache = new Map();
13
+ function isAnalyzable(node) {
14
+ const sf = node.getSourceFile();
15
+ return analyzableFiles.has(sf) && node.body != null;
16
+ }
17
+ function intern(node) {
18
+ if (!isAnalyzable(node)) {
19
+ return undefined;
20
+ }
21
+ const existing = reached.get(node);
22
+ if (existing) {
23
+ return existing;
24
+ }
25
+ const info = makeFunctionInfo(node, node.getSourceFile());
26
+ reached.set(node, info);
27
+ worklist.push(info);
28
+ return info;
29
+ }
30
+ function calleeSymbol(call) {
31
+ let sym = checker.getSymbolAtLocation(call.expression);
32
+ if (sym && sym.flags & ts.SymbolFlags.Alias) {
33
+ sym = checker.getAliasedSymbol(sym);
34
+ }
35
+ return sym;
36
+ }
37
+ function functionLikesFromSymbol(sym, isNew) {
38
+ const out = [];
39
+ for (const decl of ts.symbolDeclarations(sym)) {
40
+ if (isFunctionLike(decl)) {
41
+ out.push(decl);
42
+ continue;
43
+ }
44
+ if (ts.isVariableDeclaration(decl) &&
45
+ decl.initializer &&
46
+ isFunctionLike(decl.initializer)) {
47
+ out.push(decl.initializer);
48
+ continue;
49
+ }
50
+ if (isNew && ts.isClassLike(decl)) {
51
+ const members = decl.members ?? [];
52
+ for (const member of members) {
53
+ if (ts.isConstructorDeclaration(member)) {
54
+ out.push(member);
55
+ }
56
+ }
57
+ }
58
+ }
59
+ return out;
60
+ }
61
+ function argExpressions(call) {
62
+ return call.arguments ? Array.from(call.arguments) : [];
63
+ }
64
+ function computeCore(call) {
65
+ const isNew = ts.isNewExpression(call);
66
+ const sym = calleeSymbol(call);
67
+ let functionArgs;
68
+ const resolveFunctionArgs = () => {
69
+ if (functionArgs) {
70
+ return functionArgs;
71
+ }
72
+ const resolved = new Map();
73
+ functionArgs = resolved;
74
+ argExpressions(call).forEach((arg, index) => {
75
+ const infos = resolveFunctionValue(arg);
76
+ if (infos.length > 0) {
77
+ resolved.set(index, infos);
78
+ }
79
+ });
80
+ return functionArgs;
81
+ };
82
+ if (!sym) {
83
+ return {
84
+ symbol: undefined,
85
+ targets: [],
86
+ functionArgs: resolveFunctionArgs,
87
+ unresolved: true,
88
+ };
89
+ }
90
+ const fns = functionLikesFromSymbol(sym, isNew);
91
+ const seen = new Set();
92
+ const targets = [];
93
+ for (const fn of fns) {
94
+ const info = intern(fn);
95
+ if (info && !seen.has(info.id)) {
96
+ seen.add(info.id);
97
+ targets.push(info);
98
+ }
99
+ }
100
+ if (targets.length > 0) {
101
+ return { symbol: sym, targets, functionArgs: resolveFunctionArgs, unresolved: false };
102
+ }
103
+ if (fns.length === 0) {
104
+ return { symbol: sym, targets: [], functionArgs: resolveFunctionArgs, unresolved: true };
105
+ }
106
+ if (fns.some((fn) => hasModifier(fn, ts.SyntaxKind.AbstractKeyword))) {
107
+ return { symbol: sym, targets: [], functionArgs: resolveFunctionArgs, unresolved: true };
108
+ }
109
+ return { symbol: sym, targets: [], functionArgs: resolveFunctionArgs, unresolved: false };
110
+ }
111
+ function getCore(call) {
112
+ let core = coreCache.get(call);
113
+ if (!core) {
114
+ core = computeCore(call);
115
+ coreCache.set(call, core);
116
+ }
117
+ return core;
118
+ }
119
+ function resolveFunctionValue(expr) {
120
+ const e = unwrap(expr, { assertions: true });
121
+ if (isFunctionLike(e)) {
122
+ const info = intern(e);
123
+ return info ? [info] : [];
124
+ }
125
+ if (ts.isIdentifier(e) ||
126
+ ts.isPropertyAccessExpression(e) ||
127
+ ts.isElementAccessExpression(e)) {
128
+ let sym = checker.getSymbolAtLocation(e);
129
+ if (sym && sym.flags & ts.SymbolFlags.Alias) {
130
+ sym = checker.getAliasedSymbol(sym);
131
+ }
132
+ if (!sym) {
133
+ return [];
134
+ }
135
+ const seen = new Set();
136
+ const out = [];
137
+ for (const fn of functionLikesFromSymbol(sym, false)) {
138
+ const info = intern(fn);
139
+ if (info && !seen.has(info.id)) {
140
+ seen.add(info.id);
141
+ out.push(info);
142
+ }
143
+ }
144
+ return out;
145
+ }
146
+ return [];
147
+ }
148
+ function callsIn(fn) {
149
+ const cached = callsCache.get(fn.id);
150
+ if (cached) {
151
+ return cached;
152
+ }
153
+ const calls = [];
154
+ const visit = (node) => {
155
+ if (node !== fn.node && isFunctionLike(node)) {
156
+ return;
157
+ }
158
+ if (ts.isCallExpression(node) || ts.isNewExpression(node)) {
159
+ calls.push(node);
160
+ }
161
+ ts.forEachChild(node, visit);
162
+ };
163
+ const body = fn.node.body;
164
+ if (body) {
165
+ visit(body);
166
+ }
167
+ for (const param of fn.node.parameters) {
168
+ if (param.initializer) {
169
+ visit(param.initializer);
170
+ }
171
+ }
172
+ callsCache.set(fn.id, calls);
173
+ return calls;
174
+ }
175
+ function allFunctionLikesIn(sf) {
176
+ const out = [];
177
+ const visit = (node) => {
178
+ if (isFunctionLike(node) &&
179
+ (!ts.isFunctionDeclaration(node) || node.body)) {
180
+ out.push(node);
181
+ }
182
+ ts.forEachChild(node, visit);
183
+ };
184
+ ts.forEachChild(sf, visit);
185
+ return out;
186
+ }
187
+ function entryFiles() {
188
+ return sourceFiles.filter((sf) => !sf.isDeclarationFile &&
189
+ !sf.fileName.replace(/\\/g, '/').includes('/node_modules/'));
190
+ }
191
+ for (const sf of entryFiles()) {
192
+ for (const node of allFunctionLikesIn(sf)) {
193
+ intern(node);
194
+ }
195
+ }
196
+ for (let workIndex = 0; workIndex < worklist.length; workIndex++) {
197
+ const fn = worklist[workIndex];
198
+ for (const call of callsIn(fn)) {
199
+ getCore(call);
200
+ }
201
+ }
202
+ const reachedList = Array.from(reached.values());
203
+ function resolveCall(call, channel) {
204
+ let cached = resolutionCache.get(call)?.get(channel);
205
+ if (cached) {
206
+ return cached;
207
+ }
208
+ const core = getCore(call);
209
+ let result;
210
+ if (core.targets.length > 0) {
211
+ result = {
212
+ targets: core.targets,
213
+ overlay: undefined,
214
+ get functionArgs() { return core.functionArgs(); },
215
+ unresolved: false,
216
+ };
217
+ }
218
+ else {
219
+ const overlay = core.symbol
220
+ ? overlays.lookup(core.symbol, channel)
221
+ : undefined;
222
+ result = overlay ? {
223
+ targets: [],
224
+ overlay,
225
+ get functionArgs() { return core.functionArgs(); },
226
+ unresolved: false,
227
+ } : {
228
+ targets: [],
229
+ overlay: undefined,
230
+ get functionArgs() { return core.functionArgs(); },
231
+ unresolved: core.unresolved,
232
+ };
233
+ }
234
+ let resolutions = resolutionCache.get(call);
235
+ if (!resolutions) {
236
+ resolutions = new Map();
237
+ resolutionCache.set(call, resolutions);
238
+ }
239
+ resolutions.set(channel, result);
240
+ return result;
241
+ }
242
+ function calleesOf(fn) {
243
+ const cached = calleesCache.get(fn.id);
244
+ if (cached) {
245
+ return cached;
246
+ }
247
+ const seen = new Set();
248
+ const out = [];
249
+ for (const call of callsIn(fn)) {
250
+ for (const target of getCore(call).targets) {
251
+ if (reached.has(target.node) && !seen.has(target.id)) {
252
+ seen.add(target.id);
253
+ out.push(target);
254
+ }
255
+ }
256
+ }
257
+ calleesCache.set(fn.id, out);
258
+ return out;
259
+ }
260
+ return {
261
+ reachedFunctions() {
262
+ return reachedList;
263
+ },
264
+ calleesOf,
265
+ resolveCall,
266
+ };
267
+ }
268
+ export { buildCallGraph };
@@ -1,8 +1,7 @@
1
1
  import * as ts from '../adapter.js';
2
2
  import type { FunctionInfo, FunctionLike, SourceLocation } from './types.js';
3
+ declare const FUNCTION_LIKE_KINDS: Set<ts.SyntaxKind>;
3
4
  declare function isFunctionLike(node: ts.Node): node is FunctionLike;
4
- declare function functionName(node: FunctionLike): string;
5
- declare function functionId(node: FunctionLike, sourceFile: ts.SourceFile): string;
6
5
  declare function makeFunctionInfo(node: FunctionLike, sourceFile: ts.SourceFile): FunctionInfo;
7
6
  declare function locationOf(node: ts.Node, sourceFile: ts.SourceFile): SourceLocation;
8
- export { functionId, functionName, isFunctionLike, locationOf, makeFunctionInfo };
7
+ export { FUNCTION_LIKE_KINDS, isFunctionLike, locationOf, makeFunctionInfo };
@@ -39,17 +39,12 @@ function functionId(node, sourceFile) {
39
39
  return `${sourceFile.fileName}:${node.getStart(sourceFile)}`;
40
40
  }
41
41
  function makeFunctionInfo(node, sourceFile) {
42
- const nameNode = node.name;
43
- const pos = nameNode
44
- ? nameNode.getStart(sourceFile)
45
- : node.getStart(sourceFile);
46
42
  return {
47
43
  id: functionId(node, sourceFile),
48
44
  node,
49
45
  sourceFile,
50
46
  name: functionName(node),
51
47
  fileName: sourceFile.fileName,
52
- pos,
53
48
  };
54
49
  }
55
50
  function locationOf(node, sourceFile) {
@@ -63,4 +58,4 @@ function locationOf(node, sourceFile) {
63
58
  end: node.getEnd(),
64
59
  };
65
60
  }
66
- export { functionId, functionName, isFunctionLike, locationOf, makeFunctionInfo };
61
+ export { FUNCTION_LIKE_KINDS, isFunctionLike, locationOf, makeFunctionInfo };
@@ -6,13 +6,12 @@ type FunctionInfo = {
6
6
  readonly sourceFile: ts.SourceFile;
7
7
  readonly name: string;
8
8
  readonly fileName: string;
9
- readonly pos: number;
10
9
  };
11
10
  type Summary<V> = {
12
11
  readonly value: V;
13
12
  readonly fromCallbacks: ReadonlySet<number>;
14
13
  };
15
- export type Dispatch = 'optimist' | 'pessimist';
14
+ export type Severity = 'error' | 'info' | 'off' | 'warn';
16
15
  type CalleeResolution = {
17
16
  readonly targets: ReadonlyArray<FunctionInfo>;
18
17
  readonly overlay: OverlayLookup | undefined;
@@ -27,9 +26,6 @@ type OverlayLookup = {
27
26
  type TransferContext<V> = {
28
27
  readonly checker: ts.TypeChecker;
29
28
  readonly fn: FunctionInfo;
30
- readonly dispatch: Dispatch;
31
- readonly channelConfig: unknown;
32
- readonly sinks: ReadonlyArray<SinkConfig>;
33
29
  summaryOf(fn: FunctionInfo): Summary<V>;
34
30
  resolveCall(call: ts.CallExpression | ts.NewExpression): CalleeResolution;
35
31
  resolveCallFor(channel: string, call: ts.CallExpression | ts.NewExpression): CalleeResolution;
@@ -38,15 +34,11 @@ type TransferContext<V> = {
38
34
  type DiagnoseContext<V> = {
39
35
  readonly checker: ts.TypeChecker;
40
36
  readonly fn: FunctionInfo;
41
- readonly dispatch: Dispatch;
42
37
  readonly channelConfig: unknown;
43
- readonly sinks: ReadonlyArray<SinkConfig>;
44
- readonly isBoundary: boolean;
45
38
  summaryOf(fn: FunctionInfo): Summary<V>;
46
39
  resolveCall(call: ts.CallExpression | ts.NewExpression): CalleeResolution;
47
40
  resolveCallFor(channel: string, call: ts.CallExpression | ts.NewExpression): CalleeResolution;
48
41
  peerSummaryValue(channel: string, fnId: string): unknown;
49
- pathToBoundary(fn: FunctionInfo): ReadonlyArray<FunctionInfo>;
50
42
  roots(): ReadonlyArray<FunctionInfo>;
51
43
  };
52
44
  type Channel<V> = {
@@ -86,49 +78,28 @@ type Diagnostic = {
86
78
  readonly related: ReadonlyArray<DiagnosticRelated>;
87
79
  readonly fixes?: ReadonlyArray<DiagnosticFix>;
88
80
  };
89
- type HandlerBoundary = {
90
- readonly callee: string;
91
- readonly callbackArgs: ReadonlyArray<number>;
92
- };
93
- type SinkConfig = {
94
- readonly callee: string;
95
- readonly absorbs: ReadonlyArray<string> | undefined;
96
- };
97
81
  type ChannelConfig = {
98
- readonly enabled: boolean;
99
- readonly dispatch: Dispatch;
82
+ readonly severity: Severity;
100
83
  readonly options: unknown;
101
84
  };
102
85
  type AnalyzeConfig = {
103
86
  readonly projectRoot: string;
104
87
  readonly tsconfigPath: string;
105
- readonly entryPoints: ReadonlyArray<string>;
106
- readonly handlerBoundaries: ReadonlyArray<HandlerBoundary>;
107
- readonly sinks: ReadonlyArray<SinkConfig>;
108
- readonly presets: ReadonlyArray<string>;
109
- readonly overlays: ReadonlyArray<string>;
110
88
  readonly channels: Readonly<Record<string, ChannelConfig>>;
111
- readonly failOnFindings: boolean;
112
- readonly severity: 'error' | 'warning';
113
89
  };
114
90
  type OverlaySet = {
115
91
  lookup(symbol: ts.Symbol, channel: string): OverlayLookup | undefined;
116
92
  };
117
93
  type CallGraph = {
118
94
  reachedFunctions(): ReadonlyArray<FunctionInfo>;
119
- boundaries(): ReadonlySet<string>;
120
95
  calleesOf(fn: FunctionInfo): ReadonlyArray<FunctionInfo>;
121
96
  resolveCall(call: ts.CallExpression | ts.NewExpression, channel: string): CalleeResolution;
122
- resolveFunctionValue(expr: ts.Expression): ReadonlyArray<FunctionInfo>;
123
97
  };
124
98
  type SummaryStore<V> = {
125
99
  get(id: string): Summary<V>;
126
100
  };
127
101
  type Analysis = {
128
- readonly program: ts.Program;
129
102
  readonly checker: ts.TypeChecker;
130
- readonly config: AnalyzeConfig;
131
- readonly overlays: OverlaySet;
132
103
  readonly graph: CallGraph;
133
104
  };
134
- export { type Analysis, type AnalyzeConfig, type CallGraph, type CalleeResolution, type Channel, type ChannelConfig, type DiagnoseContext, type Diagnostic, type DiagnosticEdit, type DiagnosticFix, type DiagnosticRelated, type FunctionInfo, type HandlerBoundary, type OverlayLookup, type OverlaySet, type SinkConfig, type SourceLocation, type Summary, type SummaryStore, type TransferContext };
105
+ export { type Analysis, type AnalyzeConfig, type CallGraph, type CalleeResolution, type Channel, type ChannelConfig, type DiagnoseContext, type Diagnostic, type DiagnosticEdit, type DiagnosticFix, type DiagnosticRelated, type FunctionInfo, type OverlayLookup, type OverlaySet, type SourceLocation, type Summary, type SummaryStore, type TransferContext };
@@ -5,7 +5,7 @@
5
5
  {
6
6
  "overlay": {
7
7
  "async": {
8
- "lib.dom": {
8
+ "global": {
9
9
  "fetch": { "cancellable": true }
10
10
  }
11
11
  }