declarations
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; }