@ctxo/lang-go 0.7.0 → 0.8.0-alpha.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.
package/dist/index.js CHANGED
@@ -1,3 +1,420 @@
1
+ // src/analyzer/analyzer-adapter.ts
2
+ import { relative } from "path";
3
+
4
+ // src/logger.ts
5
+ function enabledFor(namespace) {
6
+ const env = process.env["DEBUG"];
7
+ if (!env) return false;
8
+ const patterns = env.split(",").map((p) => p.trim()).filter(Boolean);
9
+ for (const pattern of patterns) {
10
+ if (pattern === "*" || pattern === namespace) return true;
11
+ if (pattern.endsWith("*") && namespace.startsWith(pattern.slice(0, -1))) return true;
12
+ }
13
+ return false;
14
+ }
15
+ function emit(namespace, level, message, args) {
16
+ const line = `[${namespace}] ${message}${args.length ? " " + args.map(String).join(" ") : ""}`;
17
+ if (level === "error") process.stderr.write(line + "\n");
18
+ else if (level === "warn") process.stderr.write(line + "\n");
19
+ else if (enabledFor(namespace)) process.stderr.write(line + "\n");
20
+ }
21
+ function createLogger(namespace) {
22
+ return {
23
+ debug: (msg, ...args) => emit(namespace, "debug", msg, args),
24
+ info: (msg, ...args) => emit(namespace, "info", msg, args),
25
+ warn: (msg, ...args) => emit(namespace, "warn", msg, args),
26
+ error: (msg, ...args) => emit(namespace, "error", msg, args)
27
+ };
28
+ }
29
+
30
+ // src/analyzer/toolchain-detect.ts
31
+ import { execFileSync } from "child_process";
32
+ var log = createLogger("ctxo:lang-go");
33
+ var MIN_MAJOR = 1;
34
+ var MIN_MINOR = 22;
35
+ function detectGoToolchain() {
36
+ try {
37
+ const out = execFileSync("go", ["version"], { encoding: "utf-8", timeout: 1e4 }).trim();
38
+ const match = out.match(/go(\d+)\.(\d+)(?:\.(\d+))?/);
39
+ if (!match) {
40
+ log.info(`Could not parse go version output: ${out}`);
41
+ return { available: false };
42
+ }
43
+ const major = parseInt(match[1], 10);
44
+ const minor = parseInt(match[2], 10);
45
+ const version = match[3] ? `${major}.${minor}.${match[3]}` : `${major}.${minor}`;
46
+ if (major < MIN_MAJOR || major === MIN_MAJOR && minor < MIN_MINOR) {
47
+ log.info(`go ${version} found but >= ${MIN_MAJOR}.${MIN_MINOR} required`);
48
+ return { available: false, version };
49
+ }
50
+ return { available: true, version };
51
+ } catch {
52
+ return { available: false };
53
+ }
54
+ }
55
+
56
+ // src/analyzer/module-discovery.ts
57
+ import { existsSync, readdirSync } from "fs";
58
+ import { dirname, join, resolve } from "path";
59
+ var log2 = createLogger("ctxo:lang-go");
60
+ var IGNORE_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", ".ctxo", "vendor", "dist", "build"]);
61
+ function discoverGoModule(rootDir) {
62
+ let dir = resolve(rootDir);
63
+ for (let i = 0; i < 10; i++) {
64
+ if (existsSync(join(dir, "go.work"))) return dir;
65
+ if (existsSync(join(dir, "go.mod"))) return dir;
66
+ const parent = dirname(dir);
67
+ if (parent === dir) break;
68
+ dir = parent;
69
+ }
70
+ return findShallow(rootDir, 3);
71
+ }
72
+ function findShallow(dir, maxDepth, depth = 0) {
73
+ if (depth > maxDepth) return null;
74
+ try {
75
+ const entries = readdirSync(dir, { withFileTypes: true });
76
+ for (const e of entries) {
77
+ if (e.isFile() && (e.name === "go.work" || e.name === "go.mod")) {
78
+ return dir;
79
+ }
80
+ }
81
+ for (const e of entries) {
82
+ if (e.isDirectory() && !IGNORE_DIRS.has(e.name) && !e.name.startsWith(".")) {
83
+ const found = findShallow(join(dir, e.name), maxDepth, depth + 1);
84
+ if (found) return found;
85
+ }
86
+ }
87
+ } catch {
88
+ }
89
+ return null;
90
+ }
91
+ function findPackageRoot(startDir) {
92
+ let dir = startDir;
93
+ for (let i = 0; i < 10; i++) {
94
+ if (existsSync(join(dir, "package.json"))) return dir;
95
+ const parent = dirname(dir);
96
+ if (parent === dir) break;
97
+ dir = parent;
98
+ }
99
+ return null;
100
+ }
101
+ function findMonorepoRoot(startDir) {
102
+ let dir = startDir;
103
+ for (let i = 0; i < 12; i++) {
104
+ if (existsSync(join(dir, "pnpm-workspace.yaml"))) return dir;
105
+ const parent = dirname(dir);
106
+ if (parent === dir) break;
107
+ dir = parent;
108
+ }
109
+ return null;
110
+ }
111
+ function findCtxoGoAnalyzerSource() {
112
+ const pkgRoot = findPackageRoot(import.meta.dirname);
113
+ const monorepoRoot = findMonorepoRoot(import.meta.dirname);
114
+ const candidates = [
115
+ ...pkgRoot ? [join(pkgRoot, "tools/ctxo-go-analyzer")] : [],
116
+ ...monorepoRoot ? [join(monorepoRoot, "packages/lang-go/tools/ctxo-go-analyzer")] : [],
117
+ join(import.meta.dirname, "../tools/ctxo-go-analyzer"),
118
+ join(import.meta.dirname, "../../tools/ctxo-go-analyzer"),
119
+ join(import.meta.dirname, "../../../tools/ctxo-go-analyzer"),
120
+ join(process.cwd(), "node_modules/@ctxo/lang-go/tools/ctxo-go-analyzer")
121
+ ];
122
+ for (const candidate of candidates) {
123
+ if (existsSync(join(candidate, "go.mod")) && existsSync(join(candidate, "main.go"))) {
124
+ return candidate;
125
+ }
126
+ }
127
+ log2.info("ctxo-go-analyzer source not found in any candidate location");
128
+ return null;
129
+ }
130
+
131
+ // src/analyzer/binary-build.ts
132
+ import { execFileSync as execFileSync2 } from "child_process";
133
+ import { createHash } from "crypto";
134
+ import { existsSync as existsSync2, mkdirSync, readdirSync as readdirSync2, readFileSync } from "fs";
135
+ import { homedir, platform } from "os";
136
+ import { join as join2 } from "path";
137
+ var log3 = createLogger("ctxo:lang-go");
138
+ var BINARY_NAME = platform() === "win32" ? "ctxo-go-analyzer.exe" : "ctxo-go-analyzer";
139
+ var BUILD_TIMEOUT_MS = 18e4;
140
+ function ensureAnalyzerBinary(sourceDir, goVersion) {
141
+ const key = `${hashSourceTree(sourceDir)}-go${goVersion}`;
142
+ const cacheDir = join2(homedir(), ".cache", "ctxo", "lang-go-analyzer", key);
143
+ const binaryPath = join2(cacheDir, BINARY_NAME);
144
+ if (existsSync2(binaryPath)) return binaryPath;
145
+ mkdirSync(cacheDir, { recursive: true });
146
+ log3.info(`Building ctxo-go-analyzer (first run): ${binaryPath}`);
147
+ try {
148
+ execFileSync2("go", ["build", "-trimpath", "-o", binaryPath, "."], {
149
+ cwd: sourceDir,
150
+ timeout: BUILD_TIMEOUT_MS,
151
+ stdio: ["ignore", "inherit", "inherit"]
152
+ });
153
+ } catch (err) {
154
+ throw new Error(`go build failed: ${err.message}`);
155
+ }
156
+ if (!existsSync2(binaryPath)) {
157
+ throw new Error("go build completed but expected binary is missing");
158
+ }
159
+ return binaryPath;
160
+ }
161
+ function hashSourceTree(dir) {
162
+ const hash = createHash("sha1");
163
+ const files = [];
164
+ walk(dir, (path) => {
165
+ if (path.endsWith(".go") || path.endsWith("go.mod") || path.endsWith("go.sum")) {
166
+ files.push(path);
167
+ }
168
+ });
169
+ files.sort();
170
+ for (const f of files) {
171
+ hash.update(f);
172
+ hash.update(readFileSync(f));
173
+ }
174
+ return hash.digest("hex").slice(0, 12);
175
+ }
176
+ function walk(dir, cb) {
177
+ let entries;
178
+ try {
179
+ entries = readdirSync2(dir, { withFileTypes: true });
180
+ } catch {
181
+ return;
182
+ }
183
+ for (const entry of entries) {
184
+ const path = join2(dir, String(entry.name));
185
+ if (entry.isDirectory()) walk(path, cb);
186
+ else if (entry.isFile()) cb(path);
187
+ }
188
+ }
189
+
190
+ // src/analyzer/analyzer-process.ts
191
+ import { spawn } from "child_process";
192
+ var log4 = createLogger("ctxo:lang-go");
193
+ async function runBatchAnalyze(binaryPath, moduleRoot, timeoutMs = 12e4) {
194
+ return new Promise((resolve2) => {
195
+ const empty = {
196
+ files: [],
197
+ dead: [],
198
+ hasMain: false,
199
+ timeout: false,
200
+ totalFiles: 0,
201
+ elapsed: ""
202
+ };
203
+ const proc = spawn(binaryPath, ["--root", moduleRoot], {
204
+ stdio: ["ignore", "pipe", "pipe"],
205
+ timeout: timeoutMs
206
+ });
207
+ const files = [];
208
+ let dead = [];
209
+ let hasMain = false;
210
+ let timeout = false;
211
+ let totalFiles = 0;
212
+ let elapsed = "";
213
+ let stderr = "";
214
+ let buffer = "";
215
+ proc.stdout.on("data", (chunk) => {
216
+ buffer += chunk.toString();
217
+ let nl;
218
+ while ((nl = buffer.indexOf("\n")) !== -1) {
219
+ const line = buffer.slice(0, nl).trim();
220
+ buffer = buffer.slice(nl + 1);
221
+ if (!line) continue;
222
+ try {
223
+ const obj = JSON.parse(line);
224
+ switch (obj.type) {
225
+ case "file":
226
+ files.push(obj);
227
+ break;
228
+ case "dead":
229
+ dead = Array.isArray(obj.symbolIds) ? obj.symbolIds : [];
230
+ hasMain = Boolean(obj.hasMain);
231
+ timeout = Boolean(obj.timeout);
232
+ break;
233
+ case "progress":
234
+ log4.info(String(obj.message ?? ""));
235
+ break;
236
+ case "summary":
237
+ totalFiles = Number(obj.totalFiles ?? 0);
238
+ elapsed = String(obj.elapsed ?? "");
239
+ break;
240
+ }
241
+ } catch {
242
+ log4.error(`Failed to parse JSONL line: ${line.slice(0, 120)}`);
243
+ }
244
+ }
245
+ });
246
+ proc.stderr.on("data", (chunk) => {
247
+ stderr += chunk.toString();
248
+ });
249
+ proc.on("close", (code) => {
250
+ if (code !== 0) {
251
+ log4.error(`ctxo-go-analyzer exited with code ${code}: ${stderr.trim().slice(0, 500)}`);
252
+ resolve2(empty);
253
+ return;
254
+ }
255
+ resolve2({ files, dead, hasMain, timeout, totalFiles, elapsed });
256
+ });
257
+ proc.on("error", (err) => {
258
+ log4.error(`ctxo-go-analyzer spawn error: ${err.message}`);
259
+ resolve2(empty);
260
+ });
261
+ });
262
+ }
263
+
264
+ // src/analyzer/analyzer-adapter.ts
265
+ var log5 = createLogger("ctxo:lang-go");
266
+ var VALID_SYMBOL_ID = /^.+::.+::.+$/;
267
+ var GoAnalyzerAdapter = class {
268
+ extensions = [".go"];
269
+ tier = "full";
270
+ moduleRoot = null;
271
+ binaryPath = null;
272
+ modulePathPrefix = "";
273
+ cache = /* @__PURE__ */ new Map();
274
+ deadSymbolIds = /* @__PURE__ */ new Set();
275
+ hasMain = false;
276
+ timedOut = false;
277
+ batchPromise = null;
278
+ initialized = false;
279
+ isSupported(filePath) {
280
+ return filePath.endsWith(".go");
281
+ }
282
+ isReady() {
283
+ return this.initialized && this.binaryPath !== null && this.moduleRoot !== null;
284
+ }
285
+ async initialize(rootDir) {
286
+ const toolchain = detectGoToolchain();
287
+ if (!toolchain.available) {
288
+ log5.info(`Go analyzer unavailable: go ${toolchain.version ?? "not found"} (>= 1.22 required)`);
289
+ return;
290
+ }
291
+ const moduleRoot = discoverGoModule(rootDir);
292
+ if (!moduleRoot) {
293
+ log5.info("Go analyzer unavailable: no go.mod or go.work found");
294
+ return;
295
+ }
296
+ this.moduleRoot = moduleRoot;
297
+ const prefix = relative(rootDir, moduleRoot).replace(/\\/g, "/");
298
+ this.modulePathPrefix = prefix && prefix !== "." ? prefix : "";
299
+ const sourceDir = findCtxoGoAnalyzerSource();
300
+ if (!sourceDir) {
301
+ log5.info("Go analyzer unavailable: ctxo-go-analyzer source not located");
302
+ return;
303
+ }
304
+ try {
305
+ this.binaryPath = ensureAnalyzerBinary(sourceDir, toolchain.version);
306
+ } catch (err) {
307
+ log5.warn(`Go analyzer binary build failed: ${err.message}`);
308
+ return;
309
+ }
310
+ log5.info(`Go analyzer ready: go ${toolchain.version}, module ${moduleRoot}`);
311
+ this.initialized = true;
312
+ }
313
+ /**
314
+ * Returns the dead-symbol set emitted by the last batch run. Empty until
315
+ * extractSymbols/Edges has been called at least once. Consumed by cli's
316
+ * find_dead_code MCP tool via the composite delegate.
317
+ */
318
+ getDeadSymbolIds() {
319
+ return this.deadSymbolIds;
320
+ }
321
+ /** True when the analyzer ran in binary mode (precise dead-code). */
322
+ reachabilityHasMain() {
323
+ return this.hasMain;
324
+ }
325
+ /** True when reach analysis exceeded the deadline (degraded precision). */
326
+ reachabilityTimedOut() {
327
+ return this.timedOut;
328
+ }
329
+ async extractSymbols(filePath, _source) {
330
+ if (!this.isReady()) return [];
331
+ await this.ensureBatch();
332
+ const file = this.cache.get(this.normalizePath(filePath));
333
+ if (!file) return [];
334
+ return file.symbols.filter((s) => VALID_SYMBOL_ID.test(s.symbolId)).map((s) => ({
335
+ symbolId: s.symbolId,
336
+ name: s.name,
337
+ kind: s.kind,
338
+ startLine: s.startLine,
339
+ endLine: s.endLine,
340
+ ...s.startOffset != null ? { startOffset: s.startOffset } : {},
341
+ ...s.endOffset != null ? { endOffset: s.endOffset } : {}
342
+ }));
343
+ }
344
+ async extractEdges(filePath, _source) {
345
+ if (!this.isReady()) return [];
346
+ await this.ensureBatch();
347
+ const file = this.cache.get(this.normalizePath(filePath));
348
+ if (!file) return [];
349
+ return file.edges.filter((e) => VALID_SYMBOL_ID.test(e.from) && VALID_SYMBOL_ID.test(e.to)).map((e) => ({
350
+ from: e.from,
351
+ to: e.to,
352
+ kind: e.kind
353
+ }));
354
+ }
355
+ async extractComplexity(_filePath, _source) {
356
+ return [];
357
+ }
358
+ async dispose() {
359
+ this.cache.clear();
360
+ this.deadSymbolIds.clear();
361
+ this.batchPromise = null;
362
+ this.initialized = false;
363
+ }
364
+ async ensureBatch() {
365
+ if (this.batchPromise) return this.batchPromise;
366
+ this.batchPromise = this.runBatch();
367
+ return this.batchPromise;
368
+ }
369
+ async runBatch() {
370
+ if (!this.binaryPath || !this.moduleRoot) return;
371
+ const result = await runBatchAnalyze(this.binaryPath, this.moduleRoot);
372
+ this.absorbBatch(result);
373
+ log5.info(`Go analyzer batch: ${result.totalFiles} files in ${result.elapsed}, ${result.dead.length} dead`);
374
+ }
375
+ absorbBatch(result) {
376
+ this.cache.clear();
377
+ this.deadSymbolIds.clear();
378
+ this.hasMain = result.hasMain;
379
+ this.timedOut = result.timeout;
380
+ const rewrite = this.buildPathRewriter();
381
+ for (const file of result.files) {
382
+ const projectRel = rewrite(file.file);
383
+ this.cache.set(projectRel, {
384
+ ...file,
385
+ file: projectRel,
386
+ symbols: file.symbols.map((s) => ({ ...s, symbolId: rewriteId(s.symbolId, file.file, projectRel) })),
387
+ edges: file.edges.map((e) => ({
388
+ ...e,
389
+ from: rewriteId(e.from, file.file, projectRel),
390
+ to: rewriteIdAcrossModule(e.to, this.modulePathPrefix)
391
+ }))
392
+ });
393
+ }
394
+ for (const id of result.dead) {
395
+ this.deadSymbolIds.add(rewriteIdAcrossModule(id, this.modulePathPrefix));
396
+ }
397
+ }
398
+ normalizePath(filePath) {
399
+ return filePath.replace(/\\/g, "/");
400
+ }
401
+ buildPathRewriter() {
402
+ if (!this.modulePathPrefix) return (p) => p;
403
+ const prefix = this.modulePathPrefix;
404
+ return (p) => `${prefix}/${p}`;
405
+ }
406
+ };
407
+ function rewriteId(id, analyzerFile, projectFile) {
408
+ if (analyzerFile === projectFile) return id;
409
+ return id.startsWith(`${analyzerFile}::`) ? `${projectFile}${id.slice(analyzerFile.length)}` : id;
410
+ }
411
+ function rewriteIdAcrossModule(id, prefix) {
412
+ if (!prefix) return id;
413
+ const sepIdx = id.indexOf("::");
414
+ if (sepIdx <= 0) return id;
415
+ return `${prefix}/${id}`;
416
+ }
417
+
1
418
  // src/go-adapter.ts
2
419
  import GoLanguage from "tree-sitter-go";
3
420
 
@@ -49,6 +466,7 @@ var TreeSitterAdapter = class {
49
466
  };
50
467
 
51
468
  // src/go-adapter.ts
469
+ var log6 = createLogger("ctxo:lang-go");
52
470
  var GO_BRANCH_TYPES = [
53
471
  "if_statement",
54
472
  "for_statement",
@@ -72,7 +490,7 @@ var GoAdapter = class extends TreeSitterAdapter {
72
490
  const node = tree.rootNode.child(i);
73
491
  if (node.type === "function_declaration") {
74
492
  const name = node.childForFieldName("name")?.text;
75
- if (!name || !this.isExported(name)) continue;
493
+ if (!name) continue;
76
494
  const range = this.nodeToLineRange(node);
77
495
  symbols.push({
78
496
  symbolId: this.buildSymbolId(filePath, name, "function"),
@@ -83,7 +501,7 @@ var GoAdapter = class extends TreeSitterAdapter {
83
501
  }
84
502
  if (node.type === "method_declaration") {
85
503
  const methodName = node.childForFieldName("name")?.text;
86
- if (!methodName || !this.isExported(methodName)) continue;
504
+ if (!methodName) continue;
87
505
  const receiverType = this.extractReceiverType(node);
88
506
  const qualifiedName = receiverType ? `${receiverType}.${methodName}` : methodName;
89
507
  const range = this.nodeToLineRange(node);
@@ -100,7 +518,7 @@ var GoAdapter = class extends TreeSitterAdapter {
100
518
  }
101
519
  return symbols;
102
520
  } catch (err) {
103
- console.error(`[ctxo:go] Symbol extraction failed for ${filePath}: ${err.message}`);
521
+ log6.error(`Symbol extraction failed for ${filePath}: ${err.message}`);
104
522
  return [];
105
523
  }
106
524
  }
@@ -118,7 +536,7 @@ var GoAdapter = class extends TreeSitterAdapter {
118
536
  }
119
537
  return edges;
120
538
  } catch (err) {
121
- console.error(`[ctxo:go] Edge extraction failed for ${filePath}: ${err.message}`);
539
+ log6.error(`Edge extraction failed for ${filePath}: ${err.message}`);
122
540
  return [];
123
541
  }
124
542
  }
@@ -130,7 +548,7 @@ var GoAdapter = class extends TreeSitterAdapter {
130
548
  const node = tree.rootNode.child(i);
131
549
  if (node.type === "function_declaration") {
132
550
  const name = node.childForFieldName("name")?.text;
133
- if (!name || !this.isExported(name)) continue;
551
+ if (!name) continue;
134
552
  metrics.push({
135
553
  symbolId: this.buildSymbolId(filePath, name, "function"),
136
554
  cyclomatic: this.countCyclomaticComplexity(node, GO_BRANCH_TYPES)
@@ -138,7 +556,7 @@ var GoAdapter = class extends TreeSitterAdapter {
138
556
  }
139
557
  if (node.type === "method_declaration") {
140
558
  const methodName = node.childForFieldName("name")?.text;
141
- if (!methodName || !this.isExported(methodName)) continue;
559
+ if (!methodName) continue;
142
560
  const receiverType = this.extractReceiverType(node);
143
561
  const qualifiedName = receiverType ? `${receiverType}.${methodName}` : methodName;
144
562
  metrics.push({
@@ -149,7 +567,7 @@ var GoAdapter = class extends TreeSitterAdapter {
149
567
  }
150
568
  return metrics;
151
569
  } catch (err) {
152
- console.error(`[ctxo:go] Complexity extraction failed for ${filePath}: ${err.message}`);
570
+ log6.error(`Complexity extraction failed for ${filePath}: ${err.message}`);
153
571
  return [];
154
572
  }
155
573
  }
@@ -235,22 +653,76 @@ var GoAdapter = class extends TreeSitterAdapter {
235
653
  }
236
654
  };
237
655
 
656
+ // src/composite-adapter.ts
657
+ var log7 = createLogger("ctxo:lang-go");
658
+ var GoCompositeAdapter = class {
659
+ analyzer = null;
660
+ treeSitter;
661
+ constructor() {
662
+ this.treeSitter = new GoAdapter();
663
+ }
664
+ async initialize(rootDir) {
665
+ try {
666
+ const analyzer = new GoAnalyzerAdapter();
667
+ await analyzer.initialize(rootDir);
668
+ if (analyzer.isReady()) {
669
+ this.analyzer = analyzer;
670
+ log7.info("Go plugin: ctxo-go-analyzer full-tier active");
671
+ return;
672
+ }
673
+ await analyzer.dispose();
674
+ } catch (err) {
675
+ log7.warn(`Go analyzer unavailable: ${err.message}`);
676
+ }
677
+ log7.info("Go plugin: tree-sitter syntax-tier active (install Go 1.22+ for full tier)");
678
+ }
679
+ async dispose() {
680
+ if (this.analyzer) await this.analyzer.dispose();
681
+ }
682
+ extractSymbols(filePath, source) {
683
+ return (this.analyzer ?? this.treeSitter).extractSymbols(filePath, source);
684
+ }
685
+ extractEdges(filePath, source) {
686
+ return (this.analyzer ?? this.treeSitter).extractEdges(filePath, source);
687
+ }
688
+ extractComplexity(filePath, source) {
689
+ return this.treeSitter.extractComplexity(filePath, source);
690
+ }
691
+ isSupported(filePath) {
692
+ return filePath.toLowerCase().endsWith(".go");
693
+ }
694
+ setSymbolRegistry(registry) {
695
+ this.treeSitter.setSymbolRegistry?.(registry);
696
+ }
697
+ /** Exposed for cli optimizations. Null when running in syntax tier. */
698
+ getAnalyzerDelegate() {
699
+ return this.analyzer;
700
+ }
701
+ getTier() {
702
+ if (this.analyzer) return "full";
703
+ if (this.treeSitter) return "syntax";
704
+ return "unavailable";
705
+ }
706
+ };
707
+
238
708
  // src/index.ts
239
- var VERSION = "0.7.0-alpha.0";
709
+ var VERSION = "0.8.0-alpha.0";
240
710
  var plugin = {
241
711
  apiVersion: "1",
242
712
  id: "go",
243
- name: "Go (tree-sitter)",
713
+ name: "Go (ctxo-go-analyzer + tree-sitter)",
244
714
  version: VERSION,
245
715
  extensions: [".go"],
246
- tier: "syntax",
716
+ tier: "full",
247
717
  createAdapter(_ctx) {
248
- return new GoAdapter();
718
+ return new GoCompositeAdapter();
249
719
  }
250
720
  };
251
721
  var index_default = plugin;
252
722
  export {
253
723
  GoAdapter,
724
+ GoAnalyzerAdapter,
725
+ GoCompositeAdapter,
254
726
  TreeSitterAdapter,
255
727
  index_default as default,
256
728
  plugin