clearSaved

tcmts.cli.main.clearSaved · #gw5b6ura · term · runs on the server

uses tcmts.cli.mirror.declarations, which uses tcmts.core.ts.parse, which uses tcmts.core.ts.compiler, which uses process

A scratch file's text without the definitions in it saved as they are (their docs and // tcm: path lines with them, and imports only they used), so it holds what's being worked on; one the rest of the file mentions (a watch expression, another definition) stays. The names taken out.

import type { Codebase } from "#codebase/tcmts/cli/codebase";
import { classify } from "#codebase/tcmts/cli/main";
import { declarations, pruneImports } from "#codebase/tcmts/cli/mirror";
import type { ProjectDef } from "#codebase/tcmts/core/analyze";

export function clearSaved(
  cb: Codebase,
  file: string,
  text: string,
): { text: string; cleared: string[] } {
  cb.refreshShim();
  const a = cb.analyze(file, cb.scratchSalts());
  if (a.errors.length || a.diagnostics.length) return { text, cleared: [] };
  const decls = declarations(file, text);
  const spans = classify(cb, a.defs, a.namespace ?? "").flatMap((r) => {
    // (the file's own definitions, as analyzed: each a whole statement, with its doc)
    const def = r.def as ProjectDef;
    const d = decls.get(def.nameHint);
    if (r.status !== "identical" || def.file !== file || !d || d.shared) return [];
    let start = d.doc?.start ?? d.start;
    const pragma = /(?:^|\n)\/\/ tcm: path \S+\n$/.exec(text.slice(0, start));
    if (pragma) start = pragma.index + (text[pragma.index] === "\n" ? 1 : 0);
    let end = d.end;
    while (text[end] === "\n") end++;
    return [{ start, end, name: def.nameHint, path: r.path }];
  });
  const without = (keep: typeof spans) => {
    let out = text;
    for (const sp of [...keep].sort((x, y) => y.start - x.start))
      out = out.slice(0, sp.start) + out.slice(sp.end);
    return out;
  };
  const rest = without(spans);
  const gone = spans.filter(
    (sp) => !new RegExp(`\\b${sp.name.replaceAll("$", "\\$")}\\b`).test(rest),
  );
  if (!gone.length) return { text, cleared: [] };
  return {
    text: pruneImports(file, text, without(gone)).replace(/\n{3,}/g, "\n\n"),
    cleared: gone.map((sp) => sp.path),
  };
}

uses

used by