carrick 0.3.122 → 0.3.124

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "carrick",
3
- "version": "0.3.122",
3
+ "version": "0.3.124",
4
4
  "carrickCache": {
5
5
  "cache_version": 22,
6
6
  "intent_cache_version": 2
@@ -113,11 +113,11 @@
113
113
  "zod": "^3.23.0"
114
114
  },
115
115
  "optionalDependencies": {
116
- "@carrick-tools/cli-darwin-arm64": "0.3.122",
117
- "@carrick-tools/cli-darwin-x64": "0.3.122",
118
- "@carrick-tools/cli-linux-arm64": "0.3.122",
119
- "@carrick-tools/cli-linux-x64": "0.3.122",
120
- "@carrick-tools/cli-win32-x64": "0.3.122"
116
+ "@carrick-tools/cli-darwin-arm64": "0.3.124",
117
+ "@carrick-tools/cli-darwin-x64": "0.3.124",
118
+ "@carrick-tools/cli-linux-arm64": "0.3.124",
119
+ "@carrick-tools/cli-linux-x64": "0.3.124",
120
+ "@carrick-tools/cli-win32-x64": "0.3.124"
121
121
  },
122
122
  "devDependencies": {
123
123
  "@types/node": "^24.13.3"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "carrick",
3
3
  "description": "Claude Code plugin for Carrick, which indexes TypeScript codebases across service and repository boundaries. After each edit it adds the file's routes, calls, and cross-service type mismatches to the session, and it registers Carrick's language server. It pairs with the Carrick MCP server, which lets agents search functions by intent rather than name.",
4
- "version": "0.3.122",
4
+ "version": "0.3.124",
5
5
  "author": {
6
6
  "name": "Carrick",
7
7
  "email": "hello@carrick.tools"
@@ -39,6 +39,12 @@ export const MACHINERY_MEMBER_INDICATORS = new Set([
39
39
  'clone',
40
40
  'json',
41
41
  'statusText',
42
+ // FROZEN (old path, 2026-10-21): the reply-object half below only (the
43
+ // fetch half above and the threshold stay). Deletions and safety fixes
44
+ // only. Fixes for wrong or missing types go in labelled reply objects
45
+ // (carrick#2472 C4) and the language library rows (carrick#2445). Delete
46
+ // when a delete-and-replay on the four repos moves no row wrongly, after
47
+ // carrick-cloud#2379 and carrick#2445 (carrick#2472, C6).
42
48
  // Node http ServerResponse / reply-object surface
43
49
  'statusCode',
44
50
  'statusMessage',
@@ -442,7 +442,7 @@ function handleVerifyLibraryClaims(request) {
442
442
  writeProgress(request.request_id, 'verify_library_claims', 'program ready');
443
443
  const fromDir = path.resolve(projectLoader.getRepoRoot(), request.from_dir);
444
444
  log(`Verifying ${request.checks.length} library claim(s) from ${fromDir}`);
445
- const { semantics, modules } = claimsVerifier.run(fromDir, request.checks, request.budget_ms ?? SEMANTICS_BUDGET_MS);
445
+ const { semantics, modules } = claimsVerifier.run(fromDir, request.checks, request.budget_ms ?? SEMANTICS_BUDGET_MS, request.scan_root);
446
446
  return {
447
447
  request_id: request.request_id,
448
448
  status: 'success',
@@ -63,7 +63,7 @@ export declare class LibraryClaimsVerifier {
63
63
  * A check on an instance or a scope reads the maker or scope claims of the
64
64
  * same request first, whatever their place in it.
65
65
  */
66
- run(fromDir: string, checks: LibraryCheck[], budgetMs: number): VerifyResult;
66
+ run(fromDir: string, checks: LibraryCheck[], budgetMs: number, scanRoot?: string): VerifyResult;
67
67
  /**
68
68
  * Each specifier's declared surface, read with the verifier's predicates
69
69
  * (carrick#1660): every value export (or only those `only` names for the
@@ -39,6 +39,7 @@ import * as crypto from 'node:crypto';
39
39
  import * as fs from 'node:fs';
40
40
  import * as path from 'node:path';
41
41
  import { ts } from 'ts-morph';
42
+ import { PathNames, declaringFileName } from './position-rows.js';
42
43
  /** The methods a `verb` claim may name, and a method key may accept. */
43
44
  const HTTP_METHODS = new Set([
44
45
  'GET',
@@ -130,8 +131,9 @@ const HTTP_V2_RULES = { http: false, message: true, ops: new Set(['request']), m
130
131
  const SERVER_RULES = { http: false, message: true, ops: new Set(['receive']), methods: ROUTE_METHODS };
131
132
  /**
132
133
  * The role table: the role alone picks the checks. A role this build does
133
- * not read yet (GraphQL executors, server mounts) answers `role_unsupported`,
134
- * and `none` has nothing on the wire to check.
134
+ * not read yet (GraphQL executors) answers `role_unsupported`, and `none`
135
+ * has nothing on the wire to check. A server's mounts are scope claims
136
+ * (`mounts`, #2474 R0).
135
137
  */
136
138
  const ROLE_TABLE = {
137
139
  http_client: HTTP_RULES,
@@ -238,6 +240,13 @@ export function httpCheck(check) {
238
240
  }
239
241
  }
240
242
  }
243
+ /** Declarations in a fixed order, each once. */
244
+ function sortedDeclarations(declarations) {
245
+ const seen = new Map();
246
+ for (const each of declarations)
247
+ seen.set(`${each.decl_file}:${each.decl_line}`, each);
248
+ return [...seen.values()].sort((a, b) => (a.decl_file < b.decl_file ? -1 : a.decl_file > b.decl_file ? 1 : a.decl_line - b.decl_line));
249
+ }
241
250
  let probeSequence = 0;
242
251
  export class LibraryClaimsVerifier {
243
252
  project;
@@ -250,10 +259,15 @@ export class LibraryClaimsVerifier {
250
259
  * A check on an instance or a scope reads the maker or scope claims of the
251
260
  * same request first, whatever their place in it.
252
261
  */
253
- run(fromDir, checks, budgetMs) {
262
+ run(fromDir, checks, budgetMs, scanRoot) {
254
263
  const deadline = performance.now() + budgetMs;
255
264
  const stamp = (check, outcome) => outcome.verdict === 'verified'
256
- ? { claim_id: check.claim_id, receiver: check.receiver, verdict: 'verified' }
265
+ ? {
266
+ claim_id: check.claim_id,
267
+ receiver: check.receiver,
268
+ verdict: 'verified',
269
+ ...(outcome.declarations?.length ? { declarations: outcome.declarations } : {}),
270
+ }
257
271
  : {
258
272
  claim_id: check.claim_id,
259
273
  receiver: check.receiver,
@@ -330,7 +344,7 @@ export class LibraryClaimsVerifier {
330
344
  const file = program.getSourceFile(probe.getFilePath());
331
345
  if (!file)
332
346
  throw new Error(`probe file ${probePath} is not in the program`);
333
- const reader = new DeclarationReader(program, file, this.project.getModuleResolutionHost(), fromDir);
347
+ const reader = new DeclarationReader(program, file, this.project.getModuleResolutionHost(), fromDir, scanRoot);
334
348
  const localRanges = readLocalRanges(fromDir);
335
349
  const moduleReads = new Map();
336
350
  const exportReads = new Map();
@@ -501,13 +515,15 @@ export class LibraryClaimsVerifier {
501
515
  const built = builtReceiver(check);
502
516
  const builtAtDefaults = built === undefined ? undefined : atDefaults(check, built);
503
517
  const holding = [];
518
+ const declarations = [];
504
519
  for (const receiver of receivers.value) {
505
520
  const result = reader.judgeMessage(receiver, check.claim, rules, builtAtDefaults);
506
521
  if (result.outcome.verdict !== 'verified')
507
522
  return result;
508
523
  holding.push(...(result.holding ?? []));
524
+ declarations.push(...(result.outcome.declarations ?? []));
509
525
  }
510
- return { outcome: VERIFIED, holding };
526
+ return { outcome: declarations.length > 0 ? { verdict: 'verified', declarations: sortedDeclarations(declarations) } : VERIFIED, holding };
511
527
  };
512
528
  const semantics = [];
513
529
  for (let index = 0; index < checks.length; index++) {
@@ -695,6 +711,19 @@ function placementInvalid(claim) {
695
711
  const of = parseReceiver(claim.of);
696
712
  return of === undefined || (of.maker === undefined && of.scope === undefined);
697
713
  }
714
+ /**
715
+ * Where a handler's request holds its path and method (#2474 R0) is read on
716
+ * a receive op with a handler, and names `path` or `url`; every member path
717
+ * it gives is non-empty.
718
+ */
719
+ function requestAtValid(claim) {
720
+ const request = claim.request;
721
+ if (claim.op !== 'receive' || claim.handler === undefined)
722
+ return false;
723
+ if (request.path === undefined && request.url === undefined)
724
+ return false;
725
+ return [request.path, request.url, request.method].every(members => members === undefined || members.length > 0);
726
+ }
698
727
  /**
699
728
  * A message check names a receiver its claim can be read on (contract
700
729
  * amendment 2, B3). A maker is read on the export itself. An element with
@@ -841,6 +870,8 @@ class DeclarationReader {
841
870
  probe;
842
871
  host;
843
872
  checker;
873
+ /** Names declaring files as position rows do: from the scan root, else the service root. */
874
+ pathNames;
844
875
  /** The service root, as a realpath. */
845
876
  root;
846
877
  packageDirectories = new Map();
@@ -853,11 +884,12 @@ class DeclarationReader {
853
884
  declared = new Map();
854
885
  /** The service root as given and as a realpath, longest first: what a listing prints as `<root>`. */
855
886
  printedRoots;
856
- constructor(program, probe, host, serviceRoot) {
887
+ constructor(program, probe, host, serviceRoot, scanRoot) {
857
888
  this.program = program;
858
889
  this.probe = probe;
859
890
  this.host = host;
860
891
  this.checker = program.getTypeChecker();
892
+ this.pathNames = new PathNames(scanRoot ?? serviceRoot);
861
893
  this.root = this.realpath(serviceRoot);
862
894
  this.printedRoots = [...new Set([this.root, serviceRoot])]
863
895
  .filter(root => root.length > 1)
@@ -1472,9 +1504,26 @@ class DeclarationReader {
1472
1504
  * `member` (after `path`) is a home-declared callable member whose name
1473
1505
  * slot accepts a string, under the name-slot rules, and returns a type that
1474
1506
  * says something, read at its type-parameter defaults (`returnOf`).
1507
+ *
1508
+ * Route fields (#2474 R0, contract amendment of 2026-10-22 on carrick#2434):
1509
+ * - `runs` with `yields`: the member runs the function at `runs` (a
1510
+ * function with a declared signature) and hands it, at `yields.param`,
1511
+ * an instance of the package's export `yields.export` (`yieldsOutcome`);
1512
+ * - `mounts`: the receiver the claim is read on fits the parameter there
1513
+ * (`mountsOutcome`).
1514
+ * Either one binds its instance through a parameter or an argument, not
1515
+ * the member's return, so the return is not read and the claim holds no
1516
+ * overloads: a `>scope:` receiver read through it is not resolved.
1517
+ * `runs` without `yields` (or the reverse), or `mounts` beside either, is
1518
+ * `claim_invalid`.
1475
1519
  */
1476
1520
  judgeScope(receiver, claim, built) {
1477
- const layout = this.layout({ name: claim.name });
1521
+ if ((claim.runs === undefined) !== (claim.yields === undefined))
1522
+ return { outcome: unchecked('claim_invalid') };
1523
+ if (claim.mounts !== undefined && claim.runs !== undefined)
1524
+ return { outcome: unchecked('claim_invalid') };
1525
+ const binds = claim.runs !== undefined || claim.mounts !== undefined;
1526
+ const layout = this.layout({ name: claim.name, runs: claim.runs, mounts: claim.mounts });
1478
1527
  if ('failure' in layout)
1479
1528
  return { outcome: layout.failure };
1480
1529
  const callee = this.ownCallee(receiver, claim.path ?? [], claim.member, 'call');
@@ -1485,7 +1534,17 @@ class DeclarationReader {
1485
1534
  let best;
1486
1535
  for (const signature of callee.signatures) {
1487
1536
  let result = this.messageSignatureOutcome(signature, layout.value, labels);
1488
- if (result.rank === Infinity && this.returnSaysNothing(this.returnOf(signature, built))) {
1537
+ if (result.rank === Infinity && claim.yields !== undefined) {
1538
+ const given = this.yieldsOutcome(signature, claim.runs, claim.yields, receiver);
1539
+ if (given)
1540
+ result = { rank: 5, outcome: given };
1541
+ }
1542
+ if (result.rank === Infinity && claim.mounts !== undefined) {
1543
+ const mounted = this.mountsOutcome(signature, claim.mounts, receiver);
1544
+ if (mounted)
1545
+ result = { rank: 5, outcome: mounted };
1546
+ }
1547
+ if (result.rank === Infinity && !binds && this.returnSaysNothing(this.returnOf(signature, built))) {
1489
1548
  result = { rank: 6, outcome: unchecked('scope_unresolved') };
1490
1549
  }
1491
1550
  if (result.rank === Infinity)
@@ -1494,9 +1553,38 @@ class DeclarationReader {
1494
1553
  best = furthest(best, result.rank, result.outcome);
1495
1554
  }
1496
1555
  if (holding.length > 0)
1497
- return { outcome: VERIFIED, holding };
1556
+ return binds ? { outcome: VERIFIED } : { outcome: VERIFIED, holding };
1498
1557
  return { outcome: best.outcome };
1499
1558
  }
1559
+ /**
1560
+ * `mounts: { arg, key? }` on a scope (#2474 R0): the receiver the claim is
1561
+ * read on is assignable to the parameter there, so an instance like it can
1562
+ * be served under the scope's name. A parameter typed `any`, `unknown`,
1563
+ * `{}` or by an unconstrained type parameter says nothing
1564
+ * (`mounts_untyped`). There is no separate "not a function" rule: a router
1565
+ * type that is itself a handler is a common shape, and a parameter only a
1566
+ * function fits fails here because the instance does not fit it.
1567
+ * Undefined when it holds.
1568
+ */
1569
+ mountsOutcome(signature, mounts, receiver) {
1570
+ let declared = this.keyParameterAt(signature, mounts.arg);
1571
+ if (declared !== undefined && mounts.key !== undefined) {
1572
+ const property = this.declaredProperty(declared, mounts.key);
1573
+ declared = property ? this.checker.getTypeOfSymbol(property) : undefined;
1574
+ }
1575
+ if (declared === undefined)
1576
+ return failed('param_missing');
1577
+ const slot = this.throughConstraint(declared);
1578
+ if (slot === VARIADIC)
1579
+ return unchecked('mounts_untyped');
1580
+ const parts = this.parts(slot);
1581
+ if (parts.length === 0)
1582
+ return failed('mounts_not_instance');
1583
+ if (parts.some(part => this.isOpenTop(part) || this.isUnconstrained(part) || this.isEmptyObject(part))) {
1584
+ return unchecked('mounts_untyped');
1585
+ }
1586
+ return this.checker.isTypeAssignableTo(receiver.type, slot) ? undefined : failed('mounts_not_instance');
1587
+ }
1500
1588
  /**
1501
1589
  * A send, receive or request op: the home-declared callable member (after
1502
1590
  * `path`; or the receiver itself, when null) with some overload that takes
@@ -1513,6 +1601,9 @@ class DeclarationReader {
1513
1601
  if (claim.yields !== undefined && (claim.op !== 'receive' || claim.handler === undefined)) {
1514
1602
  return unchecked('claim_invalid');
1515
1603
  }
1604
+ // So is where the handler's request holds its path and method (#2474 R0).
1605
+ if (claim.request !== undefined && !requestAtValid(claim))
1606
+ return unchecked('claim_invalid');
1516
1607
  const name = claim.name;
1517
1608
  // A send carries a payload: a name alone on `send(data)` is the data. An
1518
1609
  // op that runs a function or client it is handed takes its name from
@@ -1562,6 +1653,11 @@ class DeclarationReader {
1562
1653
  if (given)
1563
1654
  result = { rank: 5, outcome: given };
1564
1655
  }
1656
+ if (result.rank === Infinity && claim.request !== undefined) {
1657
+ const read = this.requestOutcome(signature, claim.handler, claim.request);
1658
+ if (read)
1659
+ result = { rank: 5, outcome: read };
1660
+ }
1565
1661
  if (result.rank === Infinity) {
1566
1662
  held = true;
1567
1663
  break;
@@ -1572,7 +1668,28 @@ class DeclarationReader {
1572
1668
  return best.outcome;
1573
1669
  if (boundRuns)
1574
1670
  return this.boundRunsOutcome(receiver.makerHolding, boundRuns);
1575
- return VERIFIED;
1671
+ const declarations = this.declarationsOf(callee.signatures);
1672
+ return declarations.length > 0 ? { verdict: 'verified', declarations } : VERIFIED;
1673
+ }
1674
+ /**
1675
+ * Where the signatures a verified op resolved to are declared, as position
1676
+ * rows spell it (`decl_file`, `decl_line`): the member on this receiver, so
1677
+ * two members of one name on two types give two answers. A declaration no
1678
+ * row could name is left out.
1679
+ */
1680
+ declarationsOf(signatures) {
1681
+ const found = [];
1682
+ for (const signature of signatures) {
1683
+ const declaration = signature.getDeclaration();
1684
+ if (!declaration)
1685
+ continue;
1686
+ const file = declaration.getSourceFile();
1687
+ const decl_file = declaringFileName(this.program, this.pathNames, file);
1688
+ if (decl_file === null)
1689
+ continue;
1690
+ found.push({ decl_file, decl_line: file.getLineAndCharacterOfPosition(declaration.getStart(file)).line + 1 });
1691
+ }
1692
+ return sortedDeclarations(found);
1576
1693
  }
1577
1694
  /**
1578
1695
  * The method fields of an op (label structure v2, carrick#2434), under the
@@ -1680,6 +1797,48 @@ class DeclarationReader {
1680
1797
  }
1681
1798
  return failed('yields_not_export');
1682
1799
  }
1800
+ /**
1801
+ * `request: { param, path?, url?, method? }` on a receive op (#2474 R0):
1802
+ * some signature of the handler this overload takes declares a parameter
1803
+ * at `param` on which every member path the claim gives resolves, step by
1804
+ * step, through properties the library declares (`declaredProperty`).
1805
+ * Undefined when it holds.
1806
+ */
1807
+ requestOutcome(signature, handler, request) {
1808
+ let declared = this.keyParameterAt(signature, handler.arg);
1809
+ if (declared !== undefined && handler.key !== undefined) {
1810
+ const property = this.declaredProperty(declared, handler.key);
1811
+ declared = property ? this.checker.getTypeOfSymbol(property) : undefined;
1812
+ }
1813
+ if (declared === undefined)
1814
+ return failed('param_missing');
1815
+ const slot = this.throughConditional(this.throughConstraint(declared));
1816
+ if (slot === VARIADIC)
1817
+ return unchecked('handler_untyped');
1818
+ const paths = [request.path, request.url, request.method].filter((p) => p !== undefined);
1819
+ let best = failed('param_missing');
1820
+ for (const part of this.parts(slot)) {
1821
+ for (const handed of part.getCallSignatures()) {
1822
+ const given = this.parameterAt(handed, request.param);
1823
+ if (given === undefined || given === VARIADIC)
1824
+ continue;
1825
+ const resolves = paths.every(members => {
1826
+ let at = given;
1827
+ for (const member of members) {
1828
+ const property = this.declaredProperty(at, member);
1829
+ if (!property)
1830
+ return false;
1831
+ at = this.checker.getTypeOfSymbol(property);
1832
+ }
1833
+ return true;
1834
+ });
1835
+ if (resolves)
1836
+ return undefined;
1837
+ best = failed('request_member_missing');
1838
+ }
1839
+ }
1840
+ return best;
1841
+ }
1683
1842
  /**
1684
1843
  * The declarations spell `name` in one of `member`'s parameters: an
1685
1844
  * overload whose parameter there is that literal, or a key of the map a
@@ -13,29 +13,26 @@
13
13
  * | `member` | property or element access | the name or the argument | the access |
14
14
  * | `compare` | `=== !== == != < > <= >= instanceof in` | the left operand | the left operand |
15
15
  * | `ident` | an identifier in expression position | itself | itself |
16
- * | `impl` | a `call` or `member` whose declaration has no body | an implementation of it | nothing |
17
16
  * | `decl` | a `call` or `member` on a union of declaring types | one of those declarations | nothing |
18
17
  * | `jsx` | a JSX opening or self-closing element's tag | the tag's name | the tag |
19
18
  *
20
- * An `impl` row (version 2, carrick#2430) follows the `call` or `member` row
21
- * it belongs to and has its span: one per declaration that go-to-implementation
22
- * names for that row's declaration, when that declaration is an interface's
23
- * or type literal's method, a function-typed property signature, an abstract
24
- * member, or a function-typed class property or parameter with no
25
- * initializer. Its `decl_*` name the implementing declaration. Past
26
- * {@link IMPL_CAP} the row is one, with {@link FLAG_TOO_MANY} and nothing else.
27
- *
28
19
  * A `decl` row (version 3, carrick#2448) follows the `call` or `member` row
29
- * it belongs to, before its `impl` rows, and has its span: one per
20
+ * it belongs to and has its span: one per
30
21
  * declaration of the member when the receiver is a union whose constituents
31
22
  * declare it at more than one place (`(pick ? a : b).get()` with two
32
23
  * classes). That row names only the first of them. Each constituent's
33
24
  * declaration is its own member's, or, for a member with none (a mapped
34
- * type's), the declaration of the constituent type itself. Sorted and capped
35
- * as `impl` rows are; `type_text` is `null`.
25
+ * type's), the declaration of the constituent type itself. Sorted by file and
26
+ * position; past {@link DECL_CAP} the row is one, with {@link FLAG_TOO_MANY}
27
+ * and nothing else. `type_text` is `null`.
28
+ *
29
+ * Version 4 (carrick#2561) dropped the `impl` rows of versions 2 and 3: the
30
+ * go-to-implementation search behind them was most of the walk's time, and
31
+ * nothing read them. Implementations are asked for where discovery stops
32
+ * (carrick#2432).
36
33
  *
37
- * A row's key is `(start, end, kind)`, except that several `impl` rows, and
38
- * several `decl` rows, share one: TypeScript `getStart()`/`getEnd()` of the
34
+ * A row's key is `(start, end, kind)`, except that several `decl` rows share
35
+ * one: TypeScript `getStart()`/`getEnd()` of the
39
36
  * node, in UTF-16 code units from the start of the file, which is what the scanner's `sidecar_position`
40
37
  * gives for an SWC span. Every path written is relative to the scanned repo's
41
38
  * root, with `/` separators.
@@ -54,7 +51,7 @@ import { ts } from 'ts-morph';
54
51
  import type { ProjectLoader } from './project-loader.js';
55
52
  import type { PositionRowsCounts } from './types.js';
56
53
  /** The format's version, written in the header. */
57
- export declare const POSITION_ROWS_VERSION = 3;
54
+ export declare const POSITION_ROWS_VERSION = 4;
58
55
  /** The type is `any`, declared or inferred. Never set with the error type. */
59
56
  export declare const FLAG_ANY = 1;
60
57
  /** The type is the compiler's error type: something did not resolve. */
@@ -63,7 +60,7 @@ export declare const FLAG_ERROR_TYPE = 2;
63
60
  export declare const FLAG_CHECKER_THREW = 4;
64
61
  /** The declaration is outside the checkout, not the default library and in no installed package. */
65
62
  export declare const FLAG_DECLARATION_UNNAMED = 8;
66
- /** An `impl` or `decl` row standing for more than {@link IMPL_CAP} rows of its kind; it names none. */
63
+ /** A `decl` row standing for more than {@link DECL_CAP} rows; it names none. */
67
64
  export declare const FLAG_TOO_MANY = 16;
68
65
  /**
69
66
  * The declaration is published under the row's symbol name: its module
@@ -74,11 +71,11 @@ export declare const FLAG_TOO_MANY = 16;
74
71
  export declare const FLAG_PUBLISHED = 32;
75
72
  /** The declaration is what its module exports as `export =` or `default` (carrick#2508). */
76
73
  export declare const FLAG_MODULE_DEFAULT = 64;
77
- /** The most `impl` rows one declaration lists, and the most `decl` rows one position lists. */
78
- export declare const IMPL_CAP = 16;
79
- /** The kinds {@link kindOf} gives a node; `impl`, `decl` and `jsx` rows are written beside them. */
74
+ /** The most `decl` rows one position lists. */
75
+ export declare const DECL_CAP = 16;
76
+ /** The kinds {@link kindOf} gives a node; `decl` and `jsx` rows are written beside them. */
80
77
  export type NodeKind = 'call' | 'member' | 'compare' | 'ident';
81
- export type PositionKind = NodeKind | 'impl' | 'decl' | 'jsx';
78
+ export type PositionKind = NodeKind | 'decl' | 'jsx';
82
79
  /** `[kind, start, end, symbol, decl_file, decl_line, decl_package, type_text, flags]` */
83
80
  export type PositionRow = [
84
81
  PositionKind,
@@ -110,5 +107,49 @@ export interface PositionRowsOptions {
110
107
  * a directory inside the scanned trees anywhere but beneath `.carrick`.
111
108
  */
112
109
  export declare function writePositionRows(options: PositionRowsOptions): PositionRowsCounts;
110
+ /** What a declaration's file is written as in a row's `decl_file`: `lib:<name>` for the default library, else `PathNames`'. */
111
+ export declare function declaringFileName(program: ts.Program, paths: PathNames, file: ts.SourceFile): string | null;
112
+ /**
113
+ * Names for the files rows point at, never an absolute path: relative to the
114
+ * scanned repo's root when inside it (its real path too, so a root reached
115
+ * through a link still contains its files), `lib:<name>` for the compiler's
116
+ * default library, `pkg:<name>/<path>` for an installed package outside the
117
+ * root, and nothing otherwise.
118
+ */
119
+ export declare class PathNames {
120
+ private readonly roots;
121
+ private readonly packageNames;
122
+ /**
123
+ * Answers by declaring file: a service's rows name a few thousand files
124
+ * hundreds of thousands of times, and the module graph's answer is a scan
125
+ * of its packages (on a Deno service it was 40% of the walk).
126
+ */
127
+ private readonly declaringFiles;
128
+ private readonly declaringPackages;
129
+ constructor(scanRoot: string);
130
+ /** The root `file` lies under, and its path from there; `undefined` outside every root. */
131
+ private inside;
132
+ /** A request file's name: relative to the root, which every file the scanner sends is inside. */
133
+ relative(file: string): string;
134
+ /** What a declaring file is written as, or `null` when nothing names it. */
135
+ declaringFile(fileName: string): string | null;
136
+ private nameDeclaringFile;
137
+ /**
138
+ * The package a declaring file belongs to: the module graph's or the path's
139
+ * answer (`installedPackageOf`), else, for a file inside the root, the
140
+ * `name` of the nearest package.json at or above it, up to the root.
141
+ */
142
+ declaringPackage(fileName: string, packageOf: (filePath: string) => string | undefined): string | null;
143
+ private nameDeclaringPackage;
144
+ private packageNameIn;
145
+ /**
146
+ * `import("/abs/path")` in a printed type, written with the declaring
147
+ * file's name instead. The print has no enclosing node, so it names every
148
+ * module by the file that declares it and one type reads the same from
149
+ * every file; it also skips the accessibility search an enclosing node
150
+ * costs (40% of the walk on a 600-file service).
151
+ */
152
+ scrubType(text: string): string;
153
+ }
113
154
  /** The kind of row a node gives, if any (exported for the editor-parity test, carrick#2418). */
114
155
  export declare function kindOf(node: ts.Node): NodeKind | undefined;