bumpcheck 0.0.0-stage → 0.1.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 +15 -0
- package/README.md +199 -2
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +127 -0
- package/dist/cli.js.map +1 -0
- package/dist/git.d.ts +33 -0
- package/dist/git.js +94 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/npm/analyze.d.ts +18 -0
- package/dist/npm/analyze.js +190 -0
- package/dist/npm/analyze.js.map +1 -0
- package/dist/npm/diagnostics.d.ts +21 -0
- package/dist/npm/diagnostics.js +269 -0
- package/dist/npm/diagnostics.js.map +1 -0
- package/dist/npm/exports.d.ts +22 -0
- package/dist/npm/exports.js +101 -0
- package/dist/npm/exports.js.map +1 -0
- package/dist/npm/imports.d.ts +29 -0
- package/dist/npm/imports.js +215 -0
- package/dist/npm/imports.js.map +1 -0
- package/dist/npm/program.d.ts +32 -0
- package/dist/npm/program.js +187 -0
- package/dist/npm/program.js.map +1 -0
- package/dist/registry/provider.d.ts +50 -0
- package/dist/registry/provider.js +164 -0
- package/dist/registry/provider.js.map +1 -0
- package/dist/report/render.d.ts +5 -0
- package/dist/report/render.js +227 -0
- package/dist/report/render.js.map +1 -0
- package/dist/types.d.ts +99 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +51 -4
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { readFileSync, realpathSync } from 'node:fs';
|
|
3
|
+
import ts from 'typescript';
|
|
4
|
+
import { SCHEMA_VERSION } from '../types.js';
|
|
5
|
+
import { buildProgram, isInside, loadRepoConfig, walkSources } from './program.js';
|
|
6
|
+
import { relPosix } from './imports.js';
|
|
7
|
+
import { scanImports } from './imports.js';
|
|
8
|
+
import { getModuleExports, namespaceMembers } from './exports.js';
|
|
9
|
+
import { collectDiagnostics, diffDiagnostics } from './diagnostics.js';
|
|
10
|
+
/**
|
|
11
|
+
* For namespaces, say which members came and went instead of dumping two
|
|
12
|
+
* member lists. Everything else is shown as the normalized declaration.
|
|
13
|
+
*/
|
|
14
|
+
function describeChange(before, after) {
|
|
15
|
+
const a = namespaceMembers(before);
|
|
16
|
+
const b = namespaceMembers(after);
|
|
17
|
+
if (!a || !b)
|
|
18
|
+
return { before, after };
|
|
19
|
+
const removed = [...a.keys()].filter((n) => !b.has(n));
|
|
20
|
+
const added = [...b.keys()].filter((n) => !a.has(n));
|
|
21
|
+
const changed = [...a.keys()].filter((n) => b.has(n) && a.get(n) !== b.get(n));
|
|
22
|
+
const list = (xs) => (xs.length > 12 ? xs.slice(0, 12).join(', ') + `, +${xs.length - 12} more` : xs.join(', '));
|
|
23
|
+
const parts = [`namespace with ${b.size} members`];
|
|
24
|
+
if (removed.length)
|
|
25
|
+
parts.push(`removed: ${list(removed)}`);
|
|
26
|
+
if (added.length)
|
|
27
|
+
parts.push(`added: ${list(added)}`);
|
|
28
|
+
if (changed.length)
|
|
29
|
+
parts.push(`changed: ${list(changed)}`);
|
|
30
|
+
return { before: `namespace with ${a.size} members`, after: parts.join('; ') };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The whole pipeline:
|
|
34
|
+
* 1. materialize both versions,
|
|
35
|
+
* 2. build one program per version with imports redirected,
|
|
36
|
+
* 3. collect what the repo imports,
|
|
37
|
+
* 4. compare each imported symbol's declaration,
|
|
38
|
+
* 5. diff the type errors; new-only errors are the breaks.
|
|
39
|
+
*/
|
|
40
|
+
export async function analyzeNpm(opts) {
|
|
41
|
+
const started = Date.now();
|
|
42
|
+
const repoRoot = path.resolve(opts.repoRoot);
|
|
43
|
+
// TypeScript reports node_modules files by real path, so compare against
|
|
44
|
+
// real paths too (macOS tmp dirs live behind a symlink, for example).
|
|
45
|
+
const overlayFrom = realpathSync(await opts.provider.ensure(opts.pkg, opts.from));
|
|
46
|
+
const overlayTo = opts.to === opts.from ? overlayFrom : realpathSync(await opts.provider.ensure(opts.pkg, opts.to));
|
|
47
|
+
const config = loadRepoConfig(repoRoot);
|
|
48
|
+
const before = buildProgram(repoRoot, config, { pkg: opts.pkg, overlay: overlayFrom });
|
|
49
|
+
const after = buildProgram(repoRoot, config, { pkg: opts.pkg, overlay: overlayTo });
|
|
50
|
+
// Imports are a property of the repo, not of the version, so either
|
|
51
|
+
// program would do; the "after" program keeps attribution consistent.
|
|
52
|
+
const scan = scanImports(repoRoot, after, opts.pkg, overlayTo);
|
|
53
|
+
// Breaks can surface in files that never import the package, when a type
|
|
54
|
+
// from it flows through another module. So every repo source file is
|
|
55
|
+
// checked; the differential keeps unrelated errors out.
|
|
56
|
+
const absoluteFiles = after.program
|
|
57
|
+
.getSourceFiles()
|
|
58
|
+
.filter((sf) => !sf.isDeclarationFile && isInside(repoRoot, sf.fileName) && !sf.fileName.includes(`${path.sep}node_modules${path.sep}`))
|
|
59
|
+
.map((sf) => sf.fileName);
|
|
60
|
+
const specifiers = [...new Set(scan.refs.map((r) => r.specifier))];
|
|
61
|
+
const exportsBefore = new Map();
|
|
62
|
+
const exportsAfter = new Map();
|
|
63
|
+
for (const spec of specifiers) {
|
|
64
|
+
exportsBefore.set(spec, getModuleExports(before, spec));
|
|
65
|
+
exportsAfter.set(spec, getModuleExports(after, spec));
|
|
66
|
+
}
|
|
67
|
+
// "Untyped" means every imported entry resolves to JavaScript with no
|
|
68
|
+
// declarations. A specifier that does not resolve at all is a different
|
|
69
|
+
// fact: the diagnostics diff reports it as a missing module. When nothing
|
|
70
|
+
// imports the package, neither claim applies.
|
|
71
|
+
const afterEntries = [...exportsAfter.values()];
|
|
72
|
+
const untyped = afterEntries.length > 0 && afterEntries.every((e) => e.resolved && !e.typed);
|
|
73
|
+
const unanalyzed = [...scan.unanalyzed, ...config.warnings.map((reason) => ({ reason, locations: [] }))];
|
|
74
|
+
const imports = scan.refs.map((ref) => {
|
|
75
|
+
const b = exportsBefore.get(ref.specifier);
|
|
76
|
+
const a = exportsAfter.get(ref.specifier);
|
|
77
|
+
const sigBefore = b.exports.get(ref.name);
|
|
78
|
+
const sigAfter = a.exports.get(ref.name);
|
|
79
|
+
if (!a.typed || !b.typed) {
|
|
80
|
+
return { ...ref, status: 'unknown' };
|
|
81
|
+
}
|
|
82
|
+
if (sigBefore === undefined && sigAfter === undefined) {
|
|
83
|
+
// Neither version declares it. Likely a typo in the repo or a symbol
|
|
84
|
+
// only present at runtime. Both runs report the same error, which cancels.
|
|
85
|
+
return { ...ref, status: 'unknown' };
|
|
86
|
+
}
|
|
87
|
+
if (sigAfter === undefined) {
|
|
88
|
+
return { ...ref, status: 'removed', change: { before: sigBefore } };
|
|
89
|
+
}
|
|
90
|
+
if (sigBefore === undefined) {
|
|
91
|
+
// New in the target version yet already imported: the repo must have
|
|
92
|
+
// been compiling against something else. Report honestly as unknown.
|
|
93
|
+
return { ...ref, status: 'unknown', change: { after: sigAfter } };
|
|
94
|
+
}
|
|
95
|
+
if (sigBefore === sigAfter)
|
|
96
|
+
return { ...ref, status: 'unchanged' };
|
|
97
|
+
return { ...ref, status: 'changed', change: describeChange(sigBefore, sigAfter) };
|
|
98
|
+
});
|
|
99
|
+
// Source files outside the tsconfig's file set are not type checked by
|
|
100
|
+
// the repo's own tsc either, but a test suite may still load them. Say so
|
|
101
|
+
// rather than let "nothing imports X" cover files we never looked at.
|
|
102
|
+
if (config.source === 'tsconfig') {
|
|
103
|
+
const inProgram = new Set(after.program.getSourceFiles().map((sf) => sf.fileName));
|
|
104
|
+
const pattern = new RegExp(`(from\\s*|require\\s*\\(\\s*|import\\s*\\(\\s*)['"]${opts.pkg.replace(/[.*+?^${}()|[\]\\/]/g, '\\$&')}(/[^'"]*)?['"]`);
|
|
105
|
+
const outside = walkSources(repoRoot).filter((f) => !inProgram.has(f) && pattern.test(readFileSync(f, 'utf8')));
|
|
106
|
+
if (outside.length > 0) {
|
|
107
|
+
unanalyzed.push({
|
|
108
|
+
reason: `${outside.length} file${outside.length === 1 ? '' : 's'} import${outside.length === 1 ? 's' : ''} "${opts.pkg}" but ${outside.length === 1 ? 'is' : 'are'} outside tsconfig.json, so neither tsc nor bumpcheck checks ${outside.length === 1 ? 'it' : 'them'}`,
|
|
109
|
+
locations: outside.map((f) => ({ file: relPosix(repoRoot, f), line: 1, column: 1 })),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (untyped) {
|
|
114
|
+
unanalyzed.push({
|
|
115
|
+
reason: `${opts.pkg}@${opts.to} ships no type declarations and none were found on DefinitelyTyped; nothing can be proven`,
|
|
116
|
+
locations: [],
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
for (const spec of specifiers) {
|
|
120
|
+
const a = exportsAfter.get(spec);
|
|
121
|
+
const b = exportsBefore.get(spec);
|
|
122
|
+
if (b.resolved && !a.resolved) {
|
|
123
|
+
unanalyzed.push({
|
|
124
|
+
reason: `"${spec}" does not resolve in ${opts.to} under this repo's module resolution; see breaks`,
|
|
125
|
+
locations: scan.refs.filter((r) => r.specifier === spec).flatMap((r) => r.locations),
|
|
126
|
+
});
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (a.resolved && !a.typed && !untyped) {
|
|
130
|
+
unanalyzed.push({
|
|
131
|
+
reason: `"${spec}" resolves to JavaScript without declarations in ${opts.to}`,
|
|
132
|
+
locations: scan.refs.filter((r) => r.specifier === spec).flatMap((r) => r.locations),
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const diagnosticsBefore = collectDiagnostics(before, absoluteFiles);
|
|
137
|
+
const breaks = untyped
|
|
138
|
+
? []
|
|
139
|
+
: diffDiagnostics(repoRoot, diagnosticsBefore, collectDiagnostics(after, absoluteFiles), scan, after, overlayTo);
|
|
140
|
+
// Unresolved modules in the baseline mean other dependencies are missing
|
|
141
|
+
// from this checkout. Their types can carry the package's types, so
|
|
142
|
+
// breaks through them cannot be seen. Say so.
|
|
143
|
+
const unresolved = new Set();
|
|
144
|
+
for (const { diagnostic } of diagnosticsBefore.values()) {
|
|
145
|
+
if (diagnostic.code !== 2307)
|
|
146
|
+
continue;
|
|
147
|
+
const m = /Cannot find module '([^']+)'/.exec(ts.flattenDiagnosticMessageText(diagnostic.messageText, ' '));
|
|
148
|
+
if (m && !m[1].startsWith('.'))
|
|
149
|
+
unresolved.add(m[1]);
|
|
150
|
+
}
|
|
151
|
+
if (unresolved.size > 0) {
|
|
152
|
+
const names = [...unresolved].sort();
|
|
153
|
+
const shown = names.length > 5 ? names.slice(0, 5).join(', ') + `, +${names.length - 5} more` : names.join(', ');
|
|
154
|
+
unanalyzed.push({
|
|
155
|
+
reason: `${names.length} other package${names.length === 1 ? '' : 's'} could not be resolved (${shown}); install dependencies for full coverage`,
|
|
156
|
+
locations: [],
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
// A changed declaration with a break attributed to it is breaking, not
|
|
160
|
+
// merely changed. Removed symbols keep their own status.
|
|
161
|
+
const brokenSymbols = new Set(breaks.map((b) => b.symbol).filter((s) => !!s));
|
|
162
|
+
for (const imp of imports) {
|
|
163
|
+
if (imp.status === 'changed' && brokenSymbols.has(imp.name))
|
|
164
|
+
imp.status = 'breaking';
|
|
165
|
+
}
|
|
166
|
+
const summary = {
|
|
167
|
+
importedSymbols: imports.length,
|
|
168
|
+
unchanged: imports.filter((i) => i.status === 'unchanged').length,
|
|
169
|
+
changed: imports.filter((i) => i.status === 'changed').length,
|
|
170
|
+
breaking: imports.filter((i) => i.status === 'breaking').length,
|
|
171
|
+
removed: imports.filter((i) => i.status === 'removed').length,
|
|
172
|
+
unknown: imports.filter((i) => i.status === 'unknown').length,
|
|
173
|
+
breaks: breaks.length,
|
|
174
|
+
unanalyzed: unanalyzed.reduce((n, u) => n + Math.max(1, u.locations.length), 0),
|
|
175
|
+
};
|
|
176
|
+
return {
|
|
177
|
+
schemaVersion: SCHEMA_VERSION,
|
|
178
|
+
ecosystem: 'npm',
|
|
179
|
+
package: opts.pkg,
|
|
180
|
+
from: opts.from,
|
|
181
|
+
to: opts.to,
|
|
182
|
+
files: scan.files,
|
|
183
|
+
imports,
|
|
184
|
+
breaks,
|
|
185
|
+
unanalyzed,
|
|
186
|
+
summary,
|
|
187
|
+
meta: { typescript: ts.version, durationMs: Date.now() - started, untyped },
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=analyze.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/npm/analyze.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AACnF,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAsB,MAAM,cAAc,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAUvE;;;GAGG;AACH,SAAS,cAAc,CAAC,MAAc,EAAE,KAAa;IACnD,MAAM,CAAC,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,CAAC,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/E,MAAM,IAAI,GAAG,CAAC,EAAY,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,EAAE,CAAC,MAAM,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3H,MAAM,KAAK,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC;IACnD,IAAI,OAAO,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5D,IAAI,KAAK,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACtD,IAAI,OAAO,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5D,OAAO,EAAE,MAAM,EAAE,kBAAkB,CAAC,CAAC,IAAI,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACjF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAoB;IACnD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7C,yEAAyE;IACzE,sEAAsE;IACtE,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAClF,MAAM,SAAS,GAAG,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAEpH,MAAM,MAAM,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;IACvF,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;IAEpF,oEAAoE;IACpE,sEAAsE;IACtE,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAE/D,yEAAyE;IACzE,qEAAqE;IACrE,wDAAwD;IACxD,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO;SAChC,cAAc,EAAE;SAChB,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,iBAAiB,IAAI,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,GAAG,eAAe,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;SACvI,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;IAE5B,MAAM,UAAU,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACnE,MAAM,aAAa,GAAG,IAAI,GAAG,EAAyB,CAAC;IACvD,MAAM,YAAY,GAAG,IAAI,GAAG,EAAyB,CAAC;IACtD,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;QACxD,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,sEAAsE;IACtE,wEAAwE;IACxE,0EAA0E;IAC1E,8CAA8C;IAC9C,MAAM,YAAY,GAAG,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAE7F,MAAM,UAAU,GAAiB,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACvH,MAAM,OAAO,GAAqB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACtD,MAAM,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAE,CAAC;QAC5C,MAAM,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,QAAQ,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEzC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;YACzB,OAAO,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QACvC,CAAC;QACD,IAAI,SAAS,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YACtD,qEAAqE;YACrE,2EAA2E;YAC3E,OAAO,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;QACvC,CAAC;QACD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,SAAU,EAAE,EAAE,CAAC;QACvE,CAAC;QACD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,qEAAqE;YACrE,qEAAqE;YACrE,OAAO,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC;QACpE,CAAC;QACD,IAAI,SAAS,KAAK,QAAQ;YAAE,OAAO,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QACnE,OAAO,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,CAAC;IACpF,CAAC,CAAC,CAAC;IAEH,uEAAuE;IACvE,0EAA0E;IAC1E,sEAAsE;IACtE,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnF,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,sDAAsD,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,sBAAsB,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;QACnJ,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QAChH,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,UAAU,CAAC,IAAI,CAAC;gBACd,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,QAAQ,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,UAAU,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,GAAG,SAAS,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,+DAA+D,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE;gBACvQ,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;aACrF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,UAAU,CAAC,IAAI,CAAC;YACd,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,2FAA2F;YACzH,SAAS,EAAE,EAAE;SACd,CAAC,CAAC;IACL,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;QAClC,MAAM,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;QACnC,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC9B,UAAU,CAAC,IAAI,CAAC;gBACd,MAAM,EAAE,IAAI,IAAI,yBAAyB,IAAI,CAAC,EAAE,kDAAkD;gBAClG,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;aACrF,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,UAAU,CAAC,IAAI,CAAC;gBACd,MAAM,EAAE,IAAI,IAAI,oDAAoD,IAAI,CAAC,EAAE,EAAE;gBAC7E,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;aACrF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,iBAAiB,GAAG,kBAAkB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,OAAO;QACpB,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,eAAe,CAAC,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,CAAC,KAAK,EAAE,aAAa,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IAEnH,yEAAyE;IACzE,oEAAoE;IACpE,8CAA8C;IAC9C,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IACrC,KAAK,MAAM,EAAE,UAAU,EAAE,IAAI,iBAAiB,CAAC,MAAM,EAAE,EAAE,CAAC;QACxD,IAAI,UAAU,CAAC,IAAI,KAAK,IAAI;YAAE,SAAS;QACvC,MAAM,CAAC,GAAG,8BAA8B,CAAC,IAAI,CAAC,EAAE,CAAC,4BAA4B,CAAC,UAAU,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;QAC5G,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,KAAK,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjH,UAAU,CAAC,IAAI,CAAC;YACd,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,iBAAiB,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,2BAA2B,KAAK,2CAA2C;YAChJ,SAAS,EAAE,EAAE;SACd,CAAC,CAAC;IACL,CAAC;IAED,uEAAuE;IACvE,yDAAyD;IACzD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3F,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,GAAG,CAAC,MAAM,GAAG,UAAU,CAAC;IACvF,CAAC;IAED,MAAM,OAAO,GAAY;QACvB,eAAe,EAAE,OAAO,CAAC,MAAM;QAC/B,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM;QACjE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM;QAC7D,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,MAAM;QAC/D,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM;QAC7D,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM;QAC7D,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;KAChF,CAAC;IAEF,OAAO;QACL,aAAa,EAAE,cAAc;QAC7B,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,IAAI,CAAC,GAAG;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,OAAO;QACP,MAAM;QACN,UAAU;QACV,OAAO;QACP,IAAI,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE;KAC5E,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import type { Break } from '../types.js';
|
|
3
|
+
import { type BuiltProgram } from './program.js';
|
|
4
|
+
import { type ImportScan } from './imports.js';
|
|
5
|
+
interface Keyed {
|
|
6
|
+
key: string;
|
|
7
|
+
diagnostic: ts.DiagnosticWithLocation;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Semantic diagnostics for the given files, keyed so two runs over the same
|
|
11
|
+
* sources can be diffed. Position is part of the key: the sources are
|
|
12
|
+
* identical in both runs, so a shift cannot occur.
|
|
13
|
+
*/
|
|
14
|
+
export declare function collectDiagnostics(built: BuiltProgram, absoluteFiles: string[]): Map<string, Keyed>;
|
|
15
|
+
/**
|
|
16
|
+
* Errors present with the new version and absent with the old one are the
|
|
17
|
+
* breaks. Everything else cancels out, including the repo's pre-existing
|
|
18
|
+
* type errors and any noise from unresolved unrelated packages.
|
|
19
|
+
*/
|
|
20
|
+
export declare function diffDiagnostics(repoRoot: string, before: Map<string, Keyed>, after: Map<string, Keyed>, scan: ImportScan, built: BuiltProgram, overlay: string): Break[];
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { isInside } from './program.js';
|
|
3
|
+
import { toLocation } from './imports.js';
|
|
4
|
+
function flatten(d) {
|
|
5
|
+
return ts.flattenDiagnosticMessageText(d.messageText, ' ').replace(/\s+/g, ' ').trim();
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Semantic diagnostics for the given files, keyed so two runs over the same
|
|
9
|
+
* sources can be diffed. Position is part of the key: the sources are
|
|
10
|
+
* identical in both runs, so a shift cannot occur.
|
|
11
|
+
*/
|
|
12
|
+
export function collectDiagnostics(built, absoluteFiles) {
|
|
13
|
+
const out = new Map();
|
|
14
|
+
for (const file of absoluteFiles) {
|
|
15
|
+
const sf = built.program.getSourceFile(file);
|
|
16
|
+
if (!sf)
|
|
17
|
+
continue;
|
|
18
|
+
for (const d of built.program.getSemanticDiagnostics(sf)) {
|
|
19
|
+
if (d.file === undefined || d.start === undefined)
|
|
20
|
+
continue;
|
|
21
|
+
if (d.category !== ts.DiagnosticCategory.Error)
|
|
22
|
+
continue;
|
|
23
|
+
const key = `${d.file.fileName}\u0000${d.code}\u0000${d.start}\u0000${flatten(d)}`;
|
|
24
|
+
out.set(key, { key, diagnostic: d });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Errors TypeScript emits as a consequence of another error in the same
|
|
31
|
+
* statement, such as "implicitly has an 'any' type" once a property lookup
|
|
32
|
+
* failed. Reported only when they stand alone.
|
|
33
|
+
*/
|
|
34
|
+
const CASCADE_CODES = new Set([7005, 7006, 7031, 7034, 7053]);
|
|
35
|
+
const KIND_BY_CODE = {
|
|
36
|
+
1192: 'removed-export', // Module has no default export
|
|
37
|
+
2305: 'removed-export', // Module has no exported member
|
|
38
|
+
2614: 'removed-export', // ... has no exported member; did you mean to use import x from?
|
|
39
|
+
2724: 'removed-export', // ... has no exported member named; did you mean?
|
|
40
|
+
2307: 'missing-module',
|
|
41
|
+
2792: 'missing-module',
|
|
42
|
+
2554: 'arity',
|
|
43
|
+
2555: 'arity',
|
|
44
|
+
2556: 'arity',
|
|
45
|
+
2557: 'arity',
|
|
46
|
+
2322: 'type-mismatch',
|
|
47
|
+
2345: 'type-mismatch',
|
|
48
|
+
2353: 'type-mismatch',
|
|
49
|
+
2559: 'type-mismatch',
|
|
50
|
+
2739: 'type-mismatch',
|
|
51
|
+
2740: 'type-mismatch',
|
|
52
|
+
2741: 'type-mismatch',
|
|
53
|
+
2769: 'type-mismatch',
|
|
54
|
+
2339: 'missing-member',
|
|
55
|
+
2551: 'missing-member',
|
|
56
|
+
};
|
|
57
|
+
function findNodeAt(sf, pos) {
|
|
58
|
+
let best = sf;
|
|
59
|
+
const visit = (node) => {
|
|
60
|
+
if (pos >= node.getStart(sf) && pos < node.getEnd()) {
|
|
61
|
+
best = node;
|
|
62
|
+
ts.forEachChild(node, visit);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
ts.forEachChild(sf, visit);
|
|
66
|
+
return best;
|
|
67
|
+
}
|
|
68
|
+
function enclosingStatement(node) {
|
|
69
|
+
let n = node;
|
|
70
|
+
while (n.parent && !ts.isStatement(n) && !ts.isSourceFile(n.parent))
|
|
71
|
+
n = n.parent;
|
|
72
|
+
return n;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Per file: the package symbol each import binding points at, so a type
|
|
76
|
+
* declared under that symbol can be traced back to the imported name.
|
|
77
|
+
*/
|
|
78
|
+
function importTargets(checker, sf, locals) {
|
|
79
|
+
const out = new Map();
|
|
80
|
+
const visit = (node) => {
|
|
81
|
+
if (ts.isIdentifier(node) && locals.has(node.text)) {
|
|
82
|
+
const parent = node.parent;
|
|
83
|
+
const isBinding = (parent && ts.isImportClause(parent) && parent.name === node) ||
|
|
84
|
+
(parent && ts.isImportSpecifier(parent) && parent.name === node) ||
|
|
85
|
+
(parent && ts.isBindingElement(parent) && parent.name === node);
|
|
86
|
+
if (isBinding) {
|
|
87
|
+
const sym = checker.getSymbolAtLocation(node);
|
|
88
|
+
if (sym) {
|
|
89
|
+
const target = sym.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(sym) : sym;
|
|
90
|
+
out.set(target, locals.get(node.text).name);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
ts.forEachChild(node, visit);
|
|
95
|
+
};
|
|
96
|
+
visit(sf);
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
function topLevelSymbol(checker, decl) {
|
|
100
|
+
let n = decl;
|
|
101
|
+
while (n.parent && !ts.isSourceFile(n.parent))
|
|
102
|
+
n = n.parent;
|
|
103
|
+
if (ts.isVariableStatement(n))
|
|
104
|
+
n = n.declarationList.declarations[0] ?? n;
|
|
105
|
+
const name = n.name;
|
|
106
|
+
return name ? checker.getSymbolAtLocation(name) : undefined;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Attributes a diagnostic to one of the file's imported names. Three
|
|
110
|
+
* strategies, in order of certainty; returns nothing rather than guess.
|
|
111
|
+
*/
|
|
112
|
+
function attribute(built, overlay, sf, d, locals, targets, message) {
|
|
113
|
+
const fromMessage = /has no exported member (?:named )?'([^']+)'/.exec(message);
|
|
114
|
+
if (fromMessage)
|
|
115
|
+
return { symbol: fromMessage[1], attribution: 'message' };
|
|
116
|
+
const { checker } = built;
|
|
117
|
+
const statement = enclosingStatement(findNodeAt(sf, d.start));
|
|
118
|
+
// Walk outward from the error. The innermost node that mentions an import
|
|
119
|
+
// binding wins, so `a(x) + b(y)` attributes to the call that failed.
|
|
120
|
+
if (locals && locals.size > 0) {
|
|
121
|
+
for (let node = findNodeAt(sf, d.start);; node = node.parent) {
|
|
122
|
+
const viaBinding = findBinding(node, locals);
|
|
123
|
+
if (viaBinding)
|
|
124
|
+
return { symbol: viaBinding, attribution: 'binding' };
|
|
125
|
+
if (node === statement)
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Same walk, but for values whose type is declared under one of the imports.
|
|
130
|
+
if (!targets || targets.size === 0)
|
|
131
|
+
return undefined;
|
|
132
|
+
for (let node = findNodeAt(sf, d.start);; node = node.parent) {
|
|
133
|
+
const viaType = findType(node, checker, overlay, targets);
|
|
134
|
+
if (viaType)
|
|
135
|
+
return { symbol: viaType, attribution: 'type' };
|
|
136
|
+
if (node === statement)
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
function findBinding(root, locals) {
|
|
142
|
+
let found;
|
|
143
|
+
const visit = (n) => {
|
|
144
|
+
if (found)
|
|
145
|
+
return;
|
|
146
|
+
if (ts.isIdentifier(n) && locals.has(n.text))
|
|
147
|
+
found = locals.get(n.text).name;
|
|
148
|
+
else
|
|
149
|
+
ts.forEachChild(n, visit);
|
|
150
|
+
};
|
|
151
|
+
visit(root);
|
|
152
|
+
return found;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Members of namespace-like imports (`import { z } from 'zod'`), so a type
|
|
156
|
+
* declared as `ZodError` can be traced to the `z` the file actually imports.
|
|
157
|
+
*/
|
|
158
|
+
function namespaceMembers(checker, targets) {
|
|
159
|
+
const out = new Map();
|
|
160
|
+
for (const [sym, name] of targets) {
|
|
161
|
+
const isModule = sym.flags & (ts.SymbolFlags.ValueModule | ts.SymbolFlags.NamespaceModule) ||
|
|
162
|
+
(sym.declarations ?? []).some((d) => ts.isSourceFile(d) || ts.isModuleDeclaration(d));
|
|
163
|
+
if (!isModule)
|
|
164
|
+
continue;
|
|
165
|
+
for (const member of checker.getExportsOfModule(sym)) {
|
|
166
|
+
const resolved = member.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(member) : member;
|
|
167
|
+
if (!out.has(resolved))
|
|
168
|
+
out.set(resolved, name);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return out;
|
|
172
|
+
}
|
|
173
|
+
function findType(root, checker, overlay, targets) {
|
|
174
|
+
let found;
|
|
175
|
+
let members;
|
|
176
|
+
const visit = (n) => {
|
|
177
|
+
if (found)
|
|
178
|
+
return;
|
|
179
|
+
if (ts.isExpression(n) || ts.isIdentifier(n)) {
|
|
180
|
+
const type = checker.getTypeAtLocation(n);
|
|
181
|
+
for (const sym of [type.aliasSymbol, type.symbol]) {
|
|
182
|
+
if (!sym)
|
|
183
|
+
continue;
|
|
184
|
+
for (const decl of sym.declarations ?? []) {
|
|
185
|
+
if (!isInside(overlay, decl.getSourceFile().fileName))
|
|
186
|
+
continue;
|
|
187
|
+
const top = topLevelSymbol(checker, decl);
|
|
188
|
+
if (!top)
|
|
189
|
+
continue;
|
|
190
|
+
let name = targets.get(top);
|
|
191
|
+
if (!name) {
|
|
192
|
+
members ??= namespaceMembers(checker, targets);
|
|
193
|
+
name = members.get(top);
|
|
194
|
+
}
|
|
195
|
+
if (name) {
|
|
196
|
+
found = name;
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
ts.forEachChild(n, visit);
|
|
203
|
+
};
|
|
204
|
+
visit(root);
|
|
205
|
+
return found;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Errors present with the new version and absent with the old one are the
|
|
209
|
+
* breaks. Everything else cancels out, including the repo's pre-existing
|
|
210
|
+
* type errors and any noise from unresolved unrelated packages.
|
|
211
|
+
*/
|
|
212
|
+
export function diffDiagnostics(repoRoot, before, after, scan, built, overlay) {
|
|
213
|
+
const breaks = [];
|
|
214
|
+
const targetsByFile = new Map();
|
|
215
|
+
// Files that never import the package still get type-based attribution,
|
|
216
|
+
// against everything the repo imports from it anywhere.
|
|
217
|
+
let repoTargets;
|
|
218
|
+
const allTargets = () => {
|
|
219
|
+
if (repoTargets)
|
|
220
|
+
return repoTargets;
|
|
221
|
+
repoTargets = new Map();
|
|
222
|
+
for (const [file, locals] of scan.localNames) {
|
|
223
|
+
const sf = built.program.getSourceFile(file);
|
|
224
|
+
if (!sf)
|
|
225
|
+
continue;
|
|
226
|
+
for (const [sym, name] of importTargets(built.checker, sf, locals)) {
|
|
227
|
+
if (!repoTargets.has(sym))
|
|
228
|
+
repoTargets.set(sym, name);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return repoTargets;
|
|
232
|
+
};
|
|
233
|
+
const fresh = [...after.entries()].filter(([key]) => !before.has(key)).map(([, v]) => v.diagnostic);
|
|
234
|
+
const statementKey = (d) => {
|
|
235
|
+
const st = enclosingStatement(findNodeAt(d.file, d.start));
|
|
236
|
+
return `${d.file.fileName}\u0000${st.getStart(d.file)}`;
|
|
237
|
+
};
|
|
238
|
+
const rootCauses = new Set(fresh.filter((d) => !CASCADE_CODES.has(d.code)).map(statementKey));
|
|
239
|
+
for (const diagnostic of fresh) {
|
|
240
|
+
if (CASCADE_CODES.has(diagnostic.code) && rootCauses.has(statementKey(diagnostic)))
|
|
241
|
+
continue;
|
|
242
|
+
const sf = diagnostic.file;
|
|
243
|
+
const message = flatten(diagnostic);
|
|
244
|
+
const location = toLocation(repoRoot, sf, { getStart: () => diagnostic.start });
|
|
245
|
+
const locals = scan.localNames.get(sf.fileName);
|
|
246
|
+
let targets = targetsByFile.get(sf.fileName);
|
|
247
|
+
if (!targets) {
|
|
248
|
+
targets = locals ? importTargets(built.checker, sf, locals) : allTargets();
|
|
249
|
+
targetsByFile.set(sf.fileName, targets);
|
|
250
|
+
}
|
|
251
|
+
const attributed = attribute(built, overlay, sf, diagnostic, locals, targets, message);
|
|
252
|
+
const b = {
|
|
253
|
+
kind: KIND_BY_CODE[diagnostic.code] ?? 'other',
|
|
254
|
+
location,
|
|
255
|
+
message,
|
|
256
|
+
code: diagnostic.code,
|
|
257
|
+
};
|
|
258
|
+
if (attributed) {
|
|
259
|
+
b.symbol = attributed.symbol;
|
|
260
|
+
if (attributed.attribution)
|
|
261
|
+
b.attribution = attributed.attribution;
|
|
262
|
+
}
|
|
263
|
+
breaks.push(b);
|
|
264
|
+
}
|
|
265
|
+
return breaks.sort((a, b) => a.location.file === b.location.file
|
|
266
|
+
? a.location.line - b.location.line || a.location.column - b.location.column
|
|
267
|
+
: a.location.file.localeCompare(b.location.file));
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/npm/diagnostics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { BuiltProgram } from './program.js';
|
|
2
|
+
export interface ModuleExports {
|
|
3
|
+
/** False when the specifier does not resolve at all in this version. */
|
|
4
|
+
resolved: boolean;
|
|
5
|
+
/** False when it resolves only to JavaScript with no declarations. */
|
|
6
|
+
typed: boolean;
|
|
7
|
+
/** Export name -> normalized declaration text. */
|
|
8
|
+
exports: Map<string, string>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Collapses a declaration to its tokens so formatting and comments do not
|
|
12
|
+
* count as changes. Two declarations with the same tokens are the same API.
|
|
13
|
+
*/
|
|
14
|
+
export declare function normalizeDeclaration(text: string): string;
|
|
15
|
+
export declare const NAMESPACE_PREFIX = "namespace:";
|
|
16
|
+
/** Parses a namespace signature back into member -> member signature. */
|
|
17
|
+
export declare function namespaceMembers(signature: string): Map<string, string> | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Lists the public exports of `specifier` as resolved against the overlay,
|
|
20
|
+
* with a normalized signature per export.
|
|
21
|
+
*/
|
|
22
|
+
export declare function getModuleExports(built: BuiltProgram, specifier: string): ModuleExports;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
/**
|
|
3
|
+
* Collapses a declaration to its tokens so formatting and comments do not
|
|
4
|
+
* count as changes. Two declarations with the same tokens are the same API.
|
|
5
|
+
*/
|
|
6
|
+
export function normalizeDeclaration(text) {
|
|
7
|
+
const scanner = ts.createScanner(ts.ScriptTarget.Latest, true, ts.LanguageVariant.Standard, text);
|
|
8
|
+
const parts = [];
|
|
9
|
+
let kind = scanner.scan();
|
|
10
|
+
while (kind !== ts.SyntaxKind.EndOfFileToken) {
|
|
11
|
+
parts.push(scanner.getTokenText());
|
|
12
|
+
kind = scanner.scan();
|
|
13
|
+
}
|
|
14
|
+
return parts.join(' ');
|
|
15
|
+
}
|
|
16
|
+
const TS_EXTENSIONS = new Set([
|
|
17
|
+
ts.Extension.Ts,
|
|
18
|
+
ts.Extension.Tsx,
|
|
19
|
+
ts.Extension.Dts,
|
|
20
|
+
ts.Extension.Mts,
|
|
21
|
+
ts.Extension.Cts,
|
|
22
|
+
ts.Extension.Dmts,
|
|
23
|
+
ts.Extension.Dcts,
|
|
24
|
+
]);
|
|
25
|
+
export const NAMESPACE_PREFIX = 'namespace:';
|
|
26
|
+
const MEMBER_SEP = '\u0002';
|
|
27
|
+
const SIG_SEP = '\u0001';
|
|
28
|
+
function isModuleLike(sym) {
|
|
29
|
+
if (sym.flags & (ts.SymbolFlags.ValueModule | ts.SymbolFlags.NamespaceModule))
|
|
30
|
+
return true;
|
|
31
|
+
return (sym.declarations ?? []).some((d) => ts.isSourceFile(d) || ts.isModuleDeclaration(d));
|
|
32
|
+
}
|
|
33
|
+
/** Parses a namespace signature back into member -> member signature. */
|
|
34
|
+
export function namespaceMembers(signature) {
|
|
35
|
+
if (!signature.startsWith(NAMESPACE_PREFIX))
|
|
36
|
+
return undefined;
|
|
37
|
+
const out = new Map();
|
|
38
|
+
for (const entry of signature.slice(NAMESPACE_PREFIX.length).split(MEMBER_SEP)) {
|
|
39
|
+
if (!entry)
|
|
40
|
+
continue;
|
|
41
|
+
const i = entry.indexOf(SIG_SEP);
|
|
42
|
+
out.set(i < 0 ? entry : entry.slice(0, i), i < 0 ? '' : entry.slice(i + 1));
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
function symbolSignature(checker, sym, depth = 0) {
|
|
47
|
+
const target = sym.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(sym) : sym;
|
|
48
|
+
if (isModuleLike(target)) {
|
|
49
|
+
// A namespace is its members and their signatures. Nested namespaces
|
|
50
|
+
// one level down are listed by name only, to keep this bounded.
|
|
51
|
+
const members = checker
|
|
52
|
+
.getExportsOfModule(target)
|
|
53
|
+
.map((e) => (depth === 0 ? `${e.name}${SIG_SEP}${symbolSignature(checker, e, depth + 1)}` : e.name))
|
|
54
|
+
.sort();
|
|
55
|
+
return NAMESPACE_PREFIX + members.join(MEMBER_SEP);
|
|
56
|
+
}
|
|
57
|
+
const decls = target.declarations ?? [];
|
|
58
|
+
if (decls.length === 0) {
|
|
59
|
+
// No declaration (e.g. synthesized `export =` members). Fall back to the type.
|
|
60
|
+
return normalizeDeclaration(checker.typeToString(checker.getTypeOfSymbol(target), undefined, ts.TypeFormatFlags.NoTruncation));
|
|
61
|
+
}
|
|
62
|
+
return decls
|
|
63
|
+
.map((d) => normalizeDeclaration(d.getText()))
|
|
64
|
+
.sort()
|
|
65
|
+
.join('\n');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Lists the public exports of `specifier` as resolved against the overlay,
|
|
69
|
+
* with a normalized signature per export.
|
|
70
|
+
*/
|
|
71
|
+
export function getModuleExports(built, specifier) {
|
|
72
|
+
const { program, checker, resolveTarget } = built;
|
|
73
|
+
const resolution = resolveTarget(specifier).resolvedModule;
|
|
74
|
+
if (!resolution)
|
|
75
|
+
return { resolved: false, typed: false, exports: new Map() };
|
|
76
|
+
if (!TS_EXTENSIONS.has(resolution.extension))
|
|
77
|
+
return { resolved: true, typed: false, exports: new Map() };
|
|
78
|
+
const sf = program.getSourceFile(resolution.resolvedFileName);
|
|
79
|
+
if (!sf)
|
|
80
|
+
return { resolved: true, typed: false, exports: new Map() };
|
|
81
|
+
// ES-module declaration files are their own module symbol. Packages like
|
|
82
|
+
// mongoose instead declare an ambient `declare module 'name' { ... }`
|
|
83
|
+
// block, which lives in the checker's ambient module table.
|
|
84
|
+
const moduleSymbol = checker.getSymbolAtLocation(sf) ?? checker.getAmbientModules().find((m) => m.name === JSON.stringify(specifier));
|
|
85
|
+
if (!moduleSymbol)
|
|
86
|
+
return { resolved: true, typed: false, exports: new Map() };
|
|
87
|
+
const exports = new Map();
|
|
88
|
+
for (const sym of checker.getExportsOfModule(moduleSymbol)) {
|
|
89
|
+
exports.set(sym.name, symbolSignature(checker, sym));
|
|
90
|
+
}
|
|
91
|
+
// `import x from 'pkg'` compiles against a module with no default export
|
|
92
|
+
// when synthetic defaults are allowed; the default is then the module
|
|
93
|
+
// itself. Mirror that so the import is checked instead of marked unknown.
|
|
94
|
+
const options = program.getCompilerOptions();
|
|
95
|
+
const synthetic = options.allowSyntheticDefaultImports ?? options.esModuleInterop ?? false;
|
|
96
|
+
if (!exports.has('default') && synthetic) {
|
|
97
|
+
exports.set('default', symbolSignature(checker, moduleSymbol));
|
|
98
|
+
}
|
|
99
|
+
return { resolved: true, typed: true, exports };
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=exports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exports.js","sourceRoot":"","sources":["../../src/npm/exports.ts"],"names":[],"mappings":"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"}
|