exampleNames
uses tcmts.core.ts.parse, which uses tcmts.core.ts.compiler, which uses process
The names an example uses from outside itself (where they are in code): references, not property names or
names the example declares. Each may be a definition in scope where the doc is.
import { forEachChild, isOmitted, parse } from "#codebase/tcmts/core/ts"; import { isBindingElement as ts_isBindingElement, isBreakOrContinueStatement as ts_isBreakOrContinueStatement, isClassDeclaration as ts_isClassDeclaration, isExpressionWithTypeArguments as ts_isExpressionWithTypeArguments, isFunctionDeclaration as ts_isFunctionDeclaration, isIdentifier as ts_isIdentifier, isInterfaceDeclaration as ts_isInterfaceDeclaration, isLabeledStatement as ts_isLabeledStatement, isMethodDeclaration as ts_isMethodDeclaration, isParameterDeclaration as ts_isParameter, isPropertyAccessExpression as ts_isPropertyAccessExpression, isPropertyAssignment as ts_isPropertyAssignment, isPropertyDeclaration as ts_isPropertyDeclaration, isPropertySignatureDeclaration as ts_isPropertySignature, isQualifiedName as ts_isQualifiedName, isTypeAliasDeclaration as ts_isTypeAliasDeclaration, isTypeParameterDeclaration as ts_isTypeParameterDeclaration, isTypeReferenceNode as ts_isTypeReferenceNode, isVariableDeclaration as ts_isVariableDeclaration, } from "typescript/ast"; import type { BindingName as ts_BindingName, Node as ts_Node } from "typescript/ast"; export function exampleNames(code: string): { start: number; end: number; name: string; type: boolean }[] { const sf = parse("example.ts", code); const declared = new Set<string>(); const declare = (n: ts_BindingName) => { if (ts_isIdentifier(n)) declared.add(n.text); else for (const e of n.elements) if (!isOmitted(e)) declare(e.name!); }; const collect = (n: ts_Node) => { if ((ts_isVariableDeclaration(n) || ts_isParameter(n) || ts_isBindingElement(n)) && n.name) declare(n.name); if ((ts_isFunctionDeclaration(n) || ts_isClassDeclaration(n) || ts_isTypeAliasDeclaration(n) || ts_isInterfaceDeclaration(n)) && n.name) declared.add(n.name.text); if (ts_isTypeParameterDeclaration(n)) declared.add(n.name.text); forEachChild(n, collect); }; collect(sf); const out: { start: number; end: number; name: string; type: boolean }[] = []; const visit = (n: ts_Node) => { if (ts_isIdentifier(n) && !declared.has(n.text)) { const p = n.parent; const isName = (ts_isPropertyAccessExpression(p) && p.name === n) || (ts_isQualifiedName(p) && p.right === n) || ((ts_isPropertyAssignment(p) || ts_isPropertySignature(p) || ts_isMethodDeclaration(p) || ts_isPropertyDeclaration(p)) && p.name === n) || (ts_isBindingElement(p) && p.propertyName === n) || ts_isLabeledStatement(p) || ts_isBreakOrContinueStatement(p); if (!isName) out.push({ start: n.getStart(sf), end: n.end, name: n.text, type: ts_isTypeReferenceNode(p) || ts_isExpressionWithTypeArguments(p) }); } forEachChild(n, visit); }; visit(sf); return out; }