@wrongstack/tools 1.0.11 → 1.0.12
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/dist/builtin.js +15 -15
- package/dist/{chunk-GU7TZE6Z.js → chunk-2BCRQAIW.js} +7 -7
- package/dist/{chunk-XRNN44QY.js → chunk-2IRHFHZY.js} +235 -71
- package/dist/{chunk-NEYUPZL6.js → chunk-6D3UIQMF.js} +651 -303
- package/dist/chunk-BJ5LXLKE.js +351 -0
- package/dist/{chunk-C6ZOXNXV.js → chunk-CSS42GRP.js} +2 -2
- package/dist/{chunk-SKRMUHTU.js → chunk-HSLDY55L.js} +41 -8
- package/dist/{chunk-ENE22I5W.js → chunk-K37AKCTN.js} +884 -362
- package/dist/{chunk-DKXMDO5F.js → chunk-K3VX6V5P.js} +3 -3
- package/dist/chunk-OIFY4XNP.js +855 -0
- package/dist/{chunk-7GOE2ZTZ.js → chunk-OMWC2OGT.js} +2 -2
- package/dist/{chunk-IE4KDAOB.js → chunk-OYQE2UNT.js} +3 -3
- package/dist/chunk-R3HR3QI3.js +97 -0
- package/dist/{chunk-XPVYZ2S6.js → chunk-RYLMSGR5.js} +2 -2
- package/dist/{chunk-HYHE4VNA.js → chunk-UMOP3VGK.js} +79 -45
- package/dist/{chunk-6OIEYJM4.js → chunk-VMNWQI4V.js} +2 -2
- package/dist/{chunk-2UVAIS5O.js → chunk-YPSVPCIE.js} +2 -2
- package/dist/{chunk-PWZUHZP7.js → chunk-Z77XMU3U.js} +2 -2
- package/dist/codebase-index/ast-invariant-engine.d.ts +19 -2
- package/dist/codebase-index/atlas-projection.d.ts +19 -0
- package/dist/codebase-index/background-indexer.d.ts +14 -0
- package/dist/codebase-index/circuit-breaker.d.ts +7 -0
- package/dist/codebase-index/codebase-ast-replace-tool.d.ts +1 -1
- package/dist/codebase-index/codebase-impact-analysis-tool.d.ts +6 -0
- package/dist/codebase-index/codebase-invariant-check-tool.d.ts +2 -0
- package/dist/codebase-index/codebase-targeted-test-tool.d.ts +26 -0
- package/dist/codebase-index/dead-code-scan.d.ts +4 -0
- package/dist/codebase-index/go-parser.d.ts +23 -3
- package/dist/codebase-index/graph-rank-pass.d.ts +10 -0
- package/dist/codebase-index/graph-rank.d.ts +8 -0
- package/dist/codebase-index/index.d.ts +1 -1
- package/dist/codebase-index/index.js +9 -9
- package/dist/codebase-index/lsp-kind.d.ts +3 -1
- package/dist/codebase-index/module-resolver.d.ts +21 -1
- package/dist/codebase-index/parser-batch.d.ts +6 -8
- package/dist/codebase-index/parser-output.d.ts +5 -1
- package/dist/codebase-index/parser-worker-script.js +4 -4
- package/dist/codebase-index/project-server-framing.d.ts +1 -17
- package/dist/codebase-index/project-server-watcher.d.ts +6 -0
- package/dist/codebase-index/project-server.js +72 -26
- package/dist/codebase-index/py-parser.d.ts +4 -4
- package/dist/codebase-index/rs-parser.d.ts +7 -0
- package/dist/codebase-index/toolchain-scripts.d.ts +64 -0
- package/dist/codebase-index/tree-sitter/queries.d.ts +14 -0
- package/dist/codebase-index/tree-sitter/util.d.ts +6 -1
- package/dist/codebase-index/tree-sitter-parser.d.ts +7 -0
- package/dist/codebase-index/worker.js +23 -16
- package/dist/codebase-index/writer-refs.d.ts +17 -2
- package/dist/codebase-index/writer-search-helpers.d.ts +9 -0
- package/dist/codebase-index/writer.d.ts +20 -1
- package/dist/edit.js +8 -8
- package/dist/{generic-parser-N2PLGBC2.js → generic-parser-IVWLFKMR.js} +2 -2
- package/dist/go-parser-LWV3L5V7.js +197 -0
- package/dist/index.js +17 -17
- package/dist/json-parser-PERV2JHX.js +204 -0
- package/dist/pack.js +16 -16
- package/dist/parser-dispatch-ZSWCQB6M.js +14 -0
- package/dist/patch.js +8 -8
- package/dist/{py-parser-4PFZYAJ7.js → py-parser-B6D6RGH7.js} +4 -4
- package/dist/read.js +8 -8
- package/dist/replace.js +8 -8
- package/dist/rs-parser-L7SP4GWJ.js +182 -0
- package/dist/tool-tier.js +17 -17
- package/dist/{tree-sitter-parser-GILYQLS4.js → tree-sitter-parser-KU6JF3ZC.js} +6 -4
- package/dist/{ts-parser-7W26YB26.js → ts-parser-PML6QIH7.js} +55 -23
- package/dist/write.js +8 -8
- package/dist/{yaml-parser-DFBC5FWH.js → yaml-parser-7BJN544B.js} +41 -6
- package/package.json +5 -5
- package/dist/chunk-4CE3RKEP.js +0 -390
- package/dist/chunk-KHUCKLOR.js +0 -899
- package/dist/chunk-ZKC5UNGD.js +0 -167
- package/dist/go-parser-Z4H6SR3R.js +0 -474
- package/dist/json-parser-IJD77VL4.js +0 -256
- package/dist/parser-dispatch-WG4DNBHH.js +0 -14
- package/dist/rs-parser-GIWPUA3T.js +0 -81
|
@@ -0,0 +1,855 @@
|
|
|
1
|
+
// src/codebase-index/parser-output.ts
|
|
2
|
+
function toIndexSymbols(raw, file, lang) {
|
|
3
|
+
return raw.map((s) => {
|
|
4
|
+
const signature = s.signature.slice(0, 500);
|
|
5
|
+
return {
|
|
6
|
+
id: 0,
|
|
7
|
+
lang,
|
|
8
|
+
kind: s.kind,
|
|
9
|
+
name: s.name,
|
|
10
|
+
file,
|
|
11
|
+
line: s.line,
|
|
12
|
+
col: s.col,
|
|
13
|
+
signature,
|
|
14
|
+
docComment: s.doc,
|
|
15
|
+
scope: s.scope,
|
|
16
|
+
text: [s.name, signature, s.doc].filter(Boolean).join(" ")
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
var CALL_TYPES = /* @__PURE__ */ new Set([
|
|
21
|
+
"call",
|
|
22
|
+
"type_ref",
|
|
23
|
+
"inherit",
|
|
24
|
+
"implement",
|
|
25
|
+
"import"
|
|
26
|
+
]);
|
|
27
|
+
function coerceSymbols(value) {
|
|
28
|
+
if (!Array.isArray(value)) return [];
|
|
29
|
+
return value.flatMap((entry) => {
|
|
30
|
+
const candidate = entry;
|
|
31
|
+
if (typeof candidate.name !== "string" || typeof candidate.kind !== "string") return [];
|
|
32
|
+
return [
|
|
33
|
+
{
|
|
34
|
+
name: candidate.name,
|
|
35
|
+
kind: candidate.kind,
|
|
36
|
+
line: typeof candidate.line === "number" ? candidate.line : 1,
|
|
37
|
+
col: typeof candidate.col === "number" ? candidate.col : 0,
|
|
38
|
+
signature: typeof candidate.signature === "string" ? candidate.signature : "",
|
|
39
|
+
scope: typeof candidate.scope === "string" ? candidate.scope : "",
|
|
40
|
+
doc: typeof candidate.doc === "string" ? candidate.doc : ""
|
|
41
|
+
}
|
|
42
|
+
];
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function coerceRefs(value, lang) {
|
|
46
|
+
if (!Array.isArray(value)) return [];
|
|
47
|
+
return value.flatMap((entry) => {
|
|
48
|
+
const candidate = entry;
|
|
49
|
+
if (typeof candidate.toName !== "string" || !candidate.toName) return [];
|
|
50
|
+
if (typeof candidate.callType !== "string" || !CALL_TYPES.has(candidate.callType)) return [];
|
|
51
|
+
const module = typeof candidate.module === "string" && candidate.module ? candidate.module : void 0;
|
|
52
|
+
return [
|
|
53
|
+
{
|
|
54
|
+
fromId: 0,
|
|
55
|
+
toName: candidate.toName,
|
|
56
|
+
callType: candidate.callType,
|
|
57
|
+
line: typeof candidate.line === "number" ? candidate.line : 1,
|
|
58
|
+
lang,
|
|
59
|
+
module
|
|
60
|
+
}
|
|
61
|
+
];
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function parseParserOutput(stdout, lang) {
|
|
65
|
+
const trimmed = stdout.trim();
|
|
66
|
+
if (!trimmed) return { symbols: [], refs: [] };
|
|
67
|
+
let parsed;
|
|
68
|
+
try {
|
|
69
|
+
parsed = JSON.parse(trimmed);
|
|
70
|
+
} catch {
|
|
71
|
+
return { symbols: [], refs: [] };
|
|
72
|
+
}
|
|
73
|
+
if (Array.isArray(parsed)) return { symbols: coerceSymbols(parsed), refs: [] };
|
|
74
|
+
const record = parsed;
|
|
75
|
+
return {
|
|
76
|
+
symbols: coerceSymbols(record.symbols),
|
|
77
|
+
refs: dedupeRefs(coerceRefs(record.refs, lang))
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function parseParserBatchOutput(stdout, lang) {
|
|
81
|
+
const trimmed = stdout.trim();
|
|
82
|
+
if (!trimmed) return [];
|
|
83
|
+
let parsed;
|
|
84
|
+
try {
|
|
85
|
+
parsed = JSON.parse(trimmed);
|
|
86
|
+
} catch {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
if (!parsed || typeof parsed !== "object") return [];
|
|
90
|
+
const results = parsed.results;
|
|
91
|
+
if (!Array.isArray(results)) return [];
|
|
92
|
+
return results.flatMap((entry) => {
|
|
93
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) return [];
|
|
94
|
+
const candidate = entry;
|
|
95
|
+
if (typeof candidate.file !== "string" || !candidate.file) return [];
|
|
96
|
+
return [
|
|
97
|
+
{
|
|
98
|
+
file: candidate.file,
|
|
99
|
+
error: typeof candidate.error === "string" && candidate.error ? candidate.error : void 0,
|
|
100
|
+
symbols: coerceSymbols(candidate.symbols),
|
|
101
|
+
refs: dedupeRefs(coerceRefs(candidate.refs, lang))
|
|
102
|
+
}
|
|
103
|
+
];
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function dedupeRefs(refs) {
|
|
107
|
+
const seen = /* @__PURE__ */ new Set();
|
|
108
|
+
return refs.filter((ref) => {
|
|
109
|
+
const key = `${ref.toName}:${ref.callType}:${ref.line}:${ref.module ?? ""}`;
|
|
110
|
+
if (seen.has(key)) return false;
|
|
111
|
+
seen.add(key);
|
|
112
|
+
return true;
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/codebase-index/perf-metrics.ts
|
|
117
|
+
var counters = {
|
|
118
|
+
filesystemBytesRead: 0,
|
|
119
|
+
filesystemReadCount: 0,
|
|
120
|
+
parserGateWaitMs: 0,
|
|
121
|
+
parserGateCalls: 0,
|
|
122
|
+
parserSubprocessCount: 0,
|
|
123
|
+
ipcPendingPeak: 0,
|
|
124
|
+
writeQueueWaitMs: 0,
|
|
125
|
+
writeQueueCalls: 0
|
|
126
|
+
};
|
|
127
|
+
function resetCodebaseIndexPerfMetrics() {
|
|
128
|
+
for (const key of Object.keys(counters)) {
|
|
129
|
+
counters[key] = 0;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function getCodebaseIndexPerfSnapshot() {
|
|
133
|
+
return { ...counters };
|
|
134
|
+
}
|
|
135
|
+
function recordFilesystemRead(bytes) {
|
|
136
|
+
counters.filesystemBytesRead += Math.max(0, bytes);
|
|
137
|
+
counters.filesystemReadCount++;
|
|
138
|
+
}
|
|
139
|
+
function recordParserGateWait(waitMs) {
|
|
140
|
+
counters.parserGateWaitMs += Math.max(0, waitMs);
|
|
141
|
+
counters.parserGateCalls++;
|
|
142
|
+
}
|
|
143
|
+
function recordParserSubprocess() {
|
|
144
|
+
counters.parserSubprocessCount++;
|
|
145
|
+
}
|
|
146
|
+
function recordIpcPending(depth) {
|
|
147
|
+
counters.ipcPendingPeak = Math.max(counters.ipcPendingPeak, depth);
|
|
148
|
+
}
|
|
149
|
+
function recordWriteQueueWait(waitMs) {
|
|
150
|
+
counters.writeQueueWaitMs += Math.max(0, waitMs);
|
|
151
|
+
counters.writeQueueCalls++;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/codebase-index/spawn-gate.ts
|
|
155
|
+
var chain = Promise.resolve();
|
|
156
|
+
function withSpawnGate(fn) {
|
|
157
|
+
const queuedAt = performance.now();
|
|
158
|
+
const run = chain.then(
|
|
159
|
+
() => {
|
|
160
|
+
recordParserGateWait(performance.now() - queuedAt);
|
|
161
|
+
return fn();
|
|
162
|
+
},
|
|
163
|
+
() => {
|
|
164
|
+
recordParserGateWait(performance.now() - queuedAt);
|
|
165
|
+
return fn();
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
chain = run.then(
|
|
169
|
+
() => void 0,
|
|
170
|
+
() => void 0
|
|
171
|
+
);
|
|
172
|
+
return run;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// src/codebase-index/toolchain-scripts.ts
|
|
176
|
+
import { spawn } from "node:child_process";
|
|
177
|
+
import * as fsSync from "node:fs";
|
|
178
|
+
import * as fs from "node:fs/promises";
|
|
179
|
+
import * as os from "node:os";
|
|
180
|
+
import * as path from "node:path";
|
|
181
|
+
import { StringDecoder } from "node:string_decoder";
|
|
182
|
+
var GO_CORE = `
|
|
183
|
+
package main
|
|
184
|
+
|
|
185
|
+
import (
|
|
186
|
+
"encoding/json"
|
|
187
|
+
"fmt"
|
|
188
|
+
"go/ast"
|
|
189
|
+
"go/parser"
|
|
190
|
+
"go/token"
|
|
191
|
+
"io"
|
|
192
|
+
"os"
|
|
193
|
+
"strconv"
|
|
194
|
+
"strings"
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
type Sym struct {
|
|
198
|
+
Name string \`json:"name"\`
|
|
199
|
+
Kind string \`json:"kind"\`
|
|
200
|
+
Line int \`json:"line"\`
|
|
201
|
+
Col int \`json:"col"\`
|
|
202
|
+
Signature string \`json:"signature"\`
|
|
203
|
+
Scope string \`json:"scope"\`
|
|
204
|
+
Doc string \`json:"doc"\`
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Ref is a cross-reference emitted alongside the symbols, so one run yields
|
|
208
|
+
// both. Module is the import path for CallType "import", else empty.
|
|
209
|
+
type Ref struct {
|
|
210
|
+
ToName string \`json:"toName"\`
|
|
211
|
+
CallType string \`json:"callType"\`
|
|
212
|
+
Line int \`json:"line"\`
|
|
213
|
+
Module string \`json:"module"\`
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
func extract(src []byte) ([]Sym, []Ref, error) {
|
|
217
|
+
fset := token.NewFileSet()
|
|
218
|
+
node, err := parser.ParseFile(fset, "src.go", src, parser.ParseComments)
|
|
219
|
+
if err != nil {
|
|
220
|
+
return nil, nil, err
|
|
221
|
+
}
|
|
222
|
+
pkg := node.Name.Name
|
|
223
|
+
// token columns are 1-based; the index schema's are 0-based.
|
|
224
|
+
at := func(p token.Pos) (int, int) {
|
|
225
|
+
pos := fset.Position(p)
|
|
226
|
+
return pos.Line, pos.Column - 1
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
syms := []Sym{}
|
|
230
|
+
for _, decl := range node.Decls {
|
|
231
|
+
switch d := decl.(type) {
|
|
232
|
+
case *ast.FuncDecl:
|
|
233
|
+
line, col := at(d.Pos())
|
|
234
|
+
kind := "function"
|
|
235
|
+
scope := pkg + "." + d.Name.Name
|
|
236
|
+
if d.Recv != nil && len(d.Recv.List) > 0 {
|
|
237
|
+
kind = "method"
|
|
238
|
+
scope = pkg + "." + recvTypeName(d.Recv.List[0].Type) + "." + d.Name.Name
|
|
239
|
+
}
|
|
240
|
+
syms = append(syms, Sym{Name: d.Name.Name, Kind: kind, Line: line, Col: col, Signature: formatFuncSig(d), Scope: scope, Doc: firstDocLine(d.Doc)})
|
|
241
|
+
|
|
242
|
+
case *ast.GenDecl:
|
|
243
|
+
// An ungrouped declaration carries its comment on the GenDecl; a
|
|
244
|
+
// grouped one's doc describes the group, not each member.
|
|
245
|
+
var declDoc *ast.CommentGroup
|
|
246
|
+
if !d.Lparen.IsValid() {
|
|
247
|
+
declDoc = d.Doc
|
|
248
|
+
}
|
|
249
|
+
for _, spec := range d.Specs {
|
|
250
|
+
switch s := spec.(type) {
|
|
251
|
+
case *ast.TypeSpec:
|
|
252
|
+
line, col := at(s.Pos())
|
|
253
|
+
sig := "type " + s.Name.Name + formatTypeParams(s.TypeParams)
|
|
254
|
+
if s.Assign.IsValid() {
|
|
255
|
+
sig += " ="
|
|
256
|
+
}
|
|
257
|
+
sig += " " + formatType(s.Type)
|
|
258
|
+
syms = append(syms, Sym{Name: s.Name.Name, Kind: "type", Line: line, Col: col, Signature: sig, Scope: pkg, Doc: firstDocLine(s.Doc, declDoc)})
|
|
259
|
+
case *ast.ValueSpec:
|
|
260
|
+
kind := "var"
|
|
261
|
+
if d.Tok == token.CONST {
|
|
262
|
+
kind = "const"
|
|
263
|
+
}
|
|
264
|
+
for _, n := range s.Names {
|
|
265
|
+
line, col := at(n.Pos())
|
|
266
|
+
sig := kind + " " + n.Name
|
|
267
|
+
if s.Type != nil {
|
|
268
|
+
sig += " " + formatType(s.Type)
|
|
269
|
+
}
|
|
270
|
+
syms = append(syms, Sym{Name: n.Name, Kind: kind, Line: line, Col: col, Signature: sig, Scope: pkg, Doc: firstDocLine(s.Doc, declDoc)})
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
refs := []Ref{}
|
|
278
|
+
ast.Inspect(node, func(n ast.Node) bool {
|
|
279
|
+
switch expr := n.(type) {
|
|
280
|
+
case *ast.CallExpr:
|
|
281
|
+
line := fset.Position(expr.Pos()).Line
|
|
282
|
+
switch fun := expr.Fun.(type) {
|
|
283
|
+
case *ast.Ident:
|
|
284
|
+
refs = append(refs, Ref{ToName: fun.Name, CallType: "call", Line: line})
|
|
285
|
+
case *ast.SelectorExpr:
|
|
286
|
+
// The selected name (\`Join\` of \`filepath.Join\`) is the declared
|
|
287
|
+
// symbol name, so it resolves like the TS and Python call refs.
|
|
288
|
+
refs = append(refs, Ref{ToName: fun.Sel.Name, CallType: "call", Line: line})
|
|
289
|
+
}
|
|
290
|
+
case *ast.ImportSpec:
|
|
291
|
+
if expr.Path != nil {
|
|
292
|
+
if importPath, uerr := strconv.Unquote(expr.Path.Value); uerr == nil {
|
|
293
|
+
line := fset.Position(expr.Pos()).Line
|
|
294
|
+
// A Go import names a package; its last path segment is the
|
|
295
|
+
// name it is referenced by.
|
|
296
|
+
name := importPath
|
|
297
|
+
if idx := strings.LastIndex(importPath, "/"); idx >= 0 {
|
|
298
|
+
name = importPath[idx+1:]
|
|
299
|
+
}
|
|
300
|
+
refs = append(refs, Ref{ToName: name, CallType: "import", Line: line, Module: importPath})
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return true
|
|
305
|
+
})
|
|
306
|
+
return syms, refs, nil
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
func firstDocLine(groups ...*ast.CommentGroup) string {
|
|
310
|
+
for _, g := range groups {
|
|
311
|
+
if g == nil {
|
|
312
|
+
continue
|
|
313
|
+
}
|
|
314
|
+
for _, line := range strings.Split(g.Text(), "\\n") {
|
|
315
|
+
if t := strings.TrimSpace(line); t != "" {
|
|
316
|
+
if r := []rune(t); len(r) > 200 {
|
|
317
|
+
t = string(r[:200])
|
|
318
|
+
}
|
|
319
|
+
return t
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return ""
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// recvTypeName unwraps pointers, parens and generic instantiation:
|
|
327
|
+
// \`(l *List[T])\` is a method of List, not of "?".
|
|
328
|
+
func recvTypeName(t ast.Expr) string {
|
|
329
|
+
switch v := t.(type) {
|
|
330
|
+
case *ast.Ident:
|
|
331
|
+
return v.Name
|
|
332
|
+
case *ast.StarExpr:
|
|
333
|
+
return recvTypeName(v.X)
|
|
334
|
+
case *ast.ParenExpr:
|
|
335
|
+
return recvTypeName(v.X)
|
|
336
|
+
case *ast.IndexExpr:
|
|
337
|
+
return recvTypeName(v.X)
|
|
338
|
+
case *ast.IndexListExpr:
|
|
339
|
+
return recvTypeName(v.X)
|
|
340
|
+
default:
|
|
341
|
+
return "?"
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
func formatFuncSig(d *ast.FuncDecl) string {
|
|
346
|
+
sig := "func "
|
|
347
|
+
if d.Recv != nil && len(d.Recv.List) > 0 {
|
|
348
|
+
sig += formatFieldList(d.Recv.List) + " "
|
|
349
|
+
}
|
|
350
|
+
return sig + d.Name.Name + formatTypeParams(d.Type.TypeParams) + formatFuncType(d.Type)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
func fieldsOf(fl *ast.FieldList) []*ast.Field {
|
|
354
|
+
if fl == nil {
|
|
355
|
+
return nil
|
|
356
|
+
}
|
|
357
|
+
return fl.List
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
func formatFuncType(f *ast.FuncType) string {
|
|
361
|
+
out := formatFieldList(fieldsOf(f.Params))
|
|
362
|
+
results := fieldsOf(f.Results)
|
|
363
|
+
if len(results) == 1 && len(results[0].Names) == 0 {
|
|
364
|
+
out += " " + formatType(results[0].Type)
|
|
365
|
+
} else if len(results) > 0 {
|
|
366
|
+
out += " " + formatFieldList(results)
|
|
367
|
+
}
|
|
368
|
+
return out
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// formatField keeps every name of a shared-type field: \`a, b int\`.
|
|
372
|
+
func formatField(f *ast.Field) string {
|
|
373
|
+
t := formatType(f.Type)
|
|
374
|
+
if len(f.Names) == 0 {
|
|
375
|
+
return t
|
|
376
|
+
}
|
|
377
|
+
names := make([]string, len(f.Names))
|
|
378
|
+
for i, n := range f.Names {
|
|
379
|
+
names[i] = n.Name
|
|
380
|
+
}
|
|
381
|
+
return strings.Join(names, ", ") + " " + t
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
func formatFieldList(fields []*ast.Field) string {
|
|
385
|
+
parts := make([]string, len(fields))
|
|
386
|
+
for i, f := range fields {
|
|
387
|
+
parts[i] = formatField(f)
|
|
388
|
+
}
|
|
389
|
+
return "(" + strings.Join(parts, ", ") + ")"
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// formatFields renders struct fields and interface members.
|
|
393
|
+
func formatFields(fields []*ast.Field) string {
|
|
394
|
+
parts := make([]string, len(fields))
|
|
395
|
+
for i, f := range fields {
|
|
396
|
+
if ft, ok := f.Type.(*ast.FuncType); ok && len(f.Names) == 1 {
|
|
397
|
+
parts[i] = f.Names[0].Name + formatFuncType(ft)
|
|
398
|
+
} else {
|
|
399
|
+
parts[i] = formatField(f)
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return strings.Join(parts, "; ")
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
func formatTypeParams(tp *ast.FieldList) string {
|
|
406
|
+
if tp == nil || len(tp.List) == 0 {
|
|
407
|
+
return ""
|
|
408
|
+
}
|
|
409
|
+
parts := make([]string, len(tp.List))
|
|
410
|
+
for i, p := range tp.List {
|
|
411
|
+
parts[i] = formatField(p)
|
|
412
|
+
}
|
|
413
|
+
return "[" + strings.Join(parts, ", ") + "]"
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
func formatType(t ast.Expr) string {
|
|
417
|
+
if t == nil {
|
|
418
|
+
return "?"
|
|
419
|
+
}
|
|
420
|
+
switch v := t.(type) {
|
|
421
|
+
case *ast.Ident:
|
|
422
|
+
return v.Name
|
|
423
|
+
case *ast.SelectorExpr:
|
|
424
|
+
return formatType(v.X) + "." + v.Sel.Name
|
|
425
|
+
case *ast.StarExpr:
|
|
426
|
+
return "*" + formatType(v.X)
|
|
427
|
+
case *ast.ParenExpr:
|
|
428
|
+
return "(" + formatType(v.X) + ")"
|
|
429
|
+
case *ast.Ellipsis:
|
|
430
|
+
if v.Elt == nil {
|
|
431
|
+
return "..."
|
|
432
|
+
}
|
|
433
|
+
return "..." + formatType(v.Elt)
|
|
434
|
+
case *ast.ArrayType:
|
|
435
|
+
if v.Len == nil {
|
|
436
|
+
return "[]" + formatType(v.Elt)
|
|
437
|
+
}
|
|
438
|
+
return "[" + formatType(v.Len) + "]" + formatType(v.Elt)
|
|
439
|
+
case *ast.MapType:
|
|
440
|
+
return "map[" + formatType(v.Key) + "]" + formatType(v.Value)
|
|
441
|
+
case *ast.ChanType:
|
|
442
|
+
switch v.Dir {
|
|
443
|
+
case ast.SEND:
|
|
444
|
+
return "chan<- " + formatType(v.Value)
|
|
445
|
+
case ast.RECV:
|
|
446
|
+
return "<-chan " + formatType(v.Value)
|
|
447
|
+
default:
|
|
448
|
+
return "chan " + formatType(v.Value)
|
|
449
|
+
}
|
|
450
|
+
case *ast.InterfaceType:
|
|
451
|
+
if len(fieldsOf(v.Methods)) == 0 {
|
|
452
|
+
return "interface{}"
|
|
453
|
+
}
|
|
454
|
+
return "interface{ " + formatFields(v.Methods.List) + " }"
|
|
455
|
+
case *ast.StructType:
|
|
456
|
+
if len(fieldsOf(v.Fields)) == 0 {
|
|
457
|
+
return "struct{}"
|
|
458
|
+
}
|
|
459
|
+
return "struct{ " + formatFields(v.Fields.List) + " }"
|
|
460
|
+
case *ast.FuncType:
|
|
461
|
+
return "func" + formatFuncType(v)
|
|
462
|
+
case *ast.UnaryExpr:
|
|
463
|
+
return v.Op.String() + formatType(v.X)
|
|
464
|
+
case *ast.BinaryExpr:
|
|
465
|
+
return formatType(v.X) + " " + v.Op.String() + " " + formatType(v.Y)
|
|
466
|
+
case *ast.BasicLit:
|
|
467
|
+
return v.Value
|
|
468
|
+
case *ast.IndexExpr:
|
|
469
|
+
return formatType(v.X) + "[" + formatType(v.Index) + "]"
|
|
470
|
+
case *ast.IndexListExpr:
|
|
471
|
+
args := make([]string, len(v.Indices))
|
|
472
|
+
for i, idx := range v.Indices {
|
|
473
|
+
args[i] = formatType(idx)
|
|
474
|
+
}
|
|
475
|
+
return formatType(v.X) + "[" + strings.Join(args, ", ") + "]"
|
|
476
|
+
default:
|
|
477
|
+
return "?"
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
`;
|
|
481
|
+
var GO_PARSE_SCRIPT = `${GO_CORE}
|
|
482
|
+
type Result struct {
|
|
483
|
+
Symbols []Sym \`json:"symbols"\`
|
|
484
|
+
Refs []Ref \`json:"refs"\`
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
func main() {
|
|
488
|
+
empty := \`{"symbols":[],"refs":[]}\`
|
|
489
|
+
src, err := io.ReadAll(os.Stdin)
|
|
490
|
+
if err != nil {
|
|
491
|
+
fmt.Print(empty)
|
|
492
|
+
return
|
|
493
|
+
}
|
|
494
|
+
syms, refs, err := extract(src)
|
|
495
|
+
if err != nil {
|
|
496
|
+
fmt.Print(empty)
|
|
497
|
+
return
|
|
498
|
+
}
|
|
499
|
+
data, err := json.Marshal(Result{Symbols: syms, Refs: refs})
|
|
500
|
+
if err != nil {
|
|
501
|
+
fmt.Print(empty)
|
|
502
|
+
return
|
|
503
|
+
}
|
|
504
|
+
fmt.Print(string(data))
|
|
505
|
+
}
|
|
506
|
+
`;
|
|
507
|
+
var GO_BATCH_SCRIPT = `${GO_CORE}
|
|
508
|
+
type FileResult struct {
|
|
509
|
+
File string \`json:"file"\`
|
|
510
|
+
Error string \`json:"error,omitempty"\`
|
|
511
|
+
Symbols []Sym \`json:"symbols"\`
|
|
512
|
+
Refs []Ref \`json:"refs"\`
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
type BatchResult struct {
|
|
516
|
+
Version int \`json:"version"\`
|
|
517
|
+
Results []FileResult \`json:"results"\`
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
type inputFile struct {
|
|
521
|
+
File string \`json:"file"\`
|
|
522
|
+
Content string \`json:"content"\`
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
func main() {
|
|
526
|
+
var inputs []inputFile
|
|
527
|
+
raw, err := io.ReadAll(os.Stdin)
|
|
528
|
+
if err == nil {
|
|
529
|
+
err = json.Unmarshal(raw, &inputs)
|
|
530
|
+
}
|
|
531
|
+
results := make([]FileResult, 0, len(inputs))
|
|
532
|
+
if err == nil {
|
|
533
|
+
for _, in := range inputs {
|
|
534
|
+
res := FileResult{File: in.File, Symbols: []Sym{}, Refs: []Ref{}}
|
|
535
|
+
if syms, refs, perr := extract([]byte(in.Content)); perr != nil {
|
|
536
|
+
res.Error = perr.Error()
|
|
537
|
+
} else {
|
|
538
|
+
res.Symbols, res.Refs = syms, refs
|
|
539
|
+
}
|
|
540
|
+
results = append(results, res)
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
data, merr := json.Marshal(BatchResult{Version: 1, Results: results})
|
|
544
|
+
if merr != nil {
|
|
545
|
+
fmt.Print(\`{"version":1,"results":[]}\`)
|
|
546
|
+
return
|
|
547
|
+
}
|
|
548
|
+
fmt.Print(string(data))
|
|
549
|
+
}
|
|
550
|
+
`;
|
|
551
|
+
var PY_CORE = `import ast, json, sys
|
|
552
|
+
|
|
553
|
+
# Decorators whose function is an attribute accessor, by last dotted segment.
|
|
554
|
+
PROPERTY_DECORATORS = ("property", "cached_property", "abstractproperty", "setter", "getter", "deleter")
|
|
555
|
+
|
|
556
|
+
def get_name(node):
|
|
557
|
+
if isinstance(node, ast.Name):
|
|
558
|
+
return node.id
|
|
559
|
+
if isinstance(node, ast.Attribute):
|
|
560
|
+
return get_name(node.value) + "." + node.attr
|
|
561
|
+
if isinstance(node, ast.Subscript):
|
|
562
|
+
return get_name(node.value)
|
|
563
|
+
if isinstance(node, ast.Call):
|
|
564
|
+
return get_name(node.func)
|
|
565
|
+
if isinstance(node, ast.Constant):
|
|
566
|
+
return str(node.value)
|
|
567
|
+
return ""
|
|
568
|
+
|
|
569
|
+
def leaf_name(node):
|
|
570
|
+
# Declared name of the callee: \`join\` of \`os.path.join\`. Matches how the
|
|
571
|
+
# TypeScript and Go extractors record call refs.
|
|
572
|
+
if isinstance(node, ast.Attribute):
|
|
573
|
+
return node.attr
|
|
574
|
+
if isinstance(node, ast.Name):
|
|
575
|
+
return node.id
|
|
576
|
+
return get_name(node).split(".")[-1]
|
|
577
|
+
|
|
578
|
+
def is_private(name):
|
|
579
|
+
return name.startswith("__") and not name.endswith("__")
|
|
580
|
+
|
|
581
|
+
def first_doc_line(node):
|
|
582
|
+
try:
|
|
583
|
+
doc = ast.get_docstring(node)
|
|
584
|
+
except Exception:
|
|
585
|
+
return ""
|
|
586
|
+
for line in (doc or "").splitlines():
|
|
587
|
+
line = line.strip()
|
|
588
|
+
if line:
|
|
589
|
+
return line[:200]
|
|
590
|
+
return ""
|
|
591
|
+
|
|
592
|
+
def module_name_of(path):
|
|
593
|
+
base = path.replace("\\\\", "/").rsplit("/", 1)[-1]
|
|
594
|
+
return base.rsplit(".", 1)[0] if "." in base else base
|
|
595
|
+
|
|
596
|
+
def read_stdin_text():
|
|
597
|
+
# Decode explicitly: sys.stdin uses the locale code page on Windows
|
|
598
|
+
# (cp1254, cp1252, ...), which mangles or rejects the UTF-8 we are sent.
|
|
599
|
+
return sys.stdin.buffer.read().decode("utf-8", "replace")
|
|
600
|
+
|
|
601
|
+
def parse_source(text, name):
|
|
602
|
+
# ast.parse rejects a leading U+FEFF in a str source.
|
|
603
|
+
if text.startswith("\\ufeff"):
|
|
604
|
+
text = text[1:]
|
|
605
|
+
return ast.parse(text, filename=name or "<module>")
|
|
606
|
+
|
|
607
|
+
def format_args(args):
|
|
608
|
+
parts = [a.arg for a in list(getattr(args, "posonlyargs", [])) + list(args.args)]
|
|
609
|
+
if args.vararg is not None:
|
|
610
|
+
parts.append("*" + args.vararg.arg)
|
|
611
|
+
elif args.kwonlyargs:
|
|
612
|
+
parts.append("*")
|
|
613
|
+
parts.extend(a.arg for a in args.kwonlyargs)
|
|
614
|
+
if args.kwarg is not None:
|
|
615
|
+
parts.append("**" + args.kwarg.arg)
|
|
616
|
+
return ", ".join(parts)
|
|
617
|
+
|
|
618
|
+
def extract(tree, module_name):
|
|
619
|
+
syms = []
|
|
620
|
+
refs = []
|
|
621
|
+
scope = [module_name]
|
|
622
|
+
|
|
623
|
+
def add(name, kind, line, col, signature, sym_scope, doc=""):
|
|
624
|
+
syms.append({
|
|
625
|
+
"name": name, "kind": kind, "line": line, "col": col,
|
|
626
|
+
"signature": signature, "scope": sym_scope, "doc": doc,
|
|
627
|
+
})
|
|
628
|
+
|
|
629
|
+
def qualified(name):
|
|
630
|
+
return ".".join(scope) + "." + name
|
|
631
|
+
|
|
632
|
+
# Kinds are the index schema's (class/function/method/property/var/const/
|
|
633
|
+
# type). Imports are refs, not symbols: an import symbol per file made
|
|
634
|
+
# every imported name look like a definition in every importing module.
|
|
635
|
+
class Visitor(ast.NodeVisitor):
|
|
636
|
+
in_class = False
|
|
637
|
+
|
|
638
|
+
def visit_ClassDef(self, node):
|
|
639
|
+
bases = [get_name(b) for b in node.bases]
|
|
640
|
+
sig = "class " + node.name + ("(" + ", ".join(bases) + ")" if bases else "") + ": ..."
|
|
641
|
+
add(node.name, "class", node.lineno, node.col_offset, sig, qualified(node.name), first_doc_line(node))
|
|
642
|
+
scope.append(node.name)
|
|
643
|
+
outer = self.in_class
|
|
644
|
+
self.in_class = True
|
|
645
|
+
try:
|
|
646
|
+
self.generic_visit(node)
|
|
647
|
+
finally:
|
|
648
|
+
self.in_class = outer
|
|
649
|
+
scope.pop()
|
|
650
|
+
|
|
651
|
+
def visit_FunctionDef(self, node):
|
|
652
|
+
kind = "method" if self.in_class else "function"
|
|
653
|
+
for dec in node.decorator_list:
|
|
654
|
+
if get_name(dec).rsplit(".", 1)[-1] in PROPERTY_DECORATORS:
|
|
655
|
+
kind = "property"
|
|
656
|
+
prefix = "async def " if isinstance(node, ast.AsyncFunctionDef) else "def "
|
|
657
|
+
sig = prefix + node.name + "(" + format_args(node.args) + ")"
|
|
658
|
+
returns = get_name(node.returns) if node.returns is not None else ""
|
|
659
|
+
if returns:
|
|
660
|
+
sig += " -> " + returns
|
|
661
|
+
add(node.name, kind, node.lineno, node.col_offset, sig, qualified(node.name), first_doc_line(node))
|
|
662
|
+
# Bodies are not visited: function locals are not index symbols.
|
|
663
|
+
|
|
664
|
+
visit_AsyncFunctionDef = visit_FunctionDef
|
|
665
|
+
|
|
666
|
+
def add_target(self, target, line, annotation=None, has_value=True):
|
|
667
|
+
if isinstance(target, ast.Name):
|
|
668
|
+
if is_private(target.id):
|
|
669
|
+
return
|
|
670
|
+
kind = "const" if target.id.isupper() else "var"
|
|
671
|
+
if annotation is not None:
|
|
672
|
+
sig = target.id + ": " + get_name(annotation) + (" = ..." if has_value else "")
|
|
673
|
+
else:
|
|
674
|
+
sig = target.id + " = ..."
|
|
675
|
+
add(target.id, kind, line, target.col_offset, sig, ".".join(scope))
|
|
676
|
+
elif isinstance(target, (ast.Tuple, ast.List)):
|
|
677
|
+
for elt in target.elts:
|
|
678
|
+
self.add_target(elt, line)
|
|
679
|
+
elif isinstance(target, ast.Starred):
|
|
680
|
+
self.add_target(target.value, line)
|
|
681
|
+
|
|
682
|
+
def visit_Assign(self, node):
|
|
683
|
+
for target in node.targets:
|
|
684
|
+
self.add_target(target, node.lineno)
|
|
685
|
+
|
|
686
|
+
def visit_AnnAssign(self, node):
|
|
687
|
+
self.add_target(node.target, node.lineno, node.annotation, node.value is not None)
|
|
688
|
+
|
|
689
|
+
def visit_TypeAlias(self, node):
|
|
690
|
+
if isinstance(node.name, ast.Name):
|
|
691
|
+
add(node.name.id, "type", node.lineno, node.col_offset, "type " + node.name.id + " = ...", ".".join(scope))
|
|
692
|
+
|
|
693
|
+
Visitor().visit(tree)
|
|
694
|
+
|
|
695
|
+
# Refs need a full walk: the visitor deliberately skips function bodies,
|
|
696
|
+
# which is exactly where the calls are.
|
|
697
|
+
for node in ast.walk(tree):
|
|
698
|
+
if isinstance(node, ast.Call):
|
|
699
|
+
name = leaf_name(node.func)
|
|
700
|
+
if name:
|
|
701
|
+
refs.append({"toName": name, "callType": "call", "line": node.lineno})
|
|
702
|
+
elif isinstance(node, ast.Import):
|
|
703
|
+
for alias in node.names:
|
|
704
|
+
refs.append({
|
|
705
|
+
"toName": alias.name.split(".")[-1], "callType": "import",
|
|
706
|
+
"line": node.lineno, "module": alias.name,
|
|
707
|
+
})
|
|
708
|
+
elif isinstance(node, ast.ImportFrom):
|
|
709
|
+
# PEP 328: keep the leading dots so the resolver can walk up from
|
|
710
|
+
# the importing file's package.
|
|
711
|
+
module = ("." * (node.level or 0)) + (node.module or "")
|
|
712
|
+
for alias in node.names:
|
|
713
|
+
refs.append({
|
|
714
|
+
"toName": alias.name, "callType": "import",
|
|
715
|
+
"line": node.lineno, "module": module,
|
|
716
|
+
})
|
|
717
|
+
elif isinstance(node, ast.ClassDef):
|
|
718
|
+
for base in node.bases:
|
|
719
|
+
name = leaf_name(base)
|
|
720
|
+
if name:
|
|
721
|
+
refs.append({"toName": name, "callType": "inherit", "line": node.lineno})
|
|
722
|
+
|
|
723
|
+
return syms, refs
|
|
724
|
+
`;
|
|
725
|
+
var PY_PARSE_SCRIPT = `${PY_CORE}
|
|
726
|
+
def main():
|
|
727
|
+
name = sys.argv[1] if len(sys.argv) > 1 else "module.py"
|
|
728
|
+
try:
|
|
729
|
+
syms, refs = extract(parse_source(read_stdin_text(), name), module_name_of(name))
|
|
730
|
+
except Exception:
|
|
731
|
+
syms, refs = [], []
|
|
732
|
+
print(json.dumps({"symbols": syms, "refs": refs}))
|
|
733
|
+
|
|
734
|
+
main()
|
|
735
|
+
`;
|
|
736
|
+
var PY_BATCH_SCRIPT = `${PY_CORE}
|
|
737
|
+
def main():
|
|
738
|
+
try:
|
|
739
|
+
inputs = json.loads(read_stdin_text())
|
|
740
|
+
except Exception:
|
|
741
|
+
print(json.dumps({"version": 1, "results": []}))
|
|
742
|
+
return
|
|
743
|
+
results = []
|
|
744
|
+
for entry in inputs:
|
|
745
|
+
name = entry.get("file", "")
|
|
746
|
+
result = {"file": name, "symbols": [], "refs": []}
|
|
747
|
+
try:
|
|
748
|
+
syms, refs = extract(parse_source(entry.get("content", ""), name), module_name_of(name))
|
|
749
|
+
result["symbols"] = syms
|
|
750
|
+
result["refs"] = refs
|
|
751
|
+
except Exception as e:
|
|
752
|
+
result["error"] = str(e) or type(e).__name__
|
|
753
|
+
results.append(result)
|
|
754
|
+
print(json.dumps({"version": 1, "results": results}))
|
|
755
|
+
|
|
756
|
+
main()
|
|
757
|
+
`;
|
|
758
|
+
var scriptPaths = /* @__PURE__ */ new Map();
|
|
759
|
+
function privateScriptPath(prefix, fileName, script) {
|
|
760
|
+
const key = `${prefix}\0${fileName}`;
|
|
761
|
+
const cached = scriptPaths.get(key);
|
|
762
|
+
if (cached) return cached;
|
|
763
|
+
const pending = writePrivateScript(prefix, fileName, script);
|
|
764
|
+
scriptPaths.set(key, pending);
|
|
765
|
+
pending.catch(() => {
|
|
766
|
+
if (scriptPaths.get(key) === pending) scriptPaths.delete(key);
|
|
767
|
+
});
|
|
768
|
+
return pending;
|
|
769
|
+
}
|
|
770
|
+
async function writePrivateScript(prefix, fileName, script) {
|
|
771
|
+
const dir = await fs.mkdtemp(path.join(os.tmpdir(), prefix));
|
|
772
|
+
const scriptPath = path.join(dir, fileName);
|
|
773
|
+
await fs.writeFile(scriptPath, script, { encoding: "utf8", flag: "wx" });
|
|
774
|
+
process.once("exit", () => {
|
|
775
|
+
try {
|
|
776
|
+
fsSync.rmSync(dir, { recursive: true, force: true });
|
|
777
|
+
} catch {
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
return scriptPath;
|
|
781
|
+
}
|
|
782
|
+
function goSpawnOptions(scriptPath) {
|
|
783
|
+
return {
|
|
784
|
+
cwd: path.dirname(scriptPath),
|
|
785
|
+
env: { ...process.env, GOTOOLCHAIN: "local", GOWORK: "off" }
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
function pySpawnOptions(scriptPath) {
|
|
789
|
+
return { cwd: path.dirname(scriptPath) };
|
|
790
|
+
}
|
|
791
|
+
function runToolchainChild(binary, args, stdinPayload, timeoutMs, options) {
|
|
792
|
+
return new Promise((resolve) => {
|
|
793
|
+
let settled = false;
|
|
794
|
+
let stdout = "";
|
|
795
|
+
let proc;
|
|
796
|
+
try {
|
|
797
|
+
recordParserSubprocess();
|
|
798
|
+
proc = spawn(binary, args, {
|
|
799
|
+
cwd: options.cwd,
|
|
800
|
+
env: options.env ?? process.env,
|
|
801
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
802
|
+
windowsHide: true
|
|
803
|
+
});
|
|
804
|
+
} catch {
|
|
805
|
+
resolve(null);
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
const finish = (value) => {
|
|
809
|
+
if (settled) return;
|
|
810
|
+
settled = true;
|
|
811
|
+
clearTimeout(timer);
|
|
812
|
+
resolve(value);
|
|
813
|
+
};
|
|
814
|
+
const timer = setTimeout(() => {
|
|
815
|
+
proc.kill("SIGKILL");
|
|
816
|
+
finish(null);
|
|
817
|
+
}, timeoutMs);
|
|
818
|
+
timer.unref?.();
|
|
819
|
+
proc.on("error", () => finish(null));
|
|
820
|
+
const stdoutDecoder = new StringDecoder("utf8");
|
|
821
|
+
proc.stdout?.on("data", (chunk) => {
|
|
822
|
+
stdout += stdoutDecoder.write(chunk);
|
|
823
|
+
});
|
|
824
|
+
proc.stderr?.resume();
|
|
825
|
+
proc.stdin?.on("error", () => {
|
|
826
|
+
});
|
|
827
|
+
proc.stdin?.write(stdinPayload);
|
|
828
|
+
proc.stdin?.end();
|
|
829
|
+
proc.on("close", (code) => {
|
|
830
|
+
stdout += stdoutDecoder.end();
|
|
831
|
+
finish({ code, stdout });
|
|
832
|
+
});
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
export {
|
|
837
|
+
toIndexSymbols,
|
|
838
|
+
parseParserOutput,
|
|
839
|
+
parseParserBatchOutput,
|
|
840
|
+
resetCodebaseIndexPerfMetrics,
|
|
841
|
+
getCodebaseIndexPerfSnapshot,
|
|
842
|
+
recordFilesystemRead,
|
|
843
|
+
recordIpcPending,
|
|
844
|
+
recordWriteQueueWait,
|
|
845
|
+
withSpawnGate,
|
|
846
|
+
GO_PARSE_SCRIPT,
|
|
847
|
+
GO_BATCH_SCRIPT,
|
|
848
|
+
PY_PARSE_SCRIPT,
|
|
849
|
+
PY_BATCH_SCRIPT,
|
|
850
|
+
privateScriptPath,
|
|
851
|
+
goSpawnOptions,
|
|
852
|
+
pySpawnOptions,
|
|
853
|
+
runToolchainChild
|
|
854
|
+
};
|
|
855
|
+
//# sourceMappingURL=chunk-OIFY4XNP.js.map
|