definitionInScratch

tcmts.studio.definitionInScratch · #bxtubfee · term · runs on the server

uses tcmts.studio.editableCodebase, which uses tcmts.share.servedCodebase, which uses process

Where the name at offset in a scratch file is defined: a name from the codebase, its page; one the file declares, where (an offset); one from elsewhere (a package, the standard library), nowhere here.

import { cacheRefOf } from "#codebase/tcmts/core/shape";
import { declarationOf } from "#codebase/tcmts/core/ts";
import { codeHref } from "#codebase/tcmts/share";
import { analyzedScratch, editableCodebase, identifierAt, scratchPath } from "#codebase/tcmts/studio";
import type { Node as ts_Node } from "typescript/ast";
import { SymbolFlags as ts_SymbolFlags } from "typescript/sync";

export async function definitionInScratch(
  file: string,
  text: string,
  offset: number,
): Promise<{ href?: string; at?: number } | null> {
  const cb = editableCodebase();
  const abs = scratchPath(cb, file);
  const a = analyzedScratch(cb, abs, text);
  const id = identifierAt(a, abs, offset);
  if (!id) return null;
  const checker = a.checker;
  let sym = checker.getSymbolAtLocation(id);
  if (sym && sym.flags & ts_SymbolFlags.Alias) sym = checker.getAliasedSymbol(sym);
  if (!sym) return null;
  const hash = cacheRefOf(checker)(sym);
  if (hash) {
    const name = cb.store.pathsOf(cb.store.patched(hash))[0];
    return name ? { href: codeHref(name) } : null;
  }
  const decl = declarationOf(sym);
  const sf = decl?.getSourceFile();
  if (!decl || !sf || sf.fileName !== a.program.getSourceFile(abs)?.fileName) return null;
  const named = (decl as ts_Node & { name?: ts_Node }).name ?? decl;
  return { at: named.getStart(sf) };
}

uses

used by