testCyclesAreWarnedAbout
Saving says when it makes a cycle worth avoiding: one only types make (an interface breaks it), or a big one of code calling itself; two functions recursing together, and a cycle saved again as it was, aren't mentioned
import { okIn, tempDir } from "#codebase/tcmts/cli/test/e2e/harness"; import assert from "node:assert/strict"; import fs from "node:fs"; import path from "node:path"; export const testCyclesAreWarnedAbout = () => { const dir = tempDir("cycle warnings"); const tcm = (...args: string[]) => okIn(dir, ...args); tcm("init"); const save = (code: string, mode = "add") => { fs.writeFileSync(path.join(dir, "scratch.ts"), `// tcm: namespace lib\n${code}`); return tcm(mode); }; const pair = save( `export const isEven = (n: number): boolean => (n === 0 ? true : isOdd(n - 1));\nexport const isOdd = (n: number): boolean => (n === 0 ? false : isEven(n - 1));\n`, ); assert.doesNotMatch(pair, /warning: .*cycle/, "two functions recursing together are fine"); const typed = save( `export class Shop {\n name = "corner";\n describe(): string { return describeShop(this); }\n}\nexport const describeShop = (s: Shop): string => "the " + s.name + " shop";\n`, ); assert.match(typed, /warning: lib\.Shop, lib\.describeShop became one cycle \(2 definitions\)/); assert.match( typed, /only because types name each other \(lib\.describeShop's types name lib\.Shop\)/, ); const big = save( `export const a = (n: number): number => (n > 0 ? b(n - 1) : 0);\nexport const b = (n: number): number => (n > 0 ? c(n - 1) : 1);\nexport const c = (n: number): number => (n > 0 ? d(n - 1) : 2);\nexport const d = (n: number): number => (n > 0 ? e(n - 1) : 3);\nexport const e = (n: number): number => (n > 0 ? a(n - 1) : 4);\n`, ); assert.match(big, /became one cycle \(5 definitions\)[^\n]*They call each other/); // saved again as it is (a comment changed): nothing new to say const again = save( `export const a = (n: number): number => (n > 0 ? b(n - 1) : 0); // the first\n`, "update", ); assert.doesNotMatch(again, /warning: .*cycle/); }