analyzeWith

tcmts.core.analyze.analyzeWith · #e3zgbucf · term · runs on the server

uses tcmts.core.program.compilerOptions, which uses tcmts.core.program.tcmNodeTypes, which uses node:path

import { analyzeSources } from "#codebase/tcmts/core/analyze";
import type { AnalyzeHost, ProjectAnalysis } from "#codebase/tcmts/core/analyze";
import { extract, TcmError } from "#codebase/tcmts/core/extract";
import type { ExtractMode } from "#codebase/tcmts/core/extract";
import { checkProfile, compilerOptions, createProgram, fileDiagnostics } from "#codebase/tcmts/core/program";

export function analyzeWith(
  files: string[],
  host: AnalyzeHost,
  mode: ExtractMode,
): Omit<ProjectAnalysis, "packages"> {
  const { program, checker, options, dispose } = (host.compile ?? ((f, o) => createProgram(f, o)))(
    files,
    host.compilerOptions ?? compilerOptions(),
  );
  const sfs = files.map((f) => {
    const sf = program.getSourceFile(f);
    if (!sf) throw new Error(`cannot read ${f}`);
    return sf;
  });
  const base = { program, checker, dispose, defs: [], watches: [], warnings: [] as string[] };

  const diagnostics = sfs.flatMap((sf, i) =>
    fileDiagnostics(
      program,
      sf,
      host.ignoreDiagnostics,
      i === 0 && host.typecheck !== false,
      host.skipDiagnostic,
      host.typecheck !== false,
    ),
  );
  const errors: string[] = [];
  if (diagnostics.length) {
    // structural problems (enums, top-level let, ...) explain themselves better than the type errors they cause
    for (const sf of sfs) {
      try {
        extract(sf, mode);
      } catch (e) {
        if (!(e instanceof TcmError)) throw e;
        errors.push(e.message);
      }
    }
    return { ...base, diagnostics, errors };
  }
  const result = analyzeSources(sfs, checker, host, mode, options);
  if (result.errors.length)
    return { ...base, diagnostics: [], errors: result.errors, warnings: result.warnings };
  // each definition remembers the options it typechecked under, so later re-checks use the same ones
  const checked = checkProfile(options);
  for (const d of [...result.defs, ...result.watches]) d.checked = checked;
  return { ...result, program, checker, dispose, diagnostics: [] };
}

uses

used by