exampleNames

tcmts.core.docs.exampleNames · #x3u75zv5 · term · runs on the server

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

uses

used by