checkPairs
uses node:path
Check changed definitions: old and new versions of each in one program, compared lint by lint.
import type { Codebase } from "#codebase/tcmts/cli/codebase"; import { compare } from "#codebase/tcmts/cli/semver_checks"; import type { Finding, Pair } from "#codebase/tcmts/cli/semver_checks"; import { exportId } from "#codebase/tcmts/core/hash"; import { createProgram } from "#codebase/tcmts/core/program"; import { materialize, moduleFile } from "#codebase/tcmts/loader"; import path_1 from "node:path"; import { isImportDeclaration as ts_isImportDeclaration, isNamedImports as ts_isNamedImports } from "typescript/ast"; import { SymbolFlags as ts_SymbolFlags } from "typescript/sync"; import type { Symbol as ts_Symbol } from "typescript/sync"; export function checkPairs(cb: Codebase, pairs: Pair[]): Finding[] { if (!pairs.length) return []; const src = cb.source(); materialize( pairs.flatMap((p) => [p.old.hash, p.new.hash]), src, cb.lay, ); const imports = pairs.flatMap((p, i) => (["old", "new"] as const).map((side) => { const rec = p[side]; return `import ${rec.kind === "type" ? "type " : ""}{ ${exportId(rec.hash)} as ${side === "old" ? "O" : "N"}${i} } from "./${moduleFile(rec.componentHash, src)}";`; }), ); // a file in the cache importing both versions of each (never written: the compiler reads it from memory) const file = path_1.join(cb.lay.cacheDir, `_semver_${process.pid}.ts`); { const { program, checker } = createProgram( [file], { ...cb.recheckOptions(undefined), noEmit: true }, new Map([[file, imports.join("\n") + "\nexport {};\n"]]), ); const sf = program.getSourceFile(file)!; const symbols = new Map<string, ts_Symbol>(); for (const st of sf.statements) { if ( !ts_isImportDeclaration(st) || !st.importClause?.namedBindings || !ts_isNamedImports(st.importClause.namedBindings) ) continue; for (const el of st.importClause.namedBindings.elements) { const s = checker.getSymbolAtLocation(el.name); if (s) symbols.set( el.name.text, s.flags & ts_SymbolFlags.Alias ? checker.getAliasedSymbol(s) : s, ); } } return pairs.flatMap((p, i) => { const [o, n] = [symbols.get(`O${i}`), symbols.get(`N${i}`)]; if (!o || !n) return [ { lint: "type_changed", path: p.path, detail: "couldn't be compared" } satisfies Finding, ]; return compare(checker, p, o, n); }); } }
uses
- tcmts.cli.codebase.Codebase
- tcmts.cli.semver_checks.Finding
- tcmts.cli.semver_checks.Pair
- tcmts.cli.semver_checks.compare
- tcmts.core.hash.exportId
- tcmts.core.program.createProgram
- tcmts.loader.materialize
- tcmts.loader.moduleFile