computedInitializer

tcmts.cli.kept.computedInitializer · #xyqrow6s · term · runs on the server

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;
}

uses

used by