memberCode

tcmts.cli.suites.memberCode · #pm7t5vs3 · term · runs on the server

uses node:crypto

A class's own code as a suite's result depends on part of it: one of its methods (member, by name: what that method does), or, for "", the rest of it (its fields, constructor and what it extends, its methods but their bodies), which every use of it depends on. Undefined if it has no such method. Referring to other definitions by name, as ownCode does (nameOf as it takes it).

import type { Codebase } from "#codebase/tcmts/cli/codebase";
import { withoutCyclePositions } from "#codebase/tcmts/cli/main";
import type { IR } from "#codebase/tcmts/core/hash";
import { childOf, declarationOf, defParts } from "#codebase/tcmts/core/ir";
import type { DefRecord } from "#codebase/tcmts/core/types";
import crypto from "node:crypto";

export function memberCode(
  cb: Codebase,
  rec: DefRecord,
  member: string,
  nameOf = (h: string): string | undefined => cb.store.pathsOf(h)[0],
): string | undefined {
  if (rec.kind !== "class") return undefined;
  const ir = JSON.parse(
    withoutCyclePositions(rec.ir).replace(/\["Ref","([a-z2-7]+)"\]/g, (_, h: string) =>
      JSON.stringify(["Ref", nameOf(h) ?? h]),
    ),
  ) as IR[];
  const decl = declarationOf(ir);
  const members = (childOf(decl, "members") as unknown[] | undefined)?.slice(1) as
    | unknown[][]
    | undefined;
  if (!decl || !members) return undefined;
  const memberName = (m: unknown[]) => {
    const n = (m.find((c) => Array.isArray(c) && c[0] === "name") as unknown[] | undefined)?.[1];
    return Array.isArray(n) && n[0] === "N" ? String(n[1]) : undefined;
  };
  const method = (m: unknown[]) =>
    /^(MethodDeclaration|GetAccessor|SetAccessor)$/.test(String(m[0])) &&
    memberName(m) !== undefined;
  const parts =
    member === ""
      ? [
          ...defParts(ir).head,
          decl.filter((c) => !(Array.isArray(c) && c[0] === "members")),
          members.map((m) => (method(m) ? [m[0], memberName(m)] : m)),
        ]
      : members.filter((m) => method(m) && memberName(m) === member);
  if (!parts.length) return undefined;
  return crypto.createHash("sha256").update(JSON.stringify(parts)).digest("hex").slice(0, 32);
}

uses

used by