declarations

tcmts.cli.mirror.declarations · #wuplwbtw · term · runs on the server

uses tcmts.core.ts.parse, which uses tcmts.core.ts.compiler, which uses process

import type { Decl } from "#codebase/tcmts/cli/mirror";
import { getModifiers, parse } from "#codebase/tcmts/core/ts";
import {
  isClassDeclaration as ts_isClassDeclaration, isEnumDeclaration as ts_isEnumDeclaration,
  isFunctionDeclaration as ts_isFunctionDeclaration, isIdentifier as ts_isIdentifier,
  isInterfaceDeclaration as ts_isInterfaceDeclaration, isTypeAliasDeclaration as ts_isTypeAliasDeclaration,
  isVariableStatement as ts_isVariableStatement, SyntaxKind as ts_SyntaxKind,
} from "typescript/ast";
import type { Node as ts_Node, Statement as ts_Statement } from "typescript/ast";

export function declarations(file: string, text: string): Map<string, Decl> {
  const sf = parse(file, text);
  const out = new Map<string, Decl>();
  const add = (name: string, st: ts_Statement, shared = false) => {
    const docs = (st as { jsDoc?: readonly ts_Node[] }).jsDoc;
    const doc = docs?.length ? { start: docs.at(-1)!.getStart(sf), end: docs.at(-1)!.end } : undefined;
    const exported = (getModifiers(st) ?? []).some((m) => m.kind === ts_SyntaxKind.ExportKeyword);
    const prev = out.get(name);
    // overloads: one definition from the first signature to the implementation
    if (prev) out.set(name, { ...prev, end: st.end });
    else out.set(name, { start: st.getStart(sf), end: st.end, ...(doc ? { doc } : {}), exported, shared });
  };
  for (const st of sf.statements) {
    if ((ts_isFunctionDeclaration(st) || ts_isClassDeclaration(st) || ts_isInterfaceDeclaration(st) || ts_isTypeAliasDeclaration(st) || ts_isEnumDeclaration(st)) && st.name) add(st.name.text, st);
    else if (ts_isVariableStatement(st)) {
      const ds = st.declarationList.declarations;
      for (const d of ds) if (ts_isIdentifier(d.name)) add(d.name.text, st, ds.length > 1);
    }
  }
  return out;
}

uses

used by