@drkmttr/adhere 0.17.5 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
1
  import { isNote, withoutComments } from "#comments.ts";
2
+ import { DEFAULT_MAX_SYMBOL_DOCUMENTATION_LENGTH, DEFAULT_MAX_SYMBOL_LENGTH } from "#config.ts";
2
3
  import { suppressionsOf } from "#suppress.ts";
3
4
  import { Effect, Fiber, Layer, Path } from "effect";
4
5
  import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
@@ -65,7 +66,13 @@ const sources = {
65
66
  "node_modules/private/package.json": JSON.stringify({ name: "private", types: "index.d.ts" }),
66
67
  "node_modules/private/index.d.ts": "export declare const secret: number;",
67
68
  };
68
- const both: SourceReadRequest = { symbols: true, references: true, includeComments: false };
69
+ const both: SourceReadRequest = {
70
+ symbols: true,
71
+ references: true,
72
+ includeComments: false,
73
+ maxSymbolDocumentationLength: DEFAULT_MAX_SYMBOL_DOCUMENTATION_LENGTH,
74
+ maxSymbolLength: DEFAULT_MAX_SYMBOL_LENGTH,
75
+ };
69
76
  const roots: string[] = [];
70
77
  const within = async <A>(promise: Promise<A>, milliseconds: number): Promise<A> => {
71
78
  let timer: ReturnType<typeof setTimeout> | undefined;
@@ -199,11 +206,11 @@ describe("native TypeScript compiler and declaration reads", () => {
199
206
  "export const first = {} as Box<string>;",
200
207
  "export const second = {} as Box<number>;",
201
208
  "export const mapped: Readonly<Box<string>> = first;",
202
- "/** An unrelated reader. */",
203
- "export const other = { get: () => true };",
204
209
  ].join("\n"),
210
+ "other.ts": "/** An unrelated reader. */\nexport const other = { get: () => true };",
205
211
  "use.ts": [
206
- 'import { first, second, mapped, other } from "./lib";',
212
+ 'import { first, second, mapped } from "./lib";',
213
+ 'import { other } from "./other";',
207
214
  "export const results = [first.get(), second.get(), mapped.get(), other.get()];",
208
215
  ].join("\n"),
209
216
  "types.d.ts": "",
@@ -218,8 +225,79 @@ describe("native TypeScript compiler and declaration reads", () => {
218
225
  expect(get.match(/\*\*@returns\*\*/g)).toHaveLength(1);
219
226
  expect(get).toContain("The stored value.");
220
227
  expect(get).toContain("**@example** box.get();");
221
- expect(result.references!.get!["lib.ts"]).toContain(" get(): T;");
222
- expect(result.references!.get!["lib.ts"]).toContain("get: () => true");
228
+ expect(result.references!["get:lib.ts"]).toContain(" get(): T;");
229
+ expect(result.references!["get:other.ts"]).toBe("export const other = { get: () => true };");
230
+ });
231
+
232
+ it("caps documentation independently when the whole-symbol limit allows long signatures", async () => {
233
+ const documentation = `Documentation: ${"x".repeat(600)}`;
234
+ const example = "y".repeat(600);
235
+ const parameters = Array.from({ length: 24 }, (_, index) => `argument${index}: number`).join(
236
+ ", ",
237
+ );
238
+ const { root, read } = await fixture({
239
+ "lib.ts": [
240
+ `/** ${documentation} */`,
241
+ `export function original(${parameters}) { return argument0; }`,
242
+ `/** A value.\n * @example ${example}\n */`,
243
+ "export const tagged = 42;",
244
+ ].join("\n"),
245
+ "use.ts":
246
+ 'import { original, tagged } from "./lib";\nexport const result = [original, tagged];',
247
+ "types.d.ts": "",
248
+ });
249
+ const results = await run(
250
+ root,
251
+ Effect.forEach([256, 32, 0, 1024], (maxSymbolDocumentationLength) =>
252
+ read("use.ts", { ...both, maxSymbolDocumentationLength, maxSymbolLength: 4096 }),
253
+ ),
254
+ );
255
+ for (const [index, limit] of [256, 32, 0, 1024].entries()) {
256
+ const result = results[index];
257
+ const content = result?.symbols?.original ?? "";
258
+ expect(content).toMatch(/^```typescript\n[\s\S]+\n```/);
259
+ const [, signature = "", docs = ""] =
260
+ content.match(/^```typescript\n([\s\S]*?)\n```(?:\n\n([\s\S]*))?$/) ?? [];
261
+ expect(signature.length).toBeGreaterThan(256);
262
+ expect(signature).toContain("argument23: number");
263
+ expect(docs).toBe(documentation.slice(0, limit));
264
+ const tags = `A value.\n\n**@example** ${example}`.slice(0, limit);
265
+ expect(result?.symbols?.tagged).toBe(
266
+ `\`\`\`typescript\n42\n\`\`\`${tags ? `\n\n${tags}` : ""}`,
267
+ );
268
+ expect(result?.references).toEqual(results[0]?.references);
269
+ expect(result?.references?.["original:lib.ts"]).toContain(parameters);
270
+ }
271
+ });
272
+
273
+ it("caps each final symbol across bindings and documentation without shortening references", async () => {
274
+ const { root, read } = await fixture({
275
+ ...sources,
276
+ "lib.ts": library.replace("The original documented value.", "x".repeat(600)),
277
+ });
278
+ const { full, capped } = await run(
279
+ root,
280
+ Effect.gen(function* () {
281
+ const full = yield* read("use.ts", { ...both, maxSymbolLength: 4096 });
282
+ const capped = yield* Effect.forEach([256, 32, 0, 1024], (maxSymbolLength) =>
283
+ read("use.ts", { ...both, maxSymbolLength }),
284
+ );
285
+ return { full, capped };
286
+ }),
287
+ );
288
+ expect(full.symbols?.local?.length).toBeGreaterThan(256);
289
+ expect(full.symbols?.local).toContain("```typescript\nstring\n```");
290
+ for (const [index, limit] of [256, 32, 0, 1024].entries()) {
291
+ expect(capped[index]?.symbols).toEqual(
292
+ Object.fromEntries(
293
+ Object.entries(full.symbols ?? {}).map(([name, content]) => [
294
+ name,
295
+ content.slice(0, limit),
296
+ ]),
297
+ ),
298
+ );
299
+ expect(capped[index]?.references).toEqual(full.references);
300
+ }
223
301
  });
224
302
 
225
303
  it("reads const-asserted empty tuple properties and their normal usages without losing surrounding types or references", async () => {
@@ -241,8 +319,7 @@ describe("native TypeScript compiler and declaration reads", () => {
241
319
  '{ readonly action: "update"; readonly stables: readonly []; }',
242
320
  );
243
321
  expect(result.symbols!.action).toBe('```typescript\n"update"\n```');
244
- expect(result.references!.original).toEqual({ "lib.ts": "export const original = 42;" });
245
- expect(result.references).not.toHaveProperty("stables");
322
+ expect(result.references).toEqual({ "original:lib.ts": "export const original = 42;" });
246
323
  });
247
324
 
248
325
  it("keeps error types unavailable without hiding explicitly declared any types", async () => {
@@ -261,6 +338,188 @@ describe("native TypeScript compiler and declaration reads", () => {
261
338
  expect(result.symbols!.explicit).toBe("```typescript\nany\n```");
262
339
  });
263
340
 
341
+ it("omits standard built-ins without changing audited code or meaningful user signatures", async () => {
342
+ const declaration = [
343
+ "export function collect(values: Array<string>): Promise<Array<string>> {",
344
+ " return Promise.resolve(values);",
345
+ "}",
346
+ ].join("\n");
347
+ const contents = [
348
+ 'import { collect } from "./lib";',
349
+ 'export const values: Array<string> = [" value "];',
350
+ "export const copied = Array.from(values).map(value => value.trim());",
351
+ "export const objectKeys = Object.keys({ copied });",
352
+ "export const pending: Promise<string[]> = collect(copied);",
353
+ 'pending.then(value => console.log(value.join(","))).catch((error: unknown) => String(error));',
354
+ "export function inspect(flag: boolean, count: number): unknown {",
355
+ " if (flag && count > 0) {",
356
+ " try { return arguments[0] ?? undefined; } catch { return undefined; }",
357
+ " }",
358
+ " return undefined;",
359
+ "}",
360
+ ].join("\n");
361
+ const { root } = await fixture(
362
+ {
363
+ "lib.ts": "/** Collects typed values. */\n" + declaration,
364
+ "use.ts": contents,
365
+ "types.d.ts": "",
366
+ },
367
+ {
368
+ compilerOptions: {
369
+ strict: true,
370
+ target: "ES2022",
371
+ types: [],
372
+ module: "Preserve",
373
+ moduleResolution: "Bundler",
374
+ },
375
+ files: ["lib.ts", "use.ts", "types.d.ts"],
376
+ },
377
+ );
378
+ const file = { path: join(root, "use.ts"), contents };
379
+ const lines = normalized(contents);
380
+ const result = (await run(
381
+ root,
382
+ Effect.flatMap(SourceReads, (reads) => reads.read(file, lines, both)),
383
+ )) as SourceReadState;
384
+ for (const name of [
385
+ "Array",
386
+ "console",
387
+ "Object",
388
+ "Promise",
389
+ "String",
390
+ "from",
391
+ "map",
392
+ "trim",
393
+ "keys",
394
+ "then",
395
+ "log",
396
+ "join",
397
+ "catch",
398
+ "undefined",
399
+ "arguments",
400
+ "string",
401
+ "number",
402
+ "boolean",
403
+ "unknown",
404
+ "if",
405
+ "try",
406
+ ]) {
407
+ expect(result.symbols).not.toHaveProperty(name);
408
+ expect(Object.keys(result.references!).some((key) => key.startsWith(`${name}:`))).toBe(false);
409
+ }
410
+ expect(result.symbols!.collect).toContain("(values: Array<string>) => Promise<Array<string>>");
411
+ expect(result.symbols!.collect).toContain("Collects typed values.");
412
+ expect(result.symbols!.inspect).toContain("(flag: boolean, count: number) => unknown");
413
+ expect(result.references!["collect:lib.ts"]).toBe(declaration);
414
+ expect(file.contents).toBe(contents);
415
+ expect(lines).toEqual(normalized(contents));
416
+ expect(await readFile(file.path, "utf8")).toBe(contents);
417
+ });
418
+
419
+ it("omits aliased runtime built-ins while preserving third-party declarations and augmentations", async () => {
420
+ const files = {
421
+ "lib.ts": "",
422
+ "use.ts": [
423
+ 'import { readFile as readText } from "node:fs";',
424
+ 'import { hash as hashText } from "bun";',
425
+ 'import { Database as SqliteDatabase } from "bun:sqlite";',
426
+ 'import { readFile as vendorRead } from "third-party";',
427
+ 'export const runtimeText = readText("fixture.txt");',
428
+ "export const runtimeHash = hashText(runtimeText);",
429
+ 'export const database = new SqliteDatabase(":memory:");',
430
+ 'export const vendorText = vendorRead("fixture.txt");',
431
+ "export const vendorValues = Array.from([vendorText]);",
432
+ "export const extended = vendorValues.vendorFeature();",
433
+ ].join("\n"),
434
+ "types.d.ts": [
435
+ '/// <reference path="./node_modules/@types/node/index.d.ts" />',
436
+ '/// <reference path="./node_modules/@types/bun/index.d.ts" />',
437
+ '/// <reference path="./node_modules/bun-types/index.d.ts" />',
438
+ ].join("\n"),
439
+ "node_modules/@types/node/index.d.ts":
440
+ 'declare module "node:fs" { /** Reads a runtime file. */ export function readFile(path: string): string; }',
441
+ "node_modules/@types/bun/index.d.ts":
442
+ 'declare module "bun" { /** Hashes a runtime value. */ export function hash(value: string): number; }',
443
+ "node_modules/bun-types/index.d.ts":
444
+ 'declare module "bun:sqlite" { /** Opens a runtime database. */ export class Database { constructor(path: string); } }',
445
+ "node_modules/third-party/package.json": JSON.stringify({
446
+ name: "third-party",
447
+ types: "index.d.ts",
448
+ }),
449
+ "node_modules/third-party/index.d.ts": [
450
+ "/** Third-party file reader. */",
451
+ "export declare function readFile(path: string): string;",
452
+ "declare global {",
453
+ " interface Array<T> {",
454
+ " /** Third-party array extension. */",
455
+ " vendorFeature(): string;",
456
+ " }",
457
+ "}",
458
+ ].join("\n"),
459
+ };
460
+ const { root, read } = await fixture(files);
461
+ const result = await run(root, read("use.ts"));
462
+ for (const name of ["readText", "hashText", "SqliteDatabase"]) {
463
+ expect(result.symbols).not.toHaveProperty(name);
464
+ expect(Object.keys(result.references!).some((key) => key.startsWith(`${name}:`))).toBe(false);
465
+ }
466
+ expect(result.symbols!.vendorRead).toContain("(path: string) => string");
467
+ expect(result.symbols!.vendorRead).toContain("Third-party file reader.");
468
+ expect(result.symbols!.vendorFeature).toContain("Third-party array extension.");
469
+ expect(result.symbols!.Array).toEqual(expect.any(String));
470
+ expect(result.symbols!.database).toEqual(expect.any(String));
471
+ expect(result.references).toEqual({});
472
+ });
473
+
474
+ it("preserves project-owned built-in names, intrinsic-name properties and imported aliases", async () => {
475
+ const declarations = {
476
+ Array: "export const Array = (value: string) => value;",
477
+ Promise: "export const Promise = (value: number) => value;",
478
+ console: "export const console = { log(value: string) { return value; } };",
479
+ Object: "export const Object = { catch(value: string) { return value; } };",
480
+ tokens:
481
+ 'export const tokens = { undefined: "project marker", arguments: "project arguments" };',
482
+ };
483
+ const files = {
484
+ "lib.ts": [
485
+ "/** Project array builder. */",
486
+ declarations.Array,
487
+ "/** Project promise maker. */",
488
+ declarations.Promise,
489
+ declarations.console,
490
+ declarations.Object,
491
+ declarations.tokens,
492
+ ].join("\n"),
493
+ "use.ts": [
494
+ 'import { Array, Promise as createPromise, console, Object, tokens } from "./lib";',
495
+ 'export const result = createPromise(Array("value").length);',
496
+ 'console.log(Object.catch("value"));',
497
+ "export const markers = [tokens.undefined, tokens.arguments];",
498
+ ].join("\n"),
499
+ "types.d.ts": "",
500
+ };
501
+ const { root, read } = await fixture(files);
502
+ const result = await run(root, read("use.ts"));
503
+ for (const name of [
504
+ "Array",
505
+ "createPromise",
506
+ "console",
507
+ "Object",
508
+ "log",
509
+ "catch",
510
+ "tokens",
511
+ "undefined",
512
+ "arguments",
513
+ ]) {
514
+ expect(result.symbols![name]).toEqual(expect.any(String));
515
+ expect(result.references).toHaveProperty([`${name}:lib.ts`]);
516
+ }
517
+ expect(result.symbols!.Array).toContain("Project array builder.");
518
+ expect(result.symbols!.createPromise).toContain("Project promise maker.");
519
+ expect(result.references!["Array:lib.ts"]).toBe(declarations.Array);
520
+ expect(result.references!["createPromise:lib.ts"]).toBe(declarations.Promise);
521
+ });
522
+
264
523
  it("keeps declaration references and filename casing under case-insensitive native paths", async () => {
265
524
  const declaration = [
266
525
  "export function twice(value: number): number {",
@@ -303,7 +562,7 @@ describe("native TypeScript compiler and declaration reads", () => {
303
562
  expect(api.getCanonicalFileName(root)).not.toBe(root);
304
563
  expect(result.symbols!.scale).toContain("(value: number) => number");
305
564
  expect(result.symbols!.scale).toContain("Double a number.");
306
- expect(result.references).toEqual({ scale: { "Library.ts": declaration } });
565
+ expect(result.references).toEqual({ "scale:Library.ts": declaration });
307
566
  } finally {
308
567
  await api.close();
309
568
  }
@@ -313,20 +572,18 @@ describe("native TypeScript compiler and declaration reads", () => {
313
572
  const { root, read } = await fixture();
314
573
  const result = await run(root, read("use.ts"));
315
574
  const refs = result.references!;
316
- expect(refs.local).toEqual({ "lib.ts": "export const original = 42;" });
317
- expect(refs.local!["lib.ts"]).not.toContain("neighbor");
318
- expect(refs.Shape!["lib.ts"]).toBe(
575
+ expect(refs["local:lib.ts"]).toBe("export const original = 42;");
576
+ expect(refs["local:lib.ts"]).not.toContain("neighbor");
577
+ expect(refs["Shape:lib.ts"]).toBe(
319
578
  "export interface Shape { first: number }\n…\nexport interface Shape { second: string }",
320
579
  );
321
- expect(refs.pair!["lib.ts"]).toContain("\n…\n");
322
- expect(refs.pair!["lib.ts"]).toContain("export function pair(value: number): number;");
323
- expect(refs.pair!["lib.ts"]).toContain("export function pair(value: string): string;");
324
- expect(refs).not.toHaveProperty("unused");
325
- expect(refs).not.toHaveProperty("external");
326
- expect(refs).not.toHaveProperty("dependency");
327
- expect(Object.values(refs).flatMap(Object.keys)).not.toContain("use.ts");
580
+ expect(refs["pair:lib.ts"]).toContain("\n…\n");
581
+ expect(refs["pair:lib.ts"]).toContain("export function pair(value: number): number;");
582
+ expect(refs["pair:lib.ts"]).toContain("export function pair(value: string): string;");
583
+ expect(Object.keys(refs).sort()).toEqual(["Shape:lib.ts", "local:lib.ts", "pair:lib.ts"]);
584
+ expect(Object.values(refs).every((text) => typeof text === "string")).toBe(true);
328
585
  expect(JSON.stringify(refs)).not.toMatch(/ordinary comment|never send this directive/);
329
- expect(refs.local!["lib.ts"]).not.toContain("@adhere");
586
+ expect(refs["local:lib.ts"]).not.toContain("@adhere");
330
587
  expect(JSON.stringify(refs)).not.toContain(library);
331
588
  });
332
589
 
@@ -425,13 +682,11 @@ describe("native TypeScript compiler and declaration reads", () => {
425
682
  const { root, read } = await fixture(files);
426
683
  const result = await run(root, read("use.ts", { ...both, symbols: false }));
427
684
  for (const [name, text] of Object.entries(declarations)) {
428
- expect(result.references![name]).toEqual({ "lib.ts": text });
685
+ expect(result.references![`${name}:lib.ts`]).toBe(text);
429
686
  }
430
- expect(result.references!.run).toEqual({ "lib.ts": method });
431
- expect(result.references!.current).toEqual({ "lib.ts": accessors });
432
- expect(result.references!.first).toEqual({
433
- "lib.ts": ` first: 1,\n…\n${destructured}`,
434
- });
687
+ expect(result.references!["run:lib.ts"]).toBe(method);
688
+ expect(result.references!["current:lib.ts"]).toBe(accessors);
689
+ expect(result.references!["first:lib.ts"]).toBe(` first: 1,\n…\n${destructured}`);
435
690
  expect(JSON.stringify(result.references)).not.toMatch(/outsideBefore|outsideAfter/);
436
691
  });
437
692
 
@@ -450,13 +705,13 @@ describe("native TypeScript compiler and declaration reads", () => {
450
705
  expect(Object.keys(result.symbols)).toEqual(["symbols"]);
451
706
  expect(result.symbols.symbols!.local).toContain("The original documented value.");
452
707
  expect(Object.keys(result.references)).toEqual(["references"]);
453
- expect(result.references.references!.local!["lib.ts"]).toBe(
708
+ expect(result.references.references!["local:lib.ts"]).toBe(
454
709
  normalized(library, true).slice(1, 6).join("\n"),
455
710
  );
456
- expect(result.references.references!.local!["lib.ts"]).toContain(
711
+ expect(result.references.references!["local:lib.ts"]).toContain(
457
712
  "/** The original documented value. */",
458
713
  );
459
- expect(result.references.references!.local!["lib.ts"]).not.toContain("adhere-ignore");
714
+ expect(result.references.references!["local:lib.ts"]).not.toContain("adhere-ignore");
460
715
  });
461
716
 
462
717
  it("serializes concurrent same-file and child-project reads while isolating aliases and inferred ownership", async () => {
@@ -517,12 +772,8 @@ describe("native TypeScript compiler and declaration reads", () => {
517
772
  );
518
773
  expect(result[0]!.symbols!.local).toContain("First project.");
519
774
  expect(result[1]!.symbols!.local).toContain("Second project.");
520
- expect(result[0]!.references!.local).toEqual({
521
- "packages/a/src/value.ts": "export const value = 1;",
522
- });
523
- expect(result[1]!.references!.local).toEqual({
524
- "packages/b/alt/value.ts": "export const value = 2;",
525
- });
775
+ expect(result[0]!.references!["local:packages/a/src/value.ts"]).toBe("export const value = 1;");
776
+ expect(result[1]!.references!["local:packages/b/alt/value.ts"]).toBe("export const value = 2;");
526
777
  expect(result[2]!.symbols!.outside).toContain("```typescript\n3\n```");
527
778
  expect(result[2]!.references).toEqual({});
528
779
  expect(result[3]).toEqual(result[0]);
@@ -542,7 +793,7 @@ describe("native TypeScript compiler and declaration reads", () => {
542
793
  prepare(["lib.ts", "use.ts"]).pipe(Effect.andThen(read("use.ts"))),
543
794
  );
544
795
  expect(result.symbols!.local).toContain("Inferred docs.");
545
- expect(result.references!.local).toEqual({ "lib.ts": "export const value = 1;" });
796
+ expect(result.references!["local:lib.ts"]).toBe("export const value = 1;");
546
797
  expect(Object.keys(result).sort()).toEqual(["references", "symbols"]);
547
798
  });
548
799
 
@@ -570,10 +821,8 @@ describe("native TypeScript compiler and declaration reads", () => {
570
821
  const result = await run(join(root, "workspace"), read("workspace/use.ts"));
571
822
  expect(result.symbols!.original).toContain("Unicode documentation šŸ˜€.");
572
823
  expect(result.symbols!.outside).toContain("Outside documentation.");
573
- expect(result.references!.original).toEqual({
574
- "lib.ts": "export const original = 42;",
575
- });
576
- expect(result.references).not.toHaveProperty("outside");
824
+ expect(result.references!["original:lib.ts"]).toBe("export const original = 42;");
825
+ expect(Object.keys(result.references!).some((key) => key.startsWith("outside:"))).toBe(false);
577
826
  });
578
827
 
579
828
  it("pins each read to its supplied text despite disk changes and accepts new text in a later read", async () => {
@@ -799,7 +1048,7 @@ describe("native TypeScript compiler and declaration reads", () => {
799
1048
  const state = yield* Effect.promise(() => within(Effect.runPromise(reading), 3000));
800
1049
  expect(state.symbols!.local).toContain("```typescript\n42\n```");
801
1050
  expect(state.symbols!.local).toContain("The original documented value.");
802
- expect(state.references!.local).toEqual({ "lib.ts": "export const original = 42;" });
1051
+ expect(state.references!["local:lib.ts"]).toBe("export const original = 42;");
803
1052
  expect(closeDocument).toHaveBeenCalledTimes(2);
804
1053
  expect(dispose).toHaveBeenCalledTimes(2);
805
1054
  expect(close).not.toHaveBeenCalled();
@@ -11,7 +11,7 @@ import { NativeLsp } from "./NativeLsp.ts";
11
11
  import type { Project, Symbol, Type } from "typescript/async";
12
12
  import type { Node, SourceFile } from "typescript/ast";
13
13
 
14
- export type SourceReferences = Record<string, Record<string, string>>;
14
+ export type SourceReferences = Record<string, string>;
15
15
  export type SourceReadState = ReadState & {
16
16
  readonly symbols?: Record<string, string>;
17
17
  readonly references?: SourceReferences;
@@ -20,6 +20,8 @@ export interface SourceReadRequest {
20
20
  readonly symbols: boolean;
21
21
  readonly references: boolean;
22
22
  readonly includeComments: boolean;
23
+ readonly maxSymbolLength: number;
24
+ readonly maxSymbolDocumentationLength: number;
23
25
  }
24
26
  export class SourceReads extends Context.Service<
25
27
  SourceReads,
@@ -121,6 +123,28 @@ async function readOf(
121
123
  ? undefined
122
124
  : target;
123
125
  });
126
+ const builtins = new Map<number, Promise<boolean>>();
127
+ const builtinOf = (symbol: Symbol) =>
128
+ once(builtins, symbol.id, async () => {
129
+ if (symbol.declarations.length === 0) {
130
+ if (symbol.name === "undefined")
131
+ return native.sdk("isUndefinedSymbol", () => project.checker.isUndefinedSymbol(symbol));
132
+ if (symbol.name === "arguments")
133
+ return native.sdk("isArgumentsSymbol", () => project.checker.isArgumentsSymbol(symbol));
134
+ return false;
135
+ }
136
+ for (const { path } of symbol.declarations) {
137
+ if (owned(path)) return false;
138
+ const pathname = canonicalOf(path).split(sep).join("/");
139
+ if (/(?:^|\/)node_modules\/(?:@types\/(?:node|bun)|bun-types)\//.test(pathname)) continue;
140
+ // Metadata classifies standard libraries without loading their full declaration ASTs.
141
+ const metadata = await native.sdk("getSourceFileMetadata", () =>
142
+ project.program.getSourceFileMetadataByPath(path),
143
+ );
144
+ if (!metadata?.isDefaultLibrary) return false;
145
+ }
146
+ return true;
147
+ });
124
148
  const definitionsOf = (symbol: Symbol) =>
125
149
  once(definitions, symbol.id, async () => {
126
150
  const found: Node[] = [];
@@ -154,6 +178,8 @@ async function readOf(
154
178
  for (const [index, node] of nodes.entries()) {
155
179
  const local = symbols[index];
156
180
  if (!local) continue;
181
+ const binding = local.flags & sdk.SymbolFlags.Alias ? await targetOf(local) : local;
182
+ if (binding && (await builtinOf(binding))) continue;
157
183
  const name = node.getText(source);
158
184
  const shorthand = ast.isShorthandPropertyAssignment(node.parent);
159
185
  const used = usedOf(node);
@@ -214,7 +240,8 @@ async function readOf(
214
240
  );
215
241
  return [comment, ...tags.map(({ name, text }) => `**@${name}**${text ? ` ${text}` : ""}`)]
216
242
  .filter(Boolean)
217
- .join("\n\n");
243
+ .join("\n\n")
244
+ .slice(0, requested.maxSymbolDocumentationLength);
218
245
  });
219
246
  const formattedTypes = new Map<string, Promise<string>>();
220
247
  const descriptions = new Map<
@@ -254,32 +281,26 @@ async function readOf(
254
281
  }
255
282
  const cleaned = new Map<SourceFile, readonly string[]>();
256
283
  const references = sorted(
257
- [...excerpts].map(
258
- ([name, byFile]) =>
259
- [
260
- name,
261
- sorted(
262
- [...byFile].map(([pathname, { source: linked, windows }]) => {
263
- let lines = cleaned.get(linked);
264
- if (!lines) {
265
- const directed = suppressionsOf(linked.text.split("\n")).lines;
266
- lines = requested.includeComments ? directed : withoutComments(directed, isNote);
267
- cleaned.set(linked, lines);
268
- }
269
- const merged: Array<{ first: number; last: number }> = [];
270
- for (const window of windows.sort((a, b) => a.first - b.first || a.last - b.last)) {
271
- const previous = merged.at(-1);
272
- if (previous && window.first <= previous.last)
273
- previous.last = Math.max(previous.last, window.last);
274
- else merged.push({ ...window });
275
- }
276
- return [
277
- pathname,
278
- merged.map(({ first, last }) => lines.slice(first, last).join("\n")).join("\n…\n"),
279
- ] as const;
280
- }),
281
- ),
282
- ] as const,
284
+ [...excerpts].flatMap(([name, byFile]) =>
285
+ [...byFile].map(([pathname, { source: linked, windows }]) => {
286
+ let lines = cleaned.get(linked);
287
+ if (!lines) {
288
+ const directed = suppressionsOf(linked.text.split("\n")).lines;
289
+ lines = requested.includeComments ? directed : withoutComments(directed, isNote);
290
+ cleaned.set(linked, lines);
291
+ }
292
+ const merged: Array<{ first: number; last: number }> = [];
293
+ for (const window of windows.sort((a, b) => a.first - b.first || a.last - b.last)) {
294
+ const previous = merged.at(-1);
295
+ if (previous && window.first <= previous.last)
296
+ previous.last = Math.max(previous.last, window.last);
297
+ else merged.push({ ...window });
298
+ }
299
+ return [
300
+ `${name}:${pathname}`,
301
+ merged.map(({ first, last }) => lines.slice(first, last).join("\n")).join("\n…\n"),
302
+ ] as const;
303
+ }),
283
304
  ),
284
305
  );
285
306
  return {
@@ -301,7 +322,9 @@ async function readOf(
301
322
  .join("\n\n"),
302
323
  ),
303
324
  ),
304
- ].join("\n\n---\n\n"),
325
+ ]
326
+ .join("\n\n---\n\n")
327
+ .slice(0, requested.maxSymbolLength),
305
328
  ] as const,
306
329
  ),
307
330
  ),