testSyntaxErrorIsSaidAlone

tcmts.cli.test.e2e.editing.testSyntaxErrorIsSaidAlone · #saicwl67 · term

Code that doesn't parse is said by its first syntax error alone, with the lines around it: no type errors that follow from reading it wrong, no imports worked out from it. By tcm patch (where the definition's view has it), tcm check and tcm update.

import { okIn, tcmIn, 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 testSyntaxErrorIsSaidAlone = () => {
  const dir = tempDir("syntax error alone");
  const ok = (...args: string[]) => okIn(dir, ...args);
  const fails = (...args: string[]) => {
    const r = tcmIn(dir, ...args);
    assert.notEqual(r.status, 0, r.out);
    return r.out;
  };
  const alone = (out: string, where: RegExp) => {
    assert.match(out, where);
    assert.equal(out.match(/error TS\d+/g)?.length, 1, out);
    assert.doesNotMatch(out, /import \{/);
    assert.match(out, /doesn't parse; nothing else was checked/);
  };
  ok("init");
  fs.writeFileSync(
    path.join(dir, "m.ts"),
    "// tcm: namespace m\nexport const f = (s: string): string => s.trim();\n",
  );
  fs.writeFileSync(
    path.join(dir, "o.ts"),
    "// tcm: namespace o\nexport const helper = (s: string): string => s.trim();\n",
  );
  ok("add", "m.ts", "o.ts");
  const patched = fails("patch", "m.f", "--old", "s.trim()", "--new", "s.trim() helper(s)");
  alone(patched, /m\.f:1:\d+ - error TS1005/);
  assert.match(
    patched,
    /> export const f = \(s: string\): string => s\.trim\(\) helper\(s\)\n +\^/,
  );
  const file = path.join(dir, "broken.ts");
  const text =
    "// tcm: namespace m\nexport const g = `one ${f} two` three`;\n\nexport const h = helper(g);\n";
  fs.writeFileSync(file, text);
  alone(fails("check", "broken.ts"), /broken\.ts:2:\d+ - error TS1005/);
  alone(fails("update", "broken.ts"), /broken\.ts:2:\d+ - error TS1005/);
  assert.equal(fs.readFileSync(file, "utf8"), text);
}

uses