@compilr-dev/agents-coding-go 0.1.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/LICENSE +21 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/parser/go-parser.d.ts +104 -0
- package/dist/parser/go-parser.d.ts.map +1 -0
- package/dist/parser/go-parser.js +492 -0
- package/dist/parser/index.d.ts +6 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +5 -0
- package/dist/parser/node-types.d.ts +130 -0
- package/dist/parser/node-types.d.ts.map +1 -0
- package/dist/parser/node-types.js +4 -0
- package/dist/skills/go-best-practices.d.ts +7 -0
- package/dist/skills/go-best-practices.d.ts.map +1 -0
- package/dist/skills/go-best-practices.js +78 -0
- package/dist/skills/go-code-health.d.ts +7 -0
- package/dist/skills/go-code-health.d.ts.map +1 -0
- package/dist/skills/go-code-health.js +209 -0
- package/dist/skills/go-code-structure.d.ts +7 -0
- package/dist/skills/go-code-structure.d.ts.map +1 -0
- package/dist/skills/go-code-structure.js +155 -0
- package/dist/skills/go-dependency-audit.d.ts +7 -0
- package/dist/skills/go-dependency-audit.d.ts.map +1 -0
- package/dist/skills/go-dependency-audit.js +246 -0
- package/dist/skills/go-refactor-impact.d.ts +7 -0
- package/dist/skills/go-refactor-impact.d.ts.map +1 -0
- package/dist/skills/go-refactor-impact.js +232 -0
- package/dist/skills/index.d.ts +26 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +36 -0
- package/dist/tools/extract-docstrings.d.ts +51 -0
- package/dist/tools/extract-docstrings.d.ts.map +1 -0
- package/dist/tools/extract-docstrings.js +292 -0
- package/dist/tools/find-dead-code.d.ts +62 -0
- package/dist/tools/find-dead-code.d.ts.map +1 -0
- package/dist/tools/find-dead-code.js +422 -0
- package/dist/tools/find-duplicates.d.ts +65 -0
- package/dist/tools/find-duplicates.d.ts.map +1 -0
- package/dist/tools/find-duplicates.js +289 -0
- package/dist/tools/find-implementations.d.ts +71 -0
- package/dist/tools/find-implementations.d.ts.map +1 -0
- package/dist/tools/find-implementations.js +342 -0
- package/dist/tools/find-patterns.d.ts +71 -0
- package/dist/tools/find-patterns.d.ts.map +1 -0
- package/dist/tools/find-patterns.js +477 -0
- package/dist/tools/find-references.d.ts +66 -0
- package/dist/tools/find-references.d.ts.map +1 -0
- package/dist/tools/find-references.js +306 -0
- package/dist/tools/find-symbol.d.ts +86 -0
- package/dist/tools/find-symbol.d.ts.map +1 -0
- package/dist/tools/find-symbol.js +380 -0
- package/dist/tools/get-call-graph.d.ts +89 -0
- package/dist/tools/get-call-graph.d.ts.map +1 -0
- package/dist/tools/get-call-graph.js +431 -0
- package/dist/tools/get-class-hierarchy.d.ts +34 -0
- package/dist/tools/get-class-hierarchy.d.ts.map +1 -0
- package/dist/tools/get-class-hierarchy.js +250 -0
- package/dist/tools/get-complexity.d.ts +53 -0
- package/dist/tools/get-complexity.d.ts.map +1 -0
- package/dist/tools/get-complexity.js +357 -0
- package/dist/tools/get-dependency-graph.d.ts +85 -0
- package/dist/tools/get-dependency-graph.d.ts.map +1 -0
- package/dist/tools/get-dependency-graph.js +389 -0
- package/dist/tools/get-exports.d.ts +78 -0
- package/dist/tools/get-exports.d.ts.map +1 -0
- package/dist/tools/get-exports.js +437 -0
- package/dist/tools/get-file-structure.d.ts +28 -0
- package/dist/tools/get-file-structure.d.ts.map +1 -0
- package/dist/tools/get-file-structure.js +172 -0
- package/dist/tools/get-imports.d.ts +30 -0
- package/dist/tools/get-imports.d.ts.map +1 -0
- package/dist/tools/get-imports.js +420 -0
- package/dist/tools/get-signature.d.ts +100 -0
- package/dist/tools/get-signature.d.ts.map +1 -0
- package/dist/tools/get-signature.js +800 -0
- package/dist/tools/index.d.ts +55 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +75 -0
- package/dist/tools/types.d.ts +408 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +4 -0
- package/package.json +86 -0
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Go Parser using Tree-sitter
|
|
3
|
+
*
|
|
4
|
+
* Provides AST parsing and traversal for Go source files.
|
|
5
|
+
*/
|
|
6
|
+
import Parser from "tree-sitter";
|
|
7
|
+
import Go from "tree-sitter-go";
|
|
8
|
+
import { readFile } from "node:fs/promises";
|
|
9
|
+
// Initialize parser
|
|
10
|
+
const parser = new Parser();
|
|
11
|
+
// Cast to any to work around tree-sitter type mismatches between versions
|
|
12
|
+
parser.setLanguage(Go);
|
|
13
|
+
/**
|
|
14
|
+
* Parse Go source code
|
|
15
|
+
*/
|
|
16
|
+
export function parseSource(source) {
|
|
17
|
+
const tree = parser.parse(source);
|
|
18
|
+
const errors = [];
|
|
19
|
+
// Find error nodes
|
|
20
|
+
const findErrors = (node) => {
|
|
21
|
+
if (node.type === "ERROR" || node.isMissing) {
|
|
22
|
+
errors.push({
|
|
23
|
+
message: node.isMissing ? `Missing: ${node.type}` : "Syntax error",
|
|
24
|
+
line: node.startPosition.row + 1,
|
|
25
|
+
column: node.startPosition.column,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
for (const child of node.children) {
|
|
29
|
+
findErrors(child);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
findErrors(tree.rootNode);
|
|
33
|
+
return {
|
|
34
|
+
tree,
|
|
35
|
+
source,
|
|
36
|
+
hasErrors: errors.length > 0,
|
|
37
|
+
errors,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Parse Go file
|
|
42
|
+
*/
|
|
43
|
+
export async function parseFile(path) {
|
|
44
|
+
const source = await readFile(path, "utf-8");
|
|
45
|
+
return parseSource(source);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get text from a node
|
|
49
|
+
*/
|
|
50
|
+
export function getNodeText(node, source) {
|
|
51
|
+
return source.slice(node.startIndex, node.endIndex);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Extract doc comment from above a declaration
|
|
55
|
+
* Go uses line comments (//) or block comments before declarations
|
|
56
|
+
*/
|
|
57
|
+
export function extractDocComment(node, source) {
|
|
58
|
+
// Look for comment nodes immediately before this node
|
|
59
|
+
const parent = node.parent;
|
|
60
|
+
if (!parent)
|
|
61
|
+
return undefined;
|
|
62
|
+
const nodeIndex = parent.children.indexOf(node);
|
|
63
|
+
if (nodeIndex <= 0)
|
|
64
|
+
return undefined;
|
|
65
|
+
const comments = [];
|
|
66
|
+
// Collect consecutive comment nodes before this declaration
|
|
67
|
+
for (let i = nodeIndex - 1; i >= 0; i--) {
|
|
68
|
+
const sibling = parent.children[i];
|
|
69
|
+
if (sibling.type === "comment") {
|
|
70
|
+
const text = getNodeText(sibling, source);
|
|
71
|
+
// Remove comment markers
|
|
72
|
+
const cleaned = text
|
|
73
|
+
.replace(/^\/\/\s?/, "") // Line comment
|
|
74
|
+
.replace(/^\/\*\s?|\s?\*\/$/g, "") // Block comment
|
|
75
|
+
.trim();
|
|
76
|
+
comments.unshift(cleaned);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return comments.length > 0 ? comments.join("\n") : undefined;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Check if a name is exported (starts with uppercase)
|
|
86
|
+
*/
|
|
87
|
+
export function isExported(name) {
|
|
88
|
+
return (name.length > 0 &&
|
|
89
|
+
name[0] === name[0].toUpperCase() &&
|
|
90
|
+
/[A-Z]/.test(name[0]));
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Parse function parameters
|
|
94
|
+
*/
|
|
95
|
+
export function parseParameters(node, source) {
|
|
96
|
+
const params = [];
|
|
97
|
+
// Look for parameter_list
|
|
98
|
+
const paramList = node.childForFieldName("parameters");
|
|
99
|
+
if (!paramList)
|
|
100
|
+
return params;
|
|
101
|
+
for (const child of paramList.children) {
|
|
102
|
+
if (child.type === "parameter_declaration") {
|
|
103
|
+
// Can have multiple names with same type: a, b int
|
|
104
|
+
const names = [];
|
|
105
|
+
let typeNode = null;
|
|
106
|
+
let isVariadic = false;
|
|
107
|
+
for (const c of child.children) {
|
|
108
|
+
if (c.type === "identifier") {
|
|
109
|
+
names.push(getNodeText(c, source));
|
|
110
|
+
}
|
|
111
|
+
else if (c.type === "variadic_parameter_declaration") {
|
|
112
|
+
isVariadic = true;
|
|
113
|
+
const variadicName = c.children.find((n) => n.type === "identifier");
|
|
114
|
+
if (variadicName) {
|
|
115
|
+
names.push(getNodeText(variadicName, source));
|
|
116
|
+
}
|
|
117
|
+
typeNode =
|
|
118
|
+
c.children.find((n) => n.type !== "identifier" && n.type !== "," && n.type !== "...") ?? null;
|
|
119
|
+
}
|
|
120
|
+
else if (c.type !== "," && c.type !== "(" && c.type !== ")") {
|
|
121
|
+
// This is likely the type
|
|
122
|
+
typeNode = c;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const typeName = typeNode ? getNodeText(typeNode, source) : undefined;
|
|
126
|
+
for (const name of names) {
|
|
127
|
+
params.push({
|
|
128
|
+
name,
|
|
129
|
+
type: typeName,
|
|
130
|
+
isArgs: isVariadic,
|
|
131
|
+
isKwargs: false,
|
|
132
|
+
isPositionalOnly: false,
|
|
133
|
+
isKeywordOnly: false,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else if (child.type === "variadic_parameter_declaration") {
|
|
138
|
+
const nameNode = child.children.find((c) => c.type === "identifier");
|
|
139
|
+
const typeNode = child.children.find((c) => c.type !== "identifier" && c.type !== "...");
|
|
140
|
+
if (nameNode) {
|
|
141
|
+
params.push({
|
|
142
|
+
name: getNodeText(nameNode, source),
|
|
143
|
+
type: typeNode ? getNodeText(typeNode, source) : undefined,
|
|
144
|
+
isArgs: true,
|
|
145
|
+
isKwargs: false,
|
|
146
|
+
isPositionalOnly: false,
|
|
147
|
+
isKeywordOnly: false,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return params;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Parse return types (Go supports multiple return values)
|
|
156
|
+
*/
|
|
157
|
+
export function parseReturnTypes(node, source) {
|
|
158
|
+
const resultNode = node.childForFieldName("result");
|
|
159
|
+
if (!resultNode)
|
|
160
|
+
return undefined;
|
|
161
|
+
return getNodeText(resultNode, source);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Parse a function declaration
|
|
165
|
+
*/
|
|
166
|
+
export function parseFunction(node, source) {
|
|
167
|
+
const nameNode = node.childForFieldName("name");
|
|
168
|
+
const name = nameNode ? getNodeText(nameNode, source) : "";
|
|
169
|
+
return {
|
|
170
|
+
name,
|
|
171
|
+
line: node.startPosition.row + 1,
|
|
172
|
+
endLine: node.endPosition.row + 1,
|
|
173
|
+
column: node.startPosition.column,
|
|
174
|
+
parameters: parseParameters(node, source),
|
|
175
|
+
returnType: parseReturnTypes(node, source),
|
|
176
|
+
decorators: [], // Go doesn't have decorators
|
|
177
|
+
isAsync: false, // Go uses goroutines, not async/await
|
|
178
|
+
isGenerator: false, // Go doesn't have generators
|
|
179
|
+
docstring: extractDocComment(node, source),
|
|
180
|
+
isExported: isExported(name),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Parse a method declaration (function with receiver)
|
|
185
|
+
*/
|
|
186
|
+
export function parseMethod(node, source) {
|
|
187
|
+
const func = parseFunction(node, source);
|
|
188
|
+
// Get receiver info
|
|
189
|
+
const receiverNode = node.childForFieldName("receiver");
|
|
190
|
+
let receiverType;
|
|
191
|
+
let isPointerReceiver = false;
|
|
192
|
+
if (receiverNode) {
|
|
193
|
+
// receiver is parameter_list with one param
|
|
194
|
+
for (const child of receiverNode.children) {
|
|
195
|
+
if (child.type === "parameter_declaration") {
|
|
196
|
+
const typeNode = child.children.find((c) => c.type === "pointer_type" ||
|
|
197
|
+
c.type === "type_identifier" ||
|
|
198
|
+
c.type === "qualified_type");
|
|
199
|
+
if (typeNode) {
|
|
200
|
+
if (typeNode.type === "pointer_type") {
|
|
201
|
+
isPointerReceiver = true;
|
|
202
|
+
const innerType = typeNode.children.find((c) => c.type === "type_identifier");
|
|
203
|
+
receiverType = innerType
|
|
204
|
+
? getNodeText(innerType, source)
|
|
205
|
+
: getNodeText(typeNode, source);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
receiverType = getNodeText(typeNode, source);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
...func,
|
|
216
|
+
isClassMethod: false,
|
|
217
|
+
isStaticMethod: false,
|
|
218
|
+
isProperty: false,
|
|
219
|
+
isAbstract: false,
|
|
220
|
+
receiverType,
|
|
221
|
+
isPointerReceiver,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Parse a type declaration (struct or interface)
|
|
226
|
+
* We treat these as "classes" for compatibility with the tool interface
|
|
227
|
+
*/
|
|
228
|
+
export function parseClass(node, source) {
|
|
229
|
+
// node is type_declaration, which contains type_spec
|
|
230
|
+
const typeSpec = node.children.find((c) => c.type === "type_spec");
|
|
231
|
+
if (!typeSpec) {
|
|
232
|
+
return {
|
|
233
|
+
name: "",
|
|
234
|
+
line: node.startPosition.row + 1,
|
|
235
|
+
endLine: node.endPosition.row + 1,
|
|
236
|
+
column: node.startPosition.column,
|
|
237
|
+
bases: [],
|
|
238
|
+
decorators: [],
|
|
239
|
+
methods: [],
|
|
240
|
+
attributes: [],
|
|
241
|
+
isAbstract: false,
|
|
242
|
+
isDataclass: false,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
const nameNode = typeSpec.childForFieldName("name");
|
|
246
|
+
const name = nameNode ? getNodeText(nameNode, source) : "";
|
|
247
|
+
const typeNode = typeSpec.childForFieldName("type");
|
|
248
|
+
const isInterface = typeNode?.type === "interface_type";
|
|
249
|
+
const isStruct = typeNode?.type === "struct_type";
|
|
250
|
+
const methods = [];
|
|
251
|
+
const attributes = [];
|
|
252
|
+
const bases = []; // embedded types
|
|
253
|
+
if (typeNode && isStruct) {
|
|
254
|
+
// Parse struct fields
|
|
255
|
+
const fieldList = typeNode.children.find((c) => c.type === "field_declaration_list");
|
|
256
|
+
if (fieldList) {
|
|
257
|
+
for (const field of fieldList.children) {
|
|
258
|
+
if (field.type === "field_declaration") {
|
|
259
|
+
const fieldNames = [];
|
|
260
|
+
let fieldType;
|
|
261
|
+
let tag;
|
|
262
|
+
for (const c of field.children) {
|
|
263
|
+
if (c.type === "field_identifier") {
|
|
264
|
+
fieldNames.push(getNodeText(c, source));
|
|
265
|
+
}
|
|
266
|
+
else if (c.type === "raw_string_literal" ||
|
|
267
|
+
c.type === "interpreted_string_literal") {
|
|
268
|
+
tag = getNodeText(c, source);
|
|
269
|
+
}
|
|
270
|
+
else if (c.type !== "," &&
|
|
271
|
+
c.type !== "(" &&
|
|
272
|
+
c.type !== ")" &&
|
|
273
|
+
fieldNames.length > 0) {
|
|
274
|
+
fieldType = getNodeText(c, source);
|
|
275
|
+
}
|
|
276
|
+
else if (c.type === "type_identifier" ||
|
|
277
|
+
c.type === "qualified_type") {
|
|
278
|
+
// Embedded type (anonymous field)
|
|
279
|
+
bases.push(getNodeText(c, source));
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
for (const fieldName of fieldNames) {
|
|
283
|
+
attributes.push({
|
|
284
|
+
name: fieldName,
|
|
285
|
+
type: fieldType,
|
|
286
|
+
line: field.startPosition.row + 1,
|
|
287
|
+
isClassAttribute: true,
|
|
288
|
+
isExported: isExported(fieldName),
|
|
289
|
+
tag,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
else if (typeNode && isInterface) {
|
|
297
|
+
// Parse interface methods
|
|
298
|
+
const methodSpecs = typeNode.children.find((c) => c.type === "method_spec_list" || c.type === "interface_type");
|
|
299
|
+
if (methodSpecs) {
|
|
300
|
+
for (const spec of methodSpecs.children) {
|
|
301
|
+
if (spec.type === "method_spec") {
|
|
302
|
+
const methodName = spec.childForFieldName("name");
|
|
303
|
+
if (methodName) {
|
|
304
|
+
methods.push({
|
|
305
|
+
name: getNodeText(methodName, source),
|
|
306
|
+
line: spec.startPosition.row + 1,
|
|
307
|
+
endLine: spec.endPosition.row + 1,
|
|
308
|
+
column: spec.startPosition.column,
|
|
309
|
+
parameters: [],
|
|
310
|
+
decorators: [],
|
|
311
|
+
isAsync: false,
|
|
312
|
+
isGenerator: false,
|
|
313
|
+
isClassMethod: false,
|
|
314
|
+
isStaticMethod: false,
|
|
315
|
+
isProperty: false,
|
|
316
|
+
isAbstract: true, // Interface methods are abstract
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
else if (spec.type === "type_identifier" ||
|
|
321
|
+
spec.type === "qualified_type") {
|
|
322
|
+
// Embedded interface
|
|
323
|
+
bases.push(getNodeText(spec, source));
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return {
|
|
329
|
+
name,
|
|
330
|
+
line: node.startPosition.row + 1,
|
|
331
|
+
endLine: node.endPosition.row + 1,
|
|
332
|
+
column: node.startPosition.column,
|
|
333
|
+
bases,
|
|
334
|
+
decorators: [],
|
|
335
|
+
methods,
|
|
336
|
+
attributes,
|
|
337
|
+
docstring: extractDocComment(node, source),
|
|
338
|
+
isAbstract: isInterface,
|
|
339
|
+
isDataclass: false,
|
|
340
|
+
isInterface,
|
|
341
|
+
isStruct,
|
|
342
|
+
isExported: isExported(name),
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Parse import declaration
|
|
347
|
+
*/
|
|
348
|
+
export function parseImport(node, source) {
|
|
349
|
+
const imports = [];
|
|
350
|
+
// import "fmt" or import ( "fmt" ... )
|
|
351
|
+
const importSpecs = findNodes(node, (n) => n.type === "import_spec");
|
|
352
|
+
for (const spec of importSpecs) {
|
|
353
|
+
const pathNode = spec.children.find((c) => c.type === "interpreted_string_literal");
|
|
354
|
+
const aliasNode = spec.childForFieldName("name");
|
|
355
|
+
if (pathNode) {
|
|
356
|
+
const path = getNodeText(pathNode, source).replace(/"/g, "");
|
|
357
|
+
const alias = aliasNode ? getNodeText(aliasNode, source) : undefined;
|
|
358
|
+
// Determine import type
|
|
359
|
+
const isBlank = alias === "_";
|
|
360
|
+
const isDot = alias === ".";
|
|
361
|
+
imports.push({
|
|
362
|
+
module: path,
|
|
363
|
+
names: [{ name: path, alias: isBlank || isDot ? undefined : alias }],
|
|
364
|
+
line: spec.startPosition.row + 1,
|
|
365
|
+
isFromImport: false,
|
|
366
|
+
isRelative: false,
|
|
367
|
+
relativeDots: 0,
|
|
368
|
+
isBlankImport: isBlank,
|
|
369
|
+
isDotImport: isDot,
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return imports;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Parse variable/constant declaration
|
|
377
|
+
*/
|
|
378
|
+
export function parseVariable(node, source) {
|
|
379
|
+
const vars = [];
|
|
380
|
+
// Look for var_spec or const_spec
|
|
381
|
+
const specs = findNodes(node, (n) => n.type === "var_spec" || n.type === "const_spec");
|
|
382
|
+
for (const spec of specs) {
|
|
383
|
+
const names = [];
|
|
384
|
+
let typeNode = null;
|
|
385
|
+
let valueNode = null;
|
|
386
|
+
const isConst = spec.type === "const_spec";
|
|
387
|
+
for (const child of spec.children) {
|
|
388
|
+
if (child.type === "identifier") {
|
|
389
|
+
names.push(getNodeText(child, source));
|
|
390
|
+
}
|
|
391
|
+
else if (child.type === "expression_list") {
|
|
392
|
+
valueNode = child;
|
|
393
|
+
}
|
|
394
|
+
else if (child.type !== "," &&
|
|
395
|
+
child.type !== "=" &&
|
|
396
|
+
!names.includes(getNodeText(child, source))) {
|
|
397
|
+
// Likely type
|
|
398
|
+
typeNode = child;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
const typeName = typeNode ? getNodeText(typeNode, source) : undefined;
|
|
402
|
+
const value = valueNode ? getNodeText(valueNode, source) : undefined;
|
|
403
|
+
for (const name of names) {
|
|
404
|
+
vars.push({
|
|
405
|
+
name,
|
|
406
|
+
type: typeName,
|
|
407
|
+
value,
|
|
408
|
+
line: spec.startPosition.row + 1,
|
|
409
|
+
column: spec.startPosition.column,
|
|
410
|
+
isConstant: isConst,
|
|
411
|
+
isExported: isExported(name),
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return vars;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Get package name from source file
|
|
419
|
+
*/
|
|
420
|
+
export function getPackageName(tree, source) {
|
|
421
|
+
const packageClause = tree.rootNode.children.find((c) => c.type === "package_clause");
|
|
422
|
+
if (!packageClause)
|
|
423
|
+
return undefined;
|
|
424
|
+
const nameNode = packageClause.children.find((c) => c.type === "package_identifier");
|
|
425
|
+
return nameNode ? getNodeText(nameNode, source) : undefined;
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Walk the AST and collect all nodes of given types
|
|
429
|
+
*/
|
|
430
|
+
export function* walkTree(node, types) {
|
|
431
|
+
if (!types || types.includes(node.type)) {
|
|
432
|
+
yield node;
|
|
433
|
+
}
|
|
434
|
+
for (const child of node.children) {
|
|
435
|
+
yield* walkTree(child, types);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Find all nodes matching a predicate
|
|
440
|
+
*/
|
|
441
|
+
export function findNodes(node, predicate) {
|
|
442
|
+
const results = [];
|
|
443
|
+
const walk = (n) => {
|
|
444
|
+
if (predicate(n)) {
|
|
445
|
+
results.push(n);
|
|
446
|
+
}
|
|
447
|
+
for (const child of n.children) {
|
|
448
|
+
walk(child);
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
walk(node);
|
|
452
|
+
return results;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Get the containing scope for a node (function or type)
|
|
456
|
+
*/
|
|
457
|
+
export function getContainingScope(node) {
|
|
458
|
+
let current = node.parent;
|
|
459
|
+
while (current) {
|
|
460
|
+
if (current.type === "function_declaration" ||
|
|
461
|
+
current.type === "method_declaration") {
|
|
462
|
+
const nameNode = current.childForFieldName("name");
|
|
463
|
+
return {
|
|
464
|
+
type: "function",
|
|
465
|
+
name: nameNode?.text ?? "",
|
|
466
|
+
node: current,
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
if (current.type === "type_declaration") {
|
|
470
|
+
const typeSpec = current.children.find((c) => c.type === "type_spec");
|
|
471
|
+
const nameNode = typeSpec?.childForFieldName("name");
|
|
472
|
+
return {
|
|
473
|
+
type: "class",
|
|
474
|
+
name: nameNode?.text ?? "",
|
|
475
|
+
node: current,
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
current = current.parent;
|
|
479
|
+
}
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Parse decorators - Go doesn't have decorators, returns empty array
|
|
484
|
+
* This is a compatibility function for tools that expect this export
|
|
485
|
+
*/
|
|
486
|
+
export function parseDecorators(_node, _source) {
|
|
487
|
+
return [];
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Alias for extractDocComment for compatibility with tools expecting Python-style docstring extraction
|
|
491
|
+
*/
|
|
492
|
+
export const extractDocstring = extractDocComment;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Go AST node type definitions for Tree-sitter
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Go AST node types from tree-sitter-go
|
|
6
|
+
*/
|
|
7
|
+
export type GoNodeType = "source_file" | "package_clause" | "import_declaration" | "import_spec" | "import_spec_list" | "function_declaration" | "method_declaration" | "type_declaration" | "type_spec" | "const_declaration" | "var_declaration" | "const_spec" | "var_spec" | "struct_type" | "interface_type" | "map_type" | "slice_type" | "array_type" | "channel_type" | "pointer_type" | "function_type" | "type_identifier" | "qualified_type" | "block" | "expression_statement" | "return_statement" | "if_statement" | "for_statement" | "switch_statement" | "type_switch_statement" | "select_statement" | "defer_statement" | "go_statement" | "assignment_statement" | "short_var_declaration" | "identifier" | "int_literal" | "float_literal" | "imaginary_literal" | "rune_literal" | "interpreted_string_literal" | "raw_string_literal" | "true" | "false" | "nil" | "binary_expression" | "unary_expression" | "call_expression" | "selector_expression" | "index_expression" | "slice_expression" | "type_assertion_expression" | "type_conversion_expression" | "composite_literal" | "func_literal" | "parameter_list" | "parameter_declaration" | "variadic_parameter_declaration" | "field_declaration" | "field_declaration_list" | "method_spec" | "method_spec_list" | "comment" | "blank_identifier";
|
|
8
|
+
/**
|
|
9
|
+
* Decorator information (Go doesn't have decorators, kept for interface compatibility)
|
|
10
|
+
*/
|
|
11
|
+
export interface DecoratorInfo {
|
|
12
|
+
name: string;
|
|
13
|
+
arguments?: string[];
|
|
14
|
+
line: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Parameter information
|
|
18
|
+
*/
|
|
19
|
+
export interface ParameterInfo {
|
|
20
|
+
name: string;
|
|
21
|
+
type?: string;
|
|
22
|
+
default?: string;
|
|
23
|
+
isArgs: boolean;
|
|
24
|
+
isKwargs: boolean;
|
|
25
|
+
isPositionalOnly: boolean;
|
|
26
|
+
isKeywordOnly: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Function/method information
|
|
30
|
+
*/
|
|
31
|
+
export interface FunctionInfo {
|
|
32
|
+
name: string;
|
|
33
|
+
line: number;
|
|
34
|
+
endLine: number;
|
|
35
|
+
column: number;
|
|
36
|
+
parameters: ParameterInfo[];
|
|
37
|
+
returnType?: string;
|
|
38
|
+
decorators: DecoratorInfo[];
|
|
39
|
+
isAsync: boolean;
|
|
40
|
+
isGenerator: boolean;
|
|
41
|
+
docstring?: string;
|
|
42
|
+
body?: string;
|
|
43
|
+
isExported?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Method information (function with receiver)
|
|
47
|
+
*/
|
|
48
|
+
export interface MethodInfo extends FunctionInfo {
|
|
49
|
+
isClassMethod: boolean;
|
|
50
|
+
isStaticMethod: boolean;
|
|
51
|
+
isProperty: boolean;
|
|
52
|
+
isAbstract: boolean;
|
|
53
|
+
receiverType?: string;
|
|
54
|
+
isPointerReceiver?: boolean;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Attribute/field information
|
|
58
|
+
*/
|
|
59
|
+
export interface AttributeInfo {
|
|
60
|
+
name: string;
|
|
61
|
+
type?: string;
|
|
62
|
+
default?: string;
|
|
63
|
+
line: number;
|
|
64
|
+
isClassAttribute: boolean;
|
|
65
|
+
isExported?: boolean;
|
|
66
|
+
tag?: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Type information (struct or interface)
|
|
70
|
+
*/
|
|
71
|
+
export interface ClassInfo {
|
|
72
|
+
name: string;
|
|
73
|
+
line: number;
|
|
74
|
+
endLine: number;
|
|
75
|
+
column: number;
|
|
76
|
+
bases: string[];
|
|
77
|
+
decorators: DecoratorInfo[];
|
|
78
|
+
methods: MethodInfo[];
|
|
79
|
+
attributes: AttributeInfo[];
|
|
80
|
+
docstring?: string;
|
|
81
|
+
isAbstract: boolean;
|
|
82
|
+
isDataclass: boolean;
|
|
83
|
+
isInterface?: boolean;
|
|
84
|
+
isStruct?: boolean;
|
|
85
|
+
isExported?: boolean;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Variable/constant information
|
|
89
|
+
*/
|
|
90
|
+
export interface VariableInfo {
|
|
91
|
+
name: string;
|
|
92
|
+
type?: string;
|
|
93
|
+
value?: string;
|
|
94
|
+
line: number;
|
|
95
|
+
column: number;
|
|
96
|
+
isConstant: boolean;
|
|
97
|
+
isExported?: boolean;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Import information
|
|
101
|
+
*/
|
|
102
|
+
export interface ImportInfo {
|
|
103
|
+
module: string;
|
|
104
|
+
names: Array<{
|
|
105
|
+
name: string;
|
|
106
|
+
alias?: string;
|
|
107
|
+
}>;
|
|
108
|
+
alias?: string;
|
|
109
|
+
line: number;
|
|
110
|
+
isFromImport: boolean;
|
|
111
|
+
isRelative: boolean;
|
|
112
|
+
relativeDots: number;
|
|
113
|
+
isBlankImport?: boolean;
|
|
114
|
+
isDotImport?: boolean;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Position in source code
|
|
118
|
+
*/
|
|
119
|
+
export interface Position {
|
|
120
|
+
line: number;
|
|
121
|
+
column: number;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Range in source code
|
|
125
|
+
*/
|
|
126
|
+
export interface Range {
|
|
127
|
+
start: Position;
|
|
128
|
+
end: Position;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=node-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-types.d.ts","sourceRoot":"","sources":["../../src/parser/node-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"go-best-practices.d.ts","sourceRoot":"","sources":["../../src/skills/go-best-practices.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,eAAO,MAAM,oBAAoB,qCAuE/B,CAAC"}
|