computedInitializer
uses tcmts.core.ts.parse, which uses tcmts.core.ts.compiler, which uses process
Where a constant's initializer is in its stored text, if it's one that's computed (it calls something), when the
module it's in loads: const table = build(), not const f = () => … or const n = 3, or one that waits.
import { forEachChild, parse } from "#codebase/tcmts/core/ts"; import type { DefRecord } from "#codebase/tcmts/core/types"; import { isArrowFunction as ts_isArrowFunction, isClassExpression as ts_isClassExpression, isFunctionExpression as ts_isFunctionExpression, isIdentifier as ts_isIdentifier, isVariableStatement as ts_isVariableStatement, SyntaxKind as ts_SyntaxKind, } from "typescript/ast"; import type { Node as ts_Node } from "typescript/ast"; export function computedInitializer(rec: DefRecord): { start: number; end: number } | undefined { if ( rec.kind !== "term" || rec.componentSize !== 1 || rec.initKind !== "strict" || !rec.sourceText.startsWith("const ") ) return undefined; const sf = parse("kept.ts", rec.sourceText); const st = sf.statements[0]; if (!st || !ts_isVariableStatement(st) || st.declarationList.declarations.length !== 1) return undefined; const d = st.declarationList.declarations[0]!; const init = d.initializer; if ( !ts_isIdentifier(d.name) || !init || ts_isArrowFunction(init) || ts_isFunctionExpression(init) || ts_isClassExpression(init) ) return undefined; let calls = false; let waits = false; const visit = (n: ts_Node) => { if ( n.kind === ts_SyntaxKind.CallExpression || n.kind === ts_SyntaxKind.NewExpression || n.kind === ts_SyntaxKind.TaggedTemplateExpression ) calls = true; if (n.kind === ts_SyntaxKind.AwaitExpression || n.kind === ts_SyntaxKind.YieldExpression) waits = true; forEachChild(n, visit); }; visit(init); return calls && !waits ? { start: init.getStart(sf), end: init.end } : undefined; }