@shanepadgett/tau-agent 0.33.1 → 0.34.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.
Files changed (190) hide show
  1. package/docs/context.md +29 -20
  2. package/docs/extending-tau-agent.md +63 -24
  3. package/extensions/appshot/index.ts +112 -111
  4. package/extensions/aside/README.md +7 -0
  5. package/extensions/aside/index.ts +168 -0
  6. package/extensions/aside/panel.ts +83 -0
  7. package/extensions/branch/index.ts +38 -21
  8. package/extensions/cache-diagnostics/index.ts +70 -58
  9. package/extensions/checkpoint/README.md +9 -0
  10. package/extensions/checkpoint/checkpoint-budget.ts +79 -0
  11. package/extensions/checkpoint/checkpoint.ts +277 -0
  12. package/extensions/checkpoint/index.ts +102 -0
  13. package/extensions/checkpoint/messages.ts +169 -0
  14. package/extensions/checkpoint/prompt.ts +24 -0
  15. package/extensions/checkpoint/settings.ts +27 -0
  16. package/extensions/commit/commit-effort.ts +3 -3
  17. package/extensions/context/README.md +12 -8
  18. package/extensions/context/definitions.ts +178 -55
  19. package/extensions/context/index.ts +192 -160
  20. package/extensions/context/panel.ts +57 -37
  21. package/extensions/context/sync.ts +139 -89
  22. package/extensions/context/validation.ts +37 -25
  23. package/extensions/effort/README.md +1 -1
  24. package/extensions/effort/index.ts +3 -3
  25. package/extensions/effort/state.ts +3 -18
  26. package/extensions/explore/guidance.ts +6 -47
  27. package/extensions/explore/index.ts +38 -53
  28. package/extensions/explore/{ast/read → read}/hook.ts +12 -7
  29. package/extensions/explore/{ast/tools → tools}/ast-search.ts +15 -19
  30. package/extensions/explore/{ast/tools → tools}/context.ts +16 -23
  31. package/extensions/explore/{ast/tools → tools}/deps.ts +11 -15
  32. package/extensions/explore/{ast/tools → tools}/discover.ts +15 -17
  33. package/extensions/explore/{ast/tools → tools}/impact.ts +20 -23
  34. package/extensions/explore/{ast/tools → tools}/outline.ts +21 -24
  35. package/extensions/explore/{ast/tools → tools}/relationships.ts +23 -32
  36. package/extensions/explore/{ast/tools → tools}/render.ts +1 -1
  37. package/extensions/explore/{ast/tools → tools}/reverse-deps.ts +11 -15
  38. package/extensions/explore/{ast/tools → tools}/show.ts +16 -19
  39. package/extensions/explore/tools/target-params.ts +9 -0
  40. package/extensions/footer/index.ts +75 -56
  41. package/extensions/handoff/index.ts +8 -30
  42. package/extensions/image-gen/index.ts +46 -40
  43. package/extensions/patch/executor.ts +190 -135
  44. package/extensions/patch/matcher.ts +82 -48
  45. package/extensions/patch/parser.ts +149 -105
  46. package/extensions/patch/render.ts +32 -39
  47. package/extensions/patch/summary.ts +30 -26
  48. package/extensions/ready/README.md +7 -0
  49. package/extensions/ready/index.ts +58 -0
  50. package/extensions/ready/model.ts +128 -0
  51. package/extensions/ready/packs.ts +272 -0
  52. package/extensions/ready/render.ts +445 -0
  53. package/extensions/ready/scan.ts +760 -0
  54. package/extensions/reference/panel.ts +28 -16
  55. package/extensions/review/index.ts +63 -51
  56. package/extensions/review/panel.ts +5 -34
  57. package/extensions/runtime-context/context.ts +30 -26
  58. package/extensions/script-runner/README.md +2 -2
  59. package/extensions/script-runner/index.ts +122 -82
  60. package/extensions/silent-command-runner/index.ts +38 -23
  61. package/extensions/subagent/agents/context-sync.md +185 -33
  62. package/extensions/subagent/agents/scout.md +2 -2
  63. package/extensions/subagent/agents.ts +137 -84
  64. package/extensions/subagent/cmux-dashboard.ts +39 -30
  65. package/extensions/subagent/index.ts +79 -59
  66. package/extensions/subagent/resume.ts +1 -1
  67. package/extensions/subagent/run.ts +304 -193
  68. package/extensions/subagent/runtime.ts +781 -343
  69. package/extensions/tau/index.ts +47 -38
  70. package/extensions/tau-help/help.md +14 -6
  71. package/extensions/tool-loader/README.md +4 -2
  72. package/extensions/tool-loader/index.ts +77 -52
  73. package/extensions/web/index.ts +6 -3
  74. package/extensions/web/webfetch.ts +114 -86
  75. package/package.json +3 -3
  76. package/schemas/tau.schema.json +20 -33
  77. package/shared/bounded-text-result.ts +1 -0
  78. package/shared/checkpoint-visibility.ts +9 -0
  79. package/shared/events.ts +28 -10
  80. package/shared/isolated-session.ts +71 -29
  81. package/shared/model-effort.ts +9 -19
  82. package/shared/model-fallback/index.ts +66 -41
  83. package/shared/settings/load.ts +45 -38
  84. package/shared/temporary-output-store.ts +16 -10
  85. package/{extensions/explore → src}/ast/adapter.ts +11 -2
  86. package/{extensions/explore → src}/ast/engine.ts +54 -38
  87. package/{extensions/explore → src}/ast/format/ast-search.ts +15 -6
  88. package/{extensions/explore → src}/ast/format/context.ts +3 -6
  89. package/src/ast/format/deps.ts +94 -0
  90. package/{extensions/explore → src}/ast/format/discover.ts +2 -2
  91. package/{extensions/explore → src}/ast/format/impact.ts +9 -11
  92. package/{extensions/explore → src}/ast/format/outline.ts +2 -2
  93. package/{extensions/explore → src}/ast/format/relationships.ts +11 -7
  94. package/{extensions/explore → src}/ast/format/show.ts +1 -1
  95. package/src/ast/format/targeted-result.ts +20 -0
  96. package/src/ast/grammars/c_sharp.wasm +0 -0
  97. package/{extensions/explore → src}/ast/grammars/manifest.json +9 -12
  98. package/{extensions/explore → src}/ast/grammars/manifest.ts +0 -4
  99. package/{extensions/explore → src}/ast/graph/file-graph.ts +210 -98
  100. package/{extensions/explore → src}/ast/graph/relationships.ts +285 -72
  101. package/{extensions/explore → src}/ast/ir.ts +6 -0
  102. package/src/ast/languages/csharp-file-deps.ts +90 -0
  103. package/{extensions/explore → src}/ast/languages/csharp.ts +9 -40
  104. package/src/ast/languages/dotted-index.ts +131 -0
  105. package/{extensions/explore → src}/ast/languages/file-dep-util.ts +22 -13
  106. package/src/ast/languages/fixtures/sample.cs +53 -0
  107. package/src/ast/languages/fixtures/sample.cs.expected.json +156 -0
  108. package/src/ast/languages/fixtures/sample.go +37 -0
  109. package/src/ast/languages/fixtures/sample.go.expected.json +96 -0
  110. package/src/ast/languages/fixtures/sample.java +40 -0
  111. package/src/ast/languages/fixtures/sample.java.expected.json +126 -0
  112. package/src/ast/languages/fixtures/sample.kt +31 -0
  113. package/src/ast/languages/fixtures/sample.kt.expected.json +134 -0
  114. package/src/ast/languages/fixtures/sample.md +23 -0
  115. package/src/ast/languages/fixtures/sample.md.expected.json +44 -0
  116. package/src/ast/languages/fixtures/sample.rs +54 -0
  117. package/src/ast/languages/fixtures/sample.rs.expected.json +178 -0
  118. package/src/ast/languages/fixtures/sample.swift +45 -0
  119. package/src/ast/languages/fixtures/sample.swift.expected.json +147 -0
  120. package/src/ast/languages/fixtures/sample.ts +45 -0
  121. package/src/ast/languages/fixtures/sample.ts.expected.json +141 -0
  122. package/src/ast/languages/fixtures/sample.tsx +36 -0
  123. package/src/ast/languages/fixtures/sample.tsx.expected.json +59 -0
  124. package/{extensions/explore → src}/ast/languages/go-file-deps.ts +6 -0
  125. package/{extensions/explore → src}/ast/languages/go.ts +21 -3
  126. package/{extensions/explore → src}/ast/languages/java.ts +5 -38
  127. package/src/ast/languages/jvm-file-deps.ts +135 -0
  128. package/{extensions/explore → src}/ast/languages/kotlin.ts +5 -39
  129. package/{extensions/explore → src}/ast/languages/rust-file-deps.ts +3 -3
  130. package/{extensions/explore → src}/ast/languages/rust.ts +21 -13
  131. package/{extensions/explore → src}/ast/languages/swift-file-deps.ts +22 -15
  132. package/{extensions/explore → src}/ast/languages/swift.ts +9 -39
  133. package/{extensions/explore → src}/ast/languages/tree.ts +47 -0
  134. package/{extensions/explore → src}/ast/languages/typescript-file-deps.ts +108 -0
  135. package/{extensions/explore → src}/ast/languages/typescript-package-surface.ts +4 -3
  136. package/{extensions/explore → src}/ast/languages/typescript.ts +3 -5
  137. package/{extensions/explore → src}/ast/markdown.ts +72 -47
  138. package/{extensions/explore → src}/ast/queries/ast-search.ts +164 -146
  139. package/{extensions/explore → src}/ast/queries/composite-target.ts +1 -1
  140. package/{extensions/explore → src}/ast/queries/context.ts +116 -80
  141. package/{extensions/explore → src}/ast/queries/discover.ts +154 -105
  142. package/src/ast/queries/impact.ts +291 -0
  143. package/{extensions/explore → src}/ast/queries/outline.ts +4 -2
  144. package/{extensions/explore → src}/ast/queries/show.ts +46 -42
  145. package/{extensions/explore → src}/ast/query.ts +1 -1
  146. package/{extensions/explore → src}/ast/registry.ts +1 -2
  147. package/{extensions/explore → src}/ast/scan.ts +1 -1
  148. package/src/ast/session.ts +50 -0
  149. package/{extensions/explore → src}/ast/slice.ts +8 -0
  150. package/{extensions/explore → src/ast}/traverse.ts +32 -20
  151. package/src/file-injection/index.ts +547 -0
  152. package/src/image-generation/client.ts +50 -31
  153. package/src/image-generation/index.ts +177 -134
  154. package/src/index.ts +2 -0
  155. package/src/tool-loading/index.ts +58 -0
  156. package/extensions/context/evidence.ts +0 -517
  157. package/extensions/context/projection.ts +0 -141
  158. package/extensions/context/state.ts +0 -30
  159. package/extensions/context/write-scope.ts +0 -109
  160. package/extensions/explore/ast/format/deps.ts +0 -86
  161. package/extensions/explore/ast/grammars/odin.wasm +0 -0
  162. package/extensions/explore/ast/languages/csharp-file-deps.ts +0 -189
  163. package/extensions/explore/ast/languages/fixtures/sample.cs +0 -17
  164. package/extensions/explore/ast/languages/fixtures/sample.java +0 -21
  165. package/extensions/explore/ast/languages/fixtures/sample.kt +0 -15
  166. package/extensions/explore/ast/languages/fixtures/sample.odin +0 -28
  167. package/extensions/explore/ast/languages/fixtures/sample.rs +0 -31
  168. package/extensions/explore/ast/languages/fixtures/sample.swift +0 -25
  169. package/extensions/explore/ast/languages/jvm-file-deps.ts +0 -217
  170. package/extensions/explore/ast/languages/odin-file-deps.ts +0 -175
  171. package/extensions/explore/ast/languages/odin.ts +0 -407
  172. package/extensions/explore/ast/queries/impact.ts +0 -250
  173. package/extensions/explore/outline-injection.ts +0 -151
  174. package/extensions/explore/read/autoread.ts +0 -118
  175. package/extensions/working-memory/README.md +0 -17
  176. package/extensions/working-memory/checkpoint.ts +0 -242
  177. package/extensions/working-memory/index.ts +0 -341
  178. package/extensions/working-memory/memory.ts +0 -235
  179. package/extensions/working-memory/render.ts +0 -185
  180. package/extensions/working-memory/settings.ts +0 -38
  181. package/extensions/working-memory/state.ts +0 -158
  182. package/shared/autoread.ts +0 -234
  183. package/shared/context-messages.ts +0 -19
  184. package/shared/outline-injection.ts +0 -56
  185. /package/{extensions/explore → src}/ast/format/composite.ts +0 -0
  186. /package/{extensions/explore → src}/ast/grammars/kotlin.wasm +0 -0
  187. /package/{extensions/explore → src}/ast/grammars/swift.wasm +0 -0
  188. /package/{extensions/explore → src}/ast/identity.ts +0 -0
  189. /package/{extensions/explore → src}/ast/package-surface.ts +0 -0
  190. /package/{extensions/explore/ast/read/policy.ts → src/ast/read-policy.ts} +0 -0
@@ -3,17 +3,15 @@ import type { ExtractResult, GrammarAdapter, LanguageCapabilities } from "../ada
3
3
  import { resolveCsharpFileDep } from "./csharp-file-deps.ts";
4
4
  import type { CallSite, Decl, ImportRef, Visibility } from "../ir.ts";
5
5
  import {
6
- applyDoc,
7
6
  callSite,
7
+ type DocSpan,
8
8
  docSpanBefore,
9
- endLine,
10
9
  field,
11
- finishDecl,
10
+ createLeafBuilder,
12
11
  nameText,
13
12
  qualify,
14
13
  startLine,
15
14
  walkBodyNodes,
16
- type DocSpan,
17
15
  } from "./tree.ts";
18
16
 
19
17
  const CAPABILITIES: LanguageCapabilities = {
@@ -22,6 +20,7 @@ const CAPABILITIES: LanguageCapabilities = {
22
20
  fileDeps: true,
23
21
  callEdges: true,
24
22
  packageSurface: false,
23
+ structuralImplements: false,
25
24
  };
26
25
 
27
26
  const IMPORT_NOISE = new Set([
@@ -244,39 +243,7 @@ function bodyOf(node: Node): Node | null {
244
243
  return field(node, "body") ?? field(node, "accessors") ?? field(node, "value");
245
244
  }
246
245
 
247
- function leaf(
248
- node: Node,
249
- owner: string,
250
- kind: Decl["kind"],
251
- name: string,
252
- visibility: Visibility,
253
- body: Node | null,
254
- children: Decl[],
255
- doc: DocSpan | undefined,
256
- ): Decl | undefined {
257
- if (name.length === 0) return undefined;
258
- const callable = kind === "function" || kind === "method" || kind === "constructor";
259
- const typeLike = kind === "class" || kind === "interface" || kind === "enum" || kind === "struct";
260
- const decl = finishDecl(
261
- {
262
- kind,
263
- name,
264
- qualifiedName: qualify(owner, name),
265
- startLine: startLine(node),
266
- endLine: endLine(node),
267
- startOffset: node.startIndex,
268
- endOffset: node.endIndex,
269
- visibility,
270
- exported: visibility === "public",
271
- children,
272
- calls: callable ? extractCalls(body) : [],
273
- bases: typeLike ? heritageBases(node) : [],
274
- },
275
- body,
276
- );
277
- if (body === null) decl.signatureEndOffset = node.endIndex;
278
- return applyDoc(decl, doc);
279
- }
246
+ const leaf = createLeafBuilder(extractCalls, heritageBases);
280
247
 
281
248
  function variableNames(declaration: Node | null): string[] {
282
249
  if (declaration === null || declaration.type !== VARIABLE_DECLARATION) return [];
@@ -430,9 +397,11 @@ function collectImports(root: Node): ImportRef[] {
430
397
  const imports: ImportRef[] = [];
431
398
  for (const node of root.namedChildren) {
432
399
  if (node.type !== USING_DIRECTIVE) continue;
433
- // using X; / using static X; — take full directive text minus keyword noise via child names.
400
+ // using X; / using static X; / using Alias = X.Y; — the imported target is the
401
+ // last name child, so an alias name never masks what it points at.
434
402
  const nameNode =
435
- node.namedChildren.find((child) => child.type === "identifier" || child.type === "qualified_name") ?? null;
403
+ node.namedChildren.filter((child) => child.type === "identifier" || child.type === "qualified_name").at(-1) ??
404
+ null;
436
405
  const specifier = nameNode === null ? node.text.replace(/^using\s+/, "").replace(/;$/, "") : nameNode.text;
437
406
  imports.push({
438
407
  specifier,
@@ -477,7 +446,7 @@ function extractCsharp(tree: Tree, source: string): ExtractResult {
477
446
  }
478
447
  }
479
448
 
480
- return { decls, imports: collectImports(root) };
449
+ return { decls, imports: collectImports(root), fileCalls: extractCalls(root) };
481
450
  }
482
451
 
483
452
  export function csharpAdapter(): GrammarAdapter {
@@ -0,0 +1,131 @@
1
+ import { dirname, relative, resolve, sep } from "node:path";
2
+ import type { FileDepHost } from "../adapter.ts";
3
+ import { collectFilesWithExtensions, pickClosestPath, readTextFile } from "./file-dep-util.ts";
4
+
5
+ /**
6
+ * Shared resolution index for dotted-namespace languages (C#, Java, Kotlin).
7
+ *
8
+ * Two lookups, both from one scan: a dotted type FQN → the file declaring it,
9
+ * and a dotted package → the directory holding it. Path-stem suffixes cover
10
+ * layouts where file name equals type name; declared-name keys cover the rest
11
+ * (Kotlin files whose name differs from their types, C# multi-type files).
12
+ */
13
+
14
+ /** One declared type or top-level member, with the dotted package it sits in. */
15
+ export type DeclaredName = { pkg: string; name: string };
16
+
17
+ /** What a language pulls out of a file head. */
18
+ export type HeadScan = { packages: string[]; names: DeclaredName[] };
19
+
20
+ export type DottedIndex = {
21
+ /** slash key (path stems and `pkg/Name` FQNs) → files */
22
+ bySuffix: Map<string, string[]>;
23
+ /** package slash key → directories holding its files, plus that file count */
24
+ byPackage: Map<string, { dirs: string[]; fileCount: number }>;
25
+ };
26
+
27
+ /** Enough of a file to carry its package/namespace and top-level declarations. */
28
+ const HEAD_CHARS = 12000;
29
+
30
+ function slashKey(dotted: string): string {
31
+ return dotted.replace(/\./gu, "/");
32
+ }
33
+
34
+ function pushSuffix(map: Map<string, string[]>, key: string, file: string): void {
35
+ if (key.length === 0) return;
36
+ const list = map.get(key);
37
+ if (list === undefined) map.set(key, [file]);
38
+ else if (!list.includes(file)) list.push(file);
39
+ }
40
+
41
+ /** Index every slash-suffix of a stem path: a/b/c → a/b/c, b/c, c */
42
+ function indexPathSuffixes(map: Map<string, string[]>, file: string, stemRelPosix: string): void {
43
+ const parts = stemRelPosix.split("/").filter((part) => part.length > 0);
44
+ for (let i = 0; i < parts.length; i += 1) {
45
+ pushSuffix(map, parts.slice(i).join("/"), file);
46
+ }
47
+ }
48
+
49
+ function toPosixRel(scopeRoot: string, file: string): string | undefined {
50
+ const rel = relative(resolve(scopeRoot), resolve(file));
51
+ if (rel.startsWith(`..${sep}`) || rel === ".." || rel.length === 0) return undefined;
52
+ return rel.split(sep).join("/");
53
+ }
54
+
55
+ export async function buildDottedIndex(
56
+ host: FileDepHost,
57
+ memoPrefix: string,
58
+ extensions: readonly string[],
59
+ scanHead: (head: string) => HeadScan,
60
+ signal: AbortSignal,
61
+ ): Promise<DottedIndex> {
62
+ const key = `${memoPrefix}:${host.scopeRoot}`;
63
+ const cached = host.memo.get(key);
64
+ if (cached !== undefined) return cached as DottedIndex;
65
+
66
+ const bySuffix = new Map<string, string[]>();
67
+ const byPackage = new Map<string, { dirs: string[]; fileCount: number }>();
68
+ const files = await collectFilesWithExtensions(host, host.scopeRoot, extensions, signal);
69
+
70
+ for (const file of files) {
71
+ signal.throwIfAborted();
72
+ const rel = toPosixRel(host.scopeRoot, file);
73
+ if (rel === undefined) continue;
74
+ const dot = rel.lastIndexOf(".");
75
+ indexPathSuffixes(bySuffix, file, dot >= 0 ? rel.slice(0, dot) : rel);
76
+
77
+ const text = await readTextFile(file);
78
+ if (text === undefined) continue;
79
+ const scan = scanHead(text.slice(0, HEAD_CHARS));
80
+ const packages = new Set(scan.packages);
81
+ for (const declared of scan.names) {
82
+ if (declared.pkg.length === 0 || declared.name.length === 0) continue;
83
+ packages.add(declared.pkg);
84
+ pushSuffix(bySuffix, `${slashKey(declared.pkg)}/${declared.name}`, file);
85
+ }
86
+ const dir = dirname(file);
87
+ for (const pkg of packages) {
88
+ if (pkg.length === 0) continue;
89
+ const entry = byPackage.get(slashKey(pkg));
90
+ if (entry === undefined) byPackage.set(slashKey(pkg), { dirs: [dir], fileCount: 1 });
91
+ else {
92
+ if (!entry.dirs.includes(dir)) entry.dirs.push(dir);
93
+ entry.fileCount += 1;
94
+ }
95
+ }
96
+ }
97
+
98
+ for (const [, list] of bySuffix) list.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
99
+ const index: DottedIndex = { bySuffix, byPackage };
100
+ host.memo.set(key, index);
101
+ return index;
102
+ }
103
+
104
+ /** Dotted type FQN → declaring file, with a nested-type fallback to the outer type. */
105
+ export function resolveDottedFile(index: DottedIndex, fromPath: string, dotted: string): string | undefined {
106
+ const key = slashKey(dotted);
107
+ const hit = pickClosestPath(index.bySuffix.get(key) ?? [], fromPath);
108
+ if (hit !== undefined) return hit;
109
+
110
+ // Nested type: Foo.Bar.Inner → try the Foo.Bar file.
111
+ const slash = key.lastIndexOf("/");
112
+ if (slash <= 0) return undefined;
113
+ return pickClosestPath(index.bySuffix.get(key.slice(0, slash)) ?? [], fromPath);
114
+ }
115
+
116
+ /**
117
+ * Dotted package → its directory. The importer's own directory is not an edge:
118
+ * same-directory files are visible without an import.
119
+ */
120
+ export function resolveDottedPackage(
121
+ index: DottedIndex,
122
+ fromPath: string,
123
+ dotted: string,
124
+ ): { dir: string; fileCount: number } | undefined {
125
+ const entry = index.byPackage.get(slashKey(dotted));
126
+ if (entry === undefined) return undefined;
127
+ const dir = pickClosestPath(entry.dirs, fromPath);
128
+ if (dir === undefined) return undefined;
129
+ if (resolve(dir) === resolve(dirname(fromPath))) return undefined;
130
+ return { dir, fileCount: entry.fileCount };
131
+ }
@@ -17,19 +17,28 @@ export function externalId(id: string): FileDepResolution {
17
17
  return { kind: "external", id };
18
18
  }
19
19
 
20
- /**
21
- * Prefer a short internal path list. Large fan-out becomes an external id so
22
- * namespace/package imports stay agent-usable instead of dumping whole trees.
23
- */
24
- export function boundedInternalPaths(
25
- paths: readonly string[],
26
- externalFallback: string,
27
- maxFiles = 12,
28
- ): FileDepResolution {
29
- const unique = [...new Set(paths.map((path) => resolve(path)))].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
30
- if (unique.length === 0) return { kind: "unresolved" };
31
- if (unique.length > maxFiles) return externalId(externalFallback);
32
- return { kind: "internal", paths: unique };
20
+ /** In-repo directory edge: a namespace/module/package import that would dump a whole tree. */
21
+ export function packageDirectory(id: string, dir: string, fileCount: number): FileDepResolution {
22
+ return { kind: "package", id, dir: resolve(dir), fileCount };
23
+ }
24
+
25
+ /** Prefer the candidate sharing the most path prefix with the importer. */
26
+ export function pickClosestPath(candidates: readonly string[], fromPath: string): string | undefined {
27
+ if (candidates.length <= 1) return candidates[0];
28
+ const fromSegs = resolve(fromPath).split(sep);
29
+ let best: string | undefined;
30
+ let bestCommon = -1;
31
+ for (const candidate of candidates) {
32
+ const segs = resolve(candidate).split(sep);
33
+ let common = 0;
34
+ const n = Math.min(fromSegs.length, segs.length);
35
+ while (common < n && fromSegs[common] === segs[common]) common += 1;
36
+ if (best === undefined || common > bestCommon || (common === bestCommon && candidate < best)) {
37
+ best = candidate;
38
+ bestCommon = common;
39
+ }
40
+ }
41
+ return best;
33
42
  }
34
43
 
35
44
  export async function firstExistingFile(host: FileDepHost, candidates: readonly string[]): Promise<string | undefined> {
@@ -0,0 +1,53 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+
4
+ namespace Demo;
5
+
6
+ /// <summary>Greeter</summary>
7
+ public class Greeter : IGreeter
8
+ {
9
+ private int count;
10
+
11
+ public string Name { get; set; } = "";
12
+
13
+ public Greeter() {}
14
+
15
+ public Greeter(string name)
16
+ {
17
+ Name = name;
18
+ }
19
+
20
+ public void Hello()
21
+ {
22
+ count += 1;
23
+ }
24
+
25
+ public event EventHandler? Done;
26
+
27
+ public string this[int index] => Name;
28
+ }
29
+
30
+ internal struct Box
31
+ {
32
+ public int Value;
33
+ }
34
+
35
+ public interface IGreeter
36
+ {
37
+ void Hello();
38
+ }
39
+
40
+ public enum Color
41
+ {
42
+ Red,
43
+ Green,
44
+ }
45
+
46
+ public record Person(string Name);
47
+
48
+ public delegate void Notify(string message);
49
+
50
+ static class Helpers
51
+ {
52
+ public static IEnumerable<int> Range(int n) => System.Linq.Enumerable.Range(0, n);
53
+ }
@@ -0,0 +1,156 @@
1
+ {
2
+ "languageId": "c_sharp",
3
+ "parseDegraded": false,
4
+ "imports": [
5
+ "System",
6
+ "System.Collections.Generic"
7
+ ],
8
+ "decls": [
9
+ {
10
+ "kind": "namespace",
11
+ "qualifiedName": "Demo",
12
+ "visibility": "public",
13
+ "exported": true,
14
+ "children": [
15
+ {
16
+ "kind": "class",
17
+ "qualifiedName": "Demo.Greeter",
18
+ "visibility": "public",
19
+ "exported": true,
20
+ "children": [
21
+ {
22
+ "kind": "field",
23
+ "qualifiedName": "Demo.Greeter.count",
24
+ "visibility": "private",
25
+ "exported": false,
26
+ "children": []
27
+ },
28
+ {
29
+ "kind": "property",
30
+ "qualifiedName": "Demo.Greeter.Name",
31
+ "visibility": "public",
32
+ "exported": true,
33
+ "children": []
34
+ },
35
+ {
36
+ "kind": "constructor",
37
+ "qualifiedName": "Demo.Greeter.Greeter",
38
+ "visibility": "public",
39
+ "exported": true,
40
+ "children": []
41
+ },
42
+ {
43
+ "kind": "constructor",
44
+ "qualifiedName": "Demo.Greeter.Greeter",
45
+ "visibility": "public",
46
+ "exported": true,
47
+ "children": []
48
+ },
49
+ {
50
+ "kind": "method",
51
+ "qualifiedName": "Demo.Greeter.Hello",
52
+ "visibility": "public",
53
+ "exported": true,
54
+ "children": []
55
+ },
56
+ {
57
+ "kind": "event",
58
+ "qualifiedName": "Demo.Greeter.Done",
59
+ "visibility": "public",
60
+ "exported": true,
61
+ "children": []
62
+ },
63
+ {
64
+ "kind": "property",
65
+ "qualifiedName": "Demo.Greeter.this",
66
+ "visibility": "public",
67
+ "exported": true,
68
+ "children": []
69
+ }
70
+ ]
71
+ },
72
+ {
73
+ "kind": "struct",
74
+ "qualifiedName": "Demo.Box",
75
+ "visibility": "internal",
76
+ "exported": false,
77
+ "children": [
78
+ {
79
+ "kind": "field",
80
+ "qualifiedName": "Demo.Box.Value",
81
+ "visibility": "public",
82
+ "exported": true,
83
+ "children": []
84
+ }
85
+ ]
86
+ },
87
+ {
88
+ "kind": "interface",
89
+ "qualifiedName": "Demo.IGreeter",
90
+ "visibility": "public",
91
+ "exported": true,
92
+ "children": [
93
+ {
94
+ "kind": "method",
95
+ "qualifiedName": "Demo.IGreeter.Hello",
96
+ "visibility": "public",
97
+ "exported": true,
98
+ "children": []
99
+ }
100
+ ]
101
+ },
102
+ {
103
+ "kind": "enum",
104
+ "qualifiedName": "Demo.Color",
105
+ "visibility": "public",
106
+ "exported": true,
107
+ "children": [
108
+ {
109
+ "kind": "enumMember",
110
+ "qualifiedName": "Demo.Color.Red",
111
+ "visibility": "public",
112
+ "exported": true,
113
+ "children": []
114
+ },
115
+ {
116
+ "kind": "enumMember",
117
+ "qualifiedName": "Demo.Color.Green",
118
+ "visibility": "public",
119
+ "exported": true,
120
+ "children": []
121
+ }
122
+ ]
123
+ },
124
+ {
125
+ "kind": "class",
126
+ "qualifiedName": "Demo.Person",
127
+ "visibility": "public",
128
+ "exported": true,
129
+ "children": []
130
+ },
131
+ {
132
+ "kind": "function",
133
+ "qualifiedName": "Demo.Notify",
134
+ "visibility": "public",
135
+ "exported": true,
136
+ "children": []
137
+ },
138
+ {
139
+ "kind": "class",
140
+ "qualifiedName": "Demo.Helpers",
141
+ "visibility": "internal",
142
+ "exported": false,
143
+ "children": [
144
+ {
145
+ "kind": "method",
146
+ "qualifiedName": "Demo.Helpers.Range",
147
+ "visibility": "public",
148
+ "exported": true,
149
+ "children": []
150
+ }
151
+ ]
152
+ }
153
+ ]
154
+ }
155
+ ]
156
+ }
@@ -0,0 +1,37 @@
1
+ package demo
2
+
3
+ import (
4
+ "fmt"
5
+ "io"
6
+ )
7
+
8
+ // Greeter greets callers.
9
+ type Greeter struct {
10
+ Name string
11
+ count int
12
+ }
13
+
14
+ // Hello prints a greeting.
15
+ func (g *Greeter) Hello() {
16
+ fmt.Println("hi", g.Name)
17
+ }
18
+
19
+ type Writer interface {
20
+ io.Writer
21
+ Flush() error
22
+ }
23
+
24
+ type Color int
25
+
26
+ const (
27
+ Red Color = iota
28
+ Green
29
+ )
30
+
31
+ var DefaultName = "world"
32
+
33
+ func NewGreeter(name string) *Greeter {
34
+ return &Greeter{Name: name}
35
+ }
36
+
37
+ func hidden() {}
@@ -0,0 +1,96 @@
1
+ {
2
+ "languageId": "go",
3
+ "parseDegraded": false,
4
+ "imports": [
5
+ "fmt",
6
+ "io"
7
+ ],
8
+ "decls": [
9
+ {
10
+ "kind": "struct",
11
+ "qualifiedName": "Greeter",
12
+ "visibility": "public",
13
+ "exported": true,
14
+ "children": [
15
+ {
16
+ "kind": "field",
17
+ "qualifiedName": "Greeter.Name",
18
+ "visibility": "public",
19
+ "exported": true,
20
+ "children": []
21
+ },
22
+ {
23
+ "kind": "field",
24
+ "qualifiedName": "Greeter.count",
25
+ "visibility": "internal",
26
+ "exported": false,
27
+ "children": []
28
+ }
29
+ ]
30
+ },
31
+ {
32
+ "kind": "method",
33
+ "qualifiedName": "Greeter.Hello",
34
+ "visibility": "public",
35
+ "exported": true,
36
+ "children": []
37
+ },
38
+ {
39
+ "kind": "interface",
40
+ "qualifiedName": "Writer",
41
+ "visibility": "public",
42
+ "exported": true,
43
+ "children": [
44
+ {
45
+ "kind": "method",
46
+ "qualifiedName": "Writer.Flush",
47
+ "visibility": "public",
48
+ "exported": true,
49
+ "children": []
50
+ }
51
+ ]
52
+ },
53
+ {
54
+ "kind": "type",
55
+ "qualifiedName": "Color",
56
+ "visibility": "public",
57
+ "exported": true,
58
+ "children": []
59
+ },
60
+ {
61
+ "kind": "constant",
62
+ "qualifiedName": "Red",
63
+ "visibility": "public",
64
+ "exported": true,
65
+ "children": []
66
+ },
67
+ {
68
+ "kind": "constant",
69
+ "qualifiedName": "Green",
70
+ "visibility": "public",
71
+ "exported": true,
72
+ "children": []
73
+ },
74
+ {
75
+ "kind": "variable",
76
+ "qualifiedName": "DefaultName",
77
+ "visibility": "public",
78
+ "exported": true,
79
+ "children": []
80
+ },
81
+ {
82
+ "kind": "function",
83
+ "qualifiedName": "NewGreeter",
84
+ "visibility": "public",
85
+ "exported": true,
86
+ "children": []
87
+ },
88
+ {
89
+ "kind": "function",
90
+ "qualifiedName": "hidden",
91
+ "visibility": "internal",
92
+ "exported": false,
93
+ "children": []
94
+ }
95
+ ]
96
+ }
@@ -0,0 +1,40 @@
1
+ package com.demo;
2
+
3
+ import java.util.List;
4
+ import java.util.ArrayList;
5
+
6
+ /** Greeter type. */
7
+ public class Greeter implements Named {
8
+ private int count;
9
+ public static final int MAX = 10;
10
+
11
+ public Greeter() {}
12
+
13
+ public Greeter(String name) {
14
+ this.count = name.length();
15
+ }
16
+
17
+ public void hello() {
18
+ count += 1;
19
+ }
20
+
21
+ @Override
22
+ public void name() {}
23
+ }
24
+
25
+ interface Named {
26
+ void name();
27
+ }
28
+
29
+ enum Color {
30
+ RED,
31
+ GREEN;
32
+
33
+ void paint() {}
34
+ }
35
+
36
+ record Point(int x, int y) {}
37
+
38
+ @interface Internal {
39
+ String value() default "";
40
+ }