Skip to content

Commit 73f168a

Browse files
committed
feat(core): Go scanner - edge cases and documentation
Complete Go scanner integration with: Edge Cases: - init functions (multiple allowed) - Embedded structs - Multiple const/var declarations - Variadic functions - Named return values - Context parameters - Unexported types and functions Documentation: - Updated README with Go scanner section - Added Go input/output examples - Updated supported languages table - Updated roadmap with Go completion Tests: - 12 new edge case tests - 51 total Go tests, 1564 total tests passing - Coverage: 93.51% statements, 100% functions Closes #131
1 parent c1288d2 commit 73f168a

3 files changed

Lines changed: 386 additions & 2 deletions

File tree

packages/core/src/scanner/README.md

Lines changed: 140 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,142 @@ import { MyClass } from './lib';
230230
]
231231
```
232232

233+
### Example 3: Scanning Go Files
234+
235+
**Input:** `server/handler.go`
236+
```go
237+
package server
238+
239+
// Handler processes incoming requests.
240+
type Handler struct {
241+
name string
242+
}
243+
244+
// NewHandler creates a new Handler instance.
245+
func NewHandler(name string) *Handler {
246+
return &Handler{name: name}
247+
}
248+
249+
// Process handles a request and returns a response.
250+
func (h *Handler) Process(req Request) (Response, error) {
251+
// processing logic
252+
return Response{}, nil
253+
}
254+
255+
// Stack is a generic stack data structure.
256+
type Stack[T any] struct {
257+
items []T
258+
}
259+
260+
// Push adds an item to the stack.
261+
func (s *Stack[T]) Push(item T) {
262+
s.items = append(s.items, item)
263+
}
264+
```
265+
266+
**Output:**
267+
```json
268+
[
269+
{
270+
"id": "server/handler.go:Handler:4",
271+
"text": "struct Handler\ntype Handler struct\nHandler processes incoming requests.",
272+
"type": "class",
273+
"language": "go",
274+
"metadata": {
275+
"file": "server/handler.go",
276+
"startLine": 4,
277+
"endLine": 6,
278+
"name": "Handler",
279+
"signature": "type Handler struct",
280+
"exported": true,
281+
"docstring": "Handler processes incoming requests."
282+
}
283+
},
284+
{
285+
"id": "server/handler.go:NewHandler:9",
286+
"text": "function NewHandler\nfunc NewHandler(name string) *Handler\nNewHandler creates a new Handler instance.",
287+
"type": "function",
288+
"language": "go",
289+
"metadata": {
290+
"file": "server/handler.go",
291+
"startLine": 9,
292+
"endLine": 11,
293+
"name": "NewHandler",
294+
"signature": "func NewHandler(name string) *Handler",
295+
"exported": true,
296+
"docstring": "NewHandler creates a new Handler instance."
297+
}
298+
},
299+
{
300+
"id": "server/handler.go:Handler.Process:14",
301+
"text": "method Handler.Process\nfunc (h *Handler) Process(req Request) (Response, error)\nProcess handles a request and returns a response.",
302+
"type": "method",
303+
"language": "go",
304+
"metadata": {
305+
"file": "server/handler.go",
306+
"startLine": 14,
307+
"endLine": 17,
308+
"name": "Handler.Process",
309+
"signature": "func (h *Handler) Process(req Request) (Response, error)",
310+
"exported": true,
311+
"docstring": "Process handles a request and returns a response.",
312+
"custom": {
313+
"receiver": "Handler",
314+
"receiverPointer": true
315+
}
316+
}
317+
},
318+
{
319+
"id": "server/handler.go:Stack:20",
320+
"text": "struct Stack\ntype Stack[T any] struct\nStack is a generic stack data structure.",
321+
"type": "class",
322+
"language": "go",
323+
"metadata": {
324+
"file": "server/handler.go",
325+
"startLine": 20,
326+
"endLine": 22,
327+
"name": "Stack",
328+
"signature": "type Stack[T any] struct",
329+
"exported": true,
330+
"docstring": "Stack is a generic stack data structure.",
331+
"custom": {
332+
"isGeneric": true,
333+
"typeParameters": ["T any"]
334+
}
335+
}
336+
},
337+
{
338+
"id": "server/handler.go:Stack.Push:25",
339+
"text": "method Stack.Push\nfunc (s *Stack[T]) Push(item T)\nPush adds an item to the stack.",
340+
"type": "method",
341+
"language": "go",
342+
"metadata": {
343+
"file": "server/handler.go",
344+
"startLine": 25,
345+
"endLine": 27,
346+
"name": "Stack.Push",
347+
"signature": "func (s *Stack[T]) Push(item T)",
348+
"exported": true,
349+
"docstring": "Push adds an item to the stack.",
350+
"custom": {
351+
"receiver": "Stack",
352+
"receiverPointer": true,
353+
"isGeneric": true
354+
}
355+
}
356+
}
357+
]
358+
```
359+
360+
**Go Scanner Features:**
361+
- Functions, methods, structs, interfaces, type aliases
362+
- Doc comments (Go-style `//` comments preceding declarations)
363+
- Receiver method extraction with pointer/value distinction
364+
- Go generics (Go 1.18+) with type parameter tracking
365+
- Exported/unexported detection (capitalization)
366+
- Generated file skipping (`// Code generated` header)
367+
- Test file detection (`*_test.go``isTest: true`)
368+
233369
### Example 3: Full Repository Scan
234370

235371
```typescript
@@ -374,7 +510,7 @@ const utilDocs = result.documents.filter(
374510
| TypeScript | `TypeScriptScanner` | Functions, classes, methods, interfaces, types, arrow functions, exported constants, JSDoc | ✅ Implemented |
375511
| JavaScript | `TypeScriptScanner` | Functions, classes, methods, arrow functions, exported constants, JSDoc | ✅ Implemented (via .ts scanner) |
376512
| Markdown | `MarkdownScanner` | Documentation sections, code blocks | ✅ Implemented |
377-
| Go | - | Functions, structs, interfaces | 🔄 Planned (tree-sitter) |
513+
| Go | `GoScanner` | Functions, methods, structs, interfaces, types, constants, generics, doc comments | ✅ Implemented (tree-sitter) |
378514
| Python | - | Functions, classes, docstrings | 🔄 Planned (tree-sitter) |
379515
| Rust | - | Functions, structs, traits | 🔄 Planned (tree-sitter) |
380516

@@ -490,7 +626,9 @@ registry.register(new GoScanner());
490626
- [x] TypeScript scanner with ts-morph
491627
- [x] Markdown scanner with remark
492628
- [x] Scanner registry and auto-detection
493-
- [ ] Tree-sitter integration for Go, Python, Rust
629+
- [x] Go scanner with tree-sitter (functions, methods, structs, interfaces, generics)
630+
- [ ] Python scanner with tree-sitter
631+
- [ ] Rust scanner with tree-sitter
494632
- [ ] Enhanced JavaScript support (JSX, Flow)
495633
- [ ] Configuration file support
496634
- [ ] Incremental scanning (hash-based)
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
//go:build linux && amd64
2+
// +build linux,amd64
3+
4+
// Package edgecases tests various Go edge cases for the scanner.
5+
package edgecases
6+
7+
import (
8+
"context"
9+
"io"
10+
)
11+
12+
// init functions should be extracted
13+
func init() {
14+
// Package initialization
15+
}
16+
17+
// Multiple init functions are allowed
18+
func init() {
19+
// Another init
20+
}
21+
22+
// Blank identifier for interface compliance check
23+
var _ io.Reader = (*MyReader)(nil)
24+
var _ io.Writer = (*MyWriter)(nil)
25+
26+
// MyReader implements io.Reader.
27+
type MyReader struct {
28+
data []byte
29+
}
30+
31+
// Read implements io.Reader.
32+
func (r *MyReader) Read(p []byte) (n int, err error) {
33+
return copy(p, r.data), nil
34+
}
35+
36+
// MyWriter implements io.Writer.
37+
type MyWriter struct{}
38+
39+
// Write implements io.Writer.
40+
func (w *MyWriter) Write(p []byte) (n int, err error) {
41+
return len(p), nil
42+
}
43+
44+
// Embedded struct example
45+
type Base struct {
46+
ID string
47+
Name string
48+
}
49+
50+
// Extended embeds Base.
51+
type Extended struct {
52+
Base // Embedded
53+
ExtraField int // Additional field
54+
}
55+
56+
// Multiple variable declarations
57+
var (
58+
DefaultTimeout = 30
59+
MaxRetries = 3
60+
MinWorkers = 1
61+
)
62+
63+
// Multiple const declarations
64+
const (
65+
StatusPending = "pending"
66+
StatusRunning = "running"
67+
StatusComplete = "complete"
68+
)
69+
70+
// Iota usage
71+
const (
72+
Sunday = iota
73+
Monday
74+
Tuesday
75+
Wednesday
76+
Thursday
77+
Friday
78+
Saturday
79+
)
80+
81+
// Function with context (common pattern)
82+
func DoWork(ctx context.Context) error {
83+
select {
84+
case <-ctx.Done():
85+
return ctx.Err()
86+
default:
87+
return nil
88+
}
89+
}
90+
91+
// Variadic function
92+
func Sum(numbers ...int) int {
93+
total := 0
94+
for _, n := range numbers {
95+
total += n
96+
}
97+
return total
98+
}
99+
100+
// Function returning multiple values
101+
func Divide(a, b int) (int, int, error) {
102+
if b == 0 {
103+
return 0, 0, io.EOF // Using io.EOF as placeholder error
104+
}
105+
return a / b, a % b, nil
106+
}
107+
108+
// Named return values
109+
func ParseConfig(data []byte) (config *Base, err error) {
110+
config = &Base{}
111+
// parsing logic
112+
return config, nil
113+
}
114+
115+
// unexportedType should still be detected
116+
type unexportedType struct {
117+
field string
118+
}
119+
120+
// unexportedFunc should still be detected
121+
func unexportedFunc() string {
122+
return "unexported"
123+
}

0 commit comments

Comments
 (0)