@shanepadgett/tau-agent 0.27.0 → 0.28.1
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/extensions/context/sync.ts +1 -9
- package/extensions/context-pruning/prune.ts +2 -2
- package/extensions/explore/README.md +13 -21
- package/extensions/explore/ast/adapter.ts +97 -0
- package/extensions/explore/ast/engine.ts +470 -0
- package/extensions/explore/ast/format/ast-search.ts +97 -0
- package/extensions/explore/ast/format/composite.ts +26 -0
- package/extensions/explore/ast/format/context.ts +66 -0
- package/extensions/explore/ast/format/deps.ts +86 -0
- package/extensions/explore/ast/format/discover.ts +85 -0
- package/extensions/explore/ast/format/impact.ts +105 -0
- package/extensions/explore/ast/format/outline.ts +66 -0
- package/extensions/explore/ast/format/relationships.ts +81 -0
- package/extensions/explore/ast/format/show.ts +38 -0
- package/extensions/explore/ast/grammars/kotlin.wasm +0 -0
- package/extensions/explore/ast/grammars/manifest.json +41 -0
- package/extensions/explore/ast/grammars/manifest.ts +99 -0
- package/extensions/explore/ast/grammars/odin.wasm +0 -0
- package/extensions/explore/ast/grammars/swift.wasm +0 -0
- package/extensions/explore/ast/graph/file-graph.ts +360 -0
- package/extensions/explore/ast/graph/relationships.ts +597 -0
- package/extensions/explore/ast/identity.ts +119 -0
- package/extensions/explore/ast/ir.ts +136 -0
- package/extensions/explore/ast/languages/csharp-file-deps.ts +189 -0
- package/extensions/explore/ast/languages/csharp.ts +493 -0
- package/extensions/explore/ast/languages/file-dep-util.ts +120 -0
- package/extensions/explore/ast/languages/fixtures/sample.cs +17 -0
- package/extensions/explore/ast/languages/fixtures/sample.java +21 -0
- package/extensions/explore/ast/languages/fixtures/sample.kt +15 -0
- package/extensions/explore/ast/languages/fixtures/sample.odin +28 -0
- package/extensions/explore/ast/languages/fixtures/sample.rs +31 -0
- package/extensions/explore/ast/languages/fixtures/sample.swift +25 -0
- package/extensions/explore/ast/languages/go-file-deps.ts +139 -0
- package/extensions/explore/ast/languages/go.ts +545 -0
- package/extensions/explore/ast/languages/java.ts +412 -0
- package/extensions/explore/ast/languages/jvm-file-deps.ts +217 -0
- package/extensions/explore/ast/languages/kotlin.ts +611 -0
- package/extensions/explore/ast/languages/odin-file-deps.ts +175 -0
- package/extensions/explore/ast/languages/odin.ts +407 -0
- package/extensions/explore/ast/languages/rust-file-deps.ts +159 -0
- package/extensions/explore/ast/languages/rust.ts +506 -0
- package/extensions/explore/ast/languages/swift-file-deps.ts +59 -0
- package/extensions/explore/ast/languages/swift.ts +466 -0
- package/extensions/explore/ast/languages/tree.ts +220 -0
- package/extensions/explore/ast/languages/typescript-file-deps.ts +259 -0
- package/extensions/explore/ast/languages/typescript-package-surface.ts +440 -0
- package/extensions/explore/ast/languages/typescript.ts +751 -0
- package/extensions/explore/ast/markdown.ts +145 -0
- package/extensions/explore/ast/package-surface.ts +42 -0
- package/extensions/explore/ast/queries/ast-search.ts +306 -0
- package/extensions/explore/ast/queries/composite-target.ts +77 -0
- package/extensions/explore/ast/queries/context.ts +406 -0
- package/extensions/explore/ast/queries/discover.ts +427 -0
- package/extensions/explore/ast/queries/impact.ts +250 -0
- package/extensions/explore/ast/queries/outline.ts +203 -0
- package/extensions/explore/ast/queries/show.ts +262 -0
- package/extensions/explore/ast/query.ts +48 -0
- package/extensions/explore/ast/read/hook.ts +125 -0
- package/extensions/explore/ast/read/policy.ts +55 -0
- package/extensions/explore/ast/registry.ts +120 -0
- package/extensions/explore/ast/scan.ts +76 -0
- package/extensions/explore/ast/slice.ts +44 -0
- package/extensions/explore/ast/tools/ast-search.ts +138 -0
- package/extensions/explore/ast/tools/context.ts +126 -0
- package/extensions/explore/ast/tools/deps.ts +72 -0
- package/extensions/explore/ast/tools/discover.ts +208 -0
- package/extensions/explore/ast/tools/impact.ts +135 -0
- package/extensions/explore/ast/tools/outline.ts +200 -0
- package/extensions/explore/ast/tools/relationships.ts +160 -0
- package/extensions/explore/ast/tools/render.ts +121 -0
- package/extensions/explore/ast/tools/reverse-deps.ts +72 -0
- package/extensions/explore/ast/tools/show.ts +116 -0
- package/extensions/explore/guidance.ts +52 -0
- package/extensions/explore/index.ts +82 -92
- package/extensions/explore/read/autoread.ts +118 -0
- package/extensions/explore/settings.ts +49 -31
- package/extensions/explore/traverse.ts +254 -91
- package/extensions/handoff/index.ts +1 -1
- package/extensions/publish/index.ts +18 -85
- package/extensions/publish/publish-ui.ts +0 -4
- package/extensions/soul/README.md +7 -4
- package/extensions/soul/index.ts +11 -5
- package/extensions/soul/prompt.ts +31 -13
- package/extensions/soul/settings.ts +7 -2
- package/extensions/subagent/agents/context-sync.md +6 -10
- package/extensions/subagent/agents/review.md +24 -55
- package/extensions/subagent/agents/scout.md +38 -115
- package/extensions/subagent/run.ts +1 -1
- package/extensions/tau-help/help.md +2 -4
- package/package.json +6 -4
- package/schemas/tau.schema.json +35 -30
- package/{extensions/explore → shared}/autoread.ts +21 -7
- package/shared/events.ts +1 -1
- package/shared/full-file-knowledge.ts +49 -0
- package/extensions/explore/ast-guidance.ts +0 -67
- package/extensions/explore/ast-languages.ts +0 -61
- package/extensions/explore/ast-tools.ts +0 -1994
- package/extensions/explore/ast-worker.ts +0 -1025
- package/extensions/explore/find.ts +0 -147
- package/extensions/explore/full-file-knowledge.ts +0 -234
- package/extensions/explore/grep.ts +0 -749
- package/extensions/explore/limits.ts +0 -22
- package/extensions/explore/ls.ts +0 -113
- package/extensions/explore/orientation-state.ts +0 -280
- package/extensions/explore/path-display.ts +0 -41
- package/extensions/explore/path-tree.ts +0 -150
- package/extensions/explore/read-cache.ts +0 -273
- package/extensions/explore/read-snapshots.ts +0 -57
- package/extensions/explore/read-stats-panel.ts +0 -176
- package/extensions/explore/read-stats.ts +0 -138
- package/extensions/explore/read.ts +0 -372
- package/extensions/explore/result.ts +0 -29
- package/native-bin/darwin-arm64/tau-ast +0 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/** Shared declaration-kind vocabulary. Extend only for a real new kind. */
|
|
2
|
+
export type DeclKind =
|
|
3
|
+
| "module"
|
|
4
|
+
| "namespace"
|
|
5
|
+
| "package"
|
|
6
|
+
| "class"
|
|
7
|
+
| "method"
|
|
8
|
+
| "property"
|
|
9
|
+
| "field"
|
|
10
|
+
| "constructor"
|
|
11
|
+
| "enum"
|
|
12
|
+
| "interface"
|
|
13
|
+
| "type"
|
|
14
|
+
| "typeAlias"
|
|
15
|
+
| "function"
|
|
16
|
+
| "variable"
|
|
17
|
+
| "constant"
|
|
18
|
+
| "object"
|
|
19
|
+
| "enumMember"
|
|
20
|
+
| "struct"
|
|
21
|
+
| "event"
|
|
22
|
+
| "operator"
|
|
23
|
+
| "typeParameter"
|
|
24
|
+
| "heading";
|
|
25
|
+
|
|
26
|
+
export function isTypeLike(kind: DeclKind): boolean {
|
|
27
|
+
return (
|
|
28
|
+
kind === "class" ||
|
|
29
|
+
kind === "interface" ||
|
|
30
|
+
kind === "struct" ||
|
|
31
|
+
kind === "enum" ||
|
|
32
|
+
kind === "type" ||
|
|
33
|
+
kind === "typeAlias" ||
|
|
34
|
+
kind === "object" ||
|
|
35
|
+
kind === "namespace" ||
|
|
36
|
+
kind === "module" ||
|
|
37
|
+
kind === "package"
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function isCallableLike(kind: DeclKind): boolean {
|
|
42
|
+
return kind === "function" || kind === "method" || kind === "constructor" || kind === "operator";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type Visibility = "public" | "private" | "protected" | "internal";
|
|
46
|
+
|
|
47
|
+
/** Syntactic call/construct site inside a callable body (adapter-owned extraction). */
|
|
48
|
+
export type CallKind = "call" | "construct" | "macro" | "super";
|
|
49
|
+
|
|
50
|
+
export type CallSite = {
|
|
51
|
+
/** Bare callee / type name as written. */
|
|
52
|
+
name: string;
|
|
53
|
+
/** Receiver text when method-like (`obj` in `obj.foo()`); empty when free. */
|
|
54
|
+
receiver: string;
|
|
55
|
+
/** 1-indexed. */
|
|
56
|
+
line: number;
|
|
57
|
+
/** UTF-16 offsets of the name leaf (decision 12). */
|
|
58
|
+
startOffset: number;
|
|
59
|
+
endOffset: number;
|
|
60
|
+
kind: CallKind;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/** One local name introduced by an import statement. */
|
|
64
|
+
export type ImportBinding = {
|
|
65
|
+
/** Name visible in this file. */
|
|
66
|
+
local: string;
|
|
67
|
+
/** Remote name when distinct from local (`Foo as Bar` → imported Foo, local Bar). */
|
|
68
|
+
imported: string;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export type Decl = {
|
|
72
|
+
kind: DeclKind;
|
|
73
|
+
name: string;
|
|
74
|
+
/** Dotted owner.member path. */
|
|
75
|
+
qualifiedName: string;
|
|
76
|
+
/** 1-indexed, inclusive. */
|
|
77
|
+
startLine: number;
|
|
78
|
+
/** 1-indexed, inclusive. */
|
|
79
|
+
endLine: number;
|
|
80
|
+
/** UTF-16 code-unit offset into the decoded source string, inclusive (tree-sitter startIndex convention). */
|
|
81
|
+
startOffset: number;
|
|
82
|
+
/** UTF-16 code-unit offset into the decoded source string, exclusive (tree-sitter endIndex convention). */
|
|
83
|
+
endOffset: number;
|
|
84
|
+
/** Decl start → body open; signature = source.slice(startOffset, signatureEndOffset). */
|
|
85
|
+
signatureEndOffset: number;
|
|
86
|
+
/** Initializer/body spans replaced with compact markers when a signature cannot be one contiguous source slice. */
|
|
87
|
+
signatureOmissions?: Array<{
|
|
88
|
+
startOffset: number;
|
|
89
|
+
endOffset: number;
|
|
90
|
+
replacement: string;
|
|
91
|
+
}>;
|
|
92
|
+
/** Absent when no body. */
|
|
93
|
+
bodyStartOffset?: number;
|
|
94
|
+
bodyEndOffset?: number;
|
|
95
|
+
/** Attached doc comment span. */
|
|
96
|
+
docStartOffset?: number;
|
|
97
|
+
docEndOffset?: number;
|
|
98
|
+
visibility: Visibility;
|
|
99
|
+
exported: boolean;
|
|
100
|
+
children: Decl[];
|
|
101
|
+
/**
|
|
102
|
+
* Direct call/construct sites textually inside this decl's body.
|
|
103
|
+
* Nested callables own their own lists — do not hoist.
|
|
104
|
+
* Empty for non-callables and body-less decls.
|
|
105
|
+
*/
|
|
106
|
+
calls: CallSite[];
|
|
107
|
+
/**
|
|
108
|
+
* Heritage / supertype / trait names on this type-like decl (bare identifiers).
|
|
109
|
+
* Empty when not a type or no heritage.
|
|
110
|
+
*/
|
|
111
|
+
bases: string[];
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
export type ImportRef = {
|
|
115
|
+
specifier: string;
|
|
116
|
+
startLine: number;
|
|
117
|
+
/** UTF-16 offset of the full import statement (inclusive). */
|
|
118
|
+
startOffset: number;
|
|
119
|
+
/** UTF-16 offset of the full import statement (exclusive). */
|
|
120
|
+
endOffset: number;
|
|
121
|
+
/** Local names this import binds. Empty when the statement binds nothing useful (side-effect import). */
|
|
122
|
+
bindings: ImportBinding[];
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
export type FileIr = {
|
|
126
|
+
/** Absolute resolved path. */
|
|
127
|
+
path: string;
|
|
128
|
+
/** sha256 hex of file bytes. */
|
|
129
|
+
contentHash: string;
|
|
130
|
+
languageId: string;
|
|
131
|
+
lineCount: number;
|
|
132
|
+
decls: Decl[];
|
|
133
|
+
imports: ImportRef[];
|
|
134
|
+
/** True when the parse tree contained ERROR/MISSING nodes. */
|
|
135
|
+
parseDegraded: boolean;
|
|
136
|
+
};
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { relative, resolve, sep } from "node:path";
|
|
3
|
+
import type { FileDepHost, FileDepResolver } from "../adapter.ts";
|
|
4
|
+
import { collectFilesWithExtensions, externalId, internalPaths, isWithin } from "./file-dep-util.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* C# file deps — ast-bro style.
|
|
8
|
+
*
|
|
9
|
+
* Index path suffixes + `namespace.Type` FQNs. Each `using` resolves to at most
|
|
10
|
+
* one internal file (`pickClosest` on ties). Bare namespace usings that don't
|
|
11
|
+
* match a type/path become external ids — never "every file in the namespace".
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
type CsharpIndex = {
|
|
15
|
+
/** slash-key → absolute paths */
|
|
16
|
+
bySuffix: Map<string, string[]>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/** BCL / engine — never treat polyfills as project file edges. */
|
|
20
|
+
function isFrameworkNamespace(ns: string): boolean {
|
|
21
|
+
if (ns === "System" || ns.startsWith("System.")) return true;
|
|
22
|
+
if (ns === "Microsoft" || ns.startsWith("Microsoft.")) return true;
|
|
23
|
+
if (ns === "Windows" || ns.startsWith("Windows.")) return true;
|
|
24
|
+
if (ns === "UnityEngine" || ns.startsWith("UnityEngine.")) return true;
|
|
25
|
+
if (ns === "UnityEditor" || ns.startsWith("UnityEditor.")) return true;
|
|
26
|
+
if (ns === "Godot" || ns.startsWith("Godot.")) return true;
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function normalizeUsing(specifier: string): string {
|
|
31
|
+
let s = specifier.trim().replace(/;$/u, "").trim();
|
|
32
|
+
s = s.replace(/^global\s+/iu, "").trim();
|
|
33
|
+
s = s.replace(/^static\s+/iu, "").trim();
|
|
34
|
+
// Alias: using A = X.Y.Z → resolve the target.
|
|
35
|
+
const eq = s.indexOf("=");
|
|
36
|
+
if (eq !== -1) s = s.slice(eq + 1).trim();
|
|
37
|
+
return s;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const TYPE_KEYWORDS = ["class ", "struct ", "interface ", "record ", "enum ", "delegate "] as const;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Scan source for namespace + type pairs (sequential — types bind to the
|
|
44
|
+
* nearest preceding namespace declaration).
|
|
45
|
+
*/
|
|
46
|
+
function typesByNamespace(head: string): { ns: string; typeName: string }[] {
|
|
47
|
+
const out: { ns: string; typeName: string }[] = [];
|
|
48
|
+
let currentNs: string | undefined;
|
|
49
|
+
for (const raw of head.split("\n")) {
|
|
50
|
+
const line = raw.trim();
|
|
51
|
+
if (line.length === 0 || line.startsWith("//")) continue;
|
|
52
|
+
|
|
53
|
+
// file-scoped `namespace X;`, block `namespace X {`, or `namespace X` + brace next line
|
|
54
|
+
const nsMatch =
|
|
55
|
+
/^(?:internal\s+)?namespace\s+([A-Za-z_][\w.]*)\s*[;{]?\s*$/u.exec(line) ??
|
|
56
|
+
/^(?:internal\s+)?namespace\s+([A-Za-z_][\w.]*)\s*[{/]/u.exec(line);
|
|
57
|
+
if (nsMatch?.[1] !== undefined) {
|
|
58
|
+
currentNs = nsMatch[1];
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (currentNs === undefined) continue;
|
|
62
|
+
|
|
63
|
+
for (const kw of TYPE_KEYWORDS) {
|
|
64
|
+
const idx = line.indexOf(kw);
|
|
65
|
+
if (idx === -1) continue;
|
|
66
|
+
if (idx > 0 && /[A-Za-z0-9_]/u.test(line.charAt(idx - 1))) continue;
|
|
67
|
+
const rest = line.slice(idx + kw.length).trimStart();
|
|
68
|
+
const name = /^([A-Za-z_][\w]*)/u.exec(rest)?.[1];
|
|
69
|
+
if (name !== undefined) out.push({ ns: currentNs, typeName: name });
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function pushSuffix(map: Map<string, string[]>, key: string, file: string): void {
|
|
77
|
+
if (key.length === 0) return;
|
|
78
|
+
const list = map.get(key);
|
|
79
|
+
if (list === undefined) map.set(key, [file]);
|
|
80
|
+
else if (!list.includes(file)) list.push(file);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Index every slash-suffix of a stem path: a/b/c → a/b/c, b/c, c */
|
|
84
|
+
function indexPathSuffixes(map: Map<string, string[]>, file: string, stemRelPosix: string): void {
|
|
85
|
+
const parts = stemRelPosix.split("/").filter((part) => part.length > 0);
|
|
86
|
+
for (let i = 0; i < parts.length; i += 1) {
|
|
87
|
+
pushSuffix(map, parts.slice(i).join("/"), file);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function toPosixRel(scopeRoot: string, file: string): string | undefined {
|
|
92
|
+
const rel = relative(resolve(scopeRoot), resolve(file));
|
|
93
|
+
if (rel.startsWith(`..${sep}`) || rel === ".." || rel.length === 0) return undefined;
|
|
94
|
+
return rel.split(sep).join("/");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
async function buildIndex(host: FileDepHost, signal: AbortSignal): Promise<CsharpIndex> {
|
|
98
|
+
const key = `csharp-suffix:${host.scopeRoot}`;
|
|
99
|
+
const cached = host.memo.get(key);
|
|
100
|
+
if (cached !== undefined) return cached as CsharpIndex;
|
|
101
|
+
|
|
102
|
+
const bySuffix = new Map<string, string[]>();
|
|
103
|
+
const files = await collectFilesWithExtensions(host, host.scopeRoot, [".cs"], signal);
|
|
104
|
+
|
|
105
|
+
for (const file of files) {
|
|
106
|
+
signal.throwIfAborted();
|
|
107
|
+
const rel = toPosixRel(host.scopeRoot, file);
|
|
108
|
+
if (rel === undefined) continue;
|
|
109
|
+
|
|
110
|
+
const dot = rel.lastIndexOf(".");
|
|
111
|
+
const stem = dot >= 0 ? rel.slice(0, dot) : rel;
|
|
112
|
+
indexPathSuffixes(bySuffix, file, stem);
|
|
113
|
+
|
|
114
|
+
let text: string;
|
|
115
|
+
try {
|
|
116
|
+
text = await readFile(file, "utf8");
|
|
117
|
+
} catch {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const head = text.slice(0, 12000);
|
|
121
|
+
// FQN only — bare type names are too ambiguous (Platform, View, …).
|
|
122
|
+
for (const { ns, typeName } of typesByNamespace(head)) {
|
|
123
|
+
const fqn = `${ns}.${typeName}`.replace(/\./gu, "/");
|
|
124
|
+
pushSuffix(bySuffix, fqn, file);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
for (const [, list] of bySuffix) list.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
129
|
+
const index: CsharpIndex = { bySuffix };
|
|
130
|
+
host.memo.set(key, index);
|
|
131
|
+
return index;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Prefer the candidate sharing the most path prefix with the importer. */
|
|
135
|
+
function pickClosest(candidates: readonly string[], fromPath: string): string | undefined {
|
|
136
|
+
if (candidates.length === 0) return undefined;
|
|
137
|
+
if (candidates.length === 1) return candidates[0];
|
|
138
|
+
|
|
139
|
+
const fromSegs = resolve(fromPath).split(sep);
|
|
140
|
+
let best: string | undefined;
|
|
141
|
+
let bestCommon = -1;
|
|
142
|
+
for (const candidate of candidates) {
|
|
143
|
+
const segs = resolve(candidate).split(sep);
|
|
144
|
+
let common = 0;
|
|
145
|
+
const n = Math.min(fromSegs.length, segs.length);
|
|
146
|
+
while (common < n && fromSegs[common] === segs[common]) common += 1;
|
|
147
|
+
if (best === undefined || common > bestCommon || (common === bestCommon && candidate < best)) {
|
|
148
|
+
best = candidate;
|
|
149
|
+
bestCommon = common;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return best;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function lookup(index: CsharpIndex, key: string): readonly string[] | undefined {
|
|
156
|
+
const list = index.bySuffix.get(key);
|
|
157
|
+
if (list === undefined || list.length === 0) return undefined;
|
|
158
|
+
return list;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function resolveKey(index: CsharpIndex, fromPath: string, dotted: string): string | undefined {
|
|
162
|
+
const key = dotted.replace(/\./gu, "/");
|
|
163
|
+
const hit = pickClosest(lookup(index, key) ?? [], fromPath);
|
|
164
|
+
if (hit !== undefined) return hit;
|
|
165
|
+
|
|
166
|
+
// Nested type: Foo.Bar.Inner → try Foo.Bar file.
|
|
167
|
+
const slash = key.lastIndexOf("/");
|
|
168
|
+
if (slash <= 0) return undefined;
|
|
169
|
+
const parent = key.slice(0, slash);
|
|
170
|
+
return pickClosest(lookup(index, parent) ?? [], fromPath);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export const resolveCsharpFileDep: FileDepResolver = async (fromPath, specifier, host, signal) => {
|
|
174
|
+
signal.throwIfAborted();
|
|
175
|
+
const dotted = normalizeUsing(specifier);
|
|
176
|
+
if (dotted.length === 0) return { kind: "unresolved" };
|
|
177
|
+
|
|
178
|
+
if (isFrameworkNamespace(dotted)) return externalId(dotted);
|
|
179
|
+
|
|
180
|
+
const index = await buildIndex(host, signal);
|
|
181
|
+
const file = resolveKey(index, fromPath, dotted);
|
|
182
|
+
if (file === undefined) return externalId(dotted);
|
|
183
|
+
if (!isWithin(host.scopeRoot, file) && resolve(file) !== resolve(host.scopeRoot)) {
|
|
184
|
+
return externalId(dotted);
|
|
185
|
+
}
|
|
186
|
+
if (!host.ownsPath(file)) return externalId(dotted);
|
|
187
|
+
if (resolve(file) === resolve(fromPath)) return { kind: "unresolved" };
|
|
188
|
+
return internalPaths([file]);
|
|
189
|
+
};
|