Skip to content

Commit fd56154

Browse files
Copilotneongreen
andcommitted
Add lion: documentation extraction tool for Go code
Co-authored-by: neongreen <[email protected]>
1 parent c7d2645 commit fd56154

2 files changed

Lines changed: 90 additions & 89 deletions

File tree

lion/internal/extractor/extractor.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ func getEntityName(decl *ast.GenDecl) string {
101101
return ""
102102
}
103103

104-
/*lion:implementation
104+
/*
105+
lion:implementation
105106
extractFromCommentGroup processes a comment group and extracts lion comments.
106107
107108
It supports three formats:
@@ -134,7 +135,7 @@ func extractFromCommentGroup(fset *token.FileSet, cg *ast.CommentGroup, filepath
134135
}
135136
}
136137
}
137-
138+
138139
// Only use marker-at-end if there are regular comments before the marker
139140
if hasOnlyRegularComments {
140141
// Extract topic from the last line
@@ -152,12 +153,12 @@ func extractFromCommentGroup(fset *token.FileSet, cg *ast.CommentGroup, filepath
152153
}
153154
}
154155
}
155-
156+
156157
// Add marker content if provided
157158
if markerContent != "" {
158159
contentLines = append(contentLines, markerContent)
159160
}
160-
161+
161162
if len(contentLines) > 0 {
162163
pos := fset.Position(cg.List[0].Pos())
163164
entry := DocEntry{
@@ -175,7 +176,7 @@ func extractFromCommentGroup(fset *token.FileSet, cg *ast.CommentGroup, filepath
175176
}
176177
}
177178
}
178-
179+
179180
// Otherwise, process comments individually (legacy behavior)
180181
topicGroups := make(map[string][]string)
181182
topicOrder := []string{}

lion/internal/extractor/extractor_test.go

Lines changed: 84 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -359,10 +359,10 @@ type Config struct {
359359
}
360360

361361
func TestExtractMarkerAtEnd(t *testing.T) {
362-
tmpDir := t.TempDir()
362+
tmpDir := t.TempDir()
363363

364-
// Create test Go file with marker-at-end format
365-
testFile := filepath.Join(tmpDir, "test.go")
364+
// Create test Go file with marker-at-end format
365+
testFile := filepath.Join(tmpDir, "test.go")
366366
content := `// This is a multi-line comment.
367367
// It describes the functionality.
368368
// The lion marker is at the end.
@@ -386,74 +386,74 @@ return &Config{Port: 8080}
386386
}
387387
`
388388

389-
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
390-
t.Fatalf("failed to create test file: %v", err)
391-
}
389+
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
390+
t.Fatalf("failed to create test file: %v", err)
391+
}
392392

393-
// Extract documentation
394-
docs, err := Extract(tmpDir)
395-
if err != nil {
396-
t.Fatalf("Extract failed: %v", err)
397-
}
393+
// Extract documentation
394+
docs, err := Extract(tmpDir)
395+
if err != nil {
396+
t.Fatalf("Extract failed: %v", err)
397+
}
398398

399-
// Verify topics
400-
if len(docs) != 2 {
401-
t.Errorf("expected 2 topics, got %d", len(docs))
402-
}
399+
// Verify topics
400+
if len(docs) != 2 {
401+
t.Errorf("expected 2 topics, got %d", len(docs))
402+
}
403403

404-
// Verify overview content
405-
overviewEntries := docs["overview"]
406-
if len(overviewEntries) != 1 {
407-
t.Errorf("expected 1 overview entry, got %d", len(overviewEntries))
408-
}
409-
if len(overviewEntries) > 0 {
410-
content := overviewEntries[0].Content
411-
if !strings.Contains(content, "multi-line comment") {
412-
t.Errorf("overview content missing expected text, got: %q", content)
413-
}
414-
if !strings.Contains(content, "lion marker is at the end") {
415-
t.Errorf("overview content missing expected text, got: %q", content)
416-
}
417-
// Should NOT contain the lion marker itself
418-
if strings.Contains(content, "lion:overview") {
419-
t.Errorf("overview content should not contain lion marker, got: %q", content)
420-
}
421-
}
404+
// Verify overview content
405+
overviewEntries := docs["overview"]
406+
if len(overviewEntries) != 1 {
407+
t.Errorf("expected 1 overview entry, got %d", len(overviewEntries))
408+
}
409+
if len(overviewEntries) > 0 {
410+
content := overviewEntries[0].Content
411+
if !strings.Contains(content, "multi-line comment") {
412+
t.Errorf("overview content missing expected text, got: %q", content)
413+
}
414+
if !strings.Contains(content, "lion marker is at the end") {
415+
t.Errorf("overview content missing expected text, got: %q", content)
416+
}
417+
// Should NOT contain the lion marker itself
418+
if strings.Contains(content, "lion:overview") {
419+
t.Errorf("overview content should not contain lion marker, got: %q", content)
420+
}
421+
}
422422

423-
// Verify api content (should have 2 entries)
424-
apiEntries := docs["api"]
425-
if len(apiEntries) != 2 {
426-
t.Errorf("expected 2 api entries, got %d", len(apiEntries))
427-
}
423+
// Verify api content (should have 2 entries)
424+
apiEntries := docs["api"]
425+
if len(apiEntries) != 2 {
426+
t.Errorf("expected 2 api entries, got %d", len(apiEntries))
427+
}
428428

429-
// First api entry (Config struct)
430-
if len(apiEntries) > 0 {
431-
content := apiEntries[0].Content
432-
if !strings.Contains(content, "Config struct holds settings") {
433-
t.Errorf("api content missing expected text, got: %q", content)
434-
}
435-
if !strings.Contains(content, "marker-at-end format") {
436-
t.Errorf("api content missing expected text, got: %q", content)
437-
}
438-
}
429+
// First api entry (Config struct)
430+
if len(apiEntries) > 0 {
431+
content := apiEntries[0].Content
432+
if !strings.Contains(content, "Config struct holds settings") {
433+
t.Errorf("api content missing expected text, got: %q", content)
434+
}
435+
if !strings.Contains(content, "marker-at-end format") {
436+
t.Errorf("api content missing expected text, got: %q", content)
437+
}
438+
}
439439

440-
// Second api entry (Initialize function) - should include marker line content
441-
if len(apiEntries) > 1 {
442-
content := apiEntries[1].Content
443-
if !strings.Contains(content, "Initialize creates a new instance") {
444-
t.Errorf("api content missing expected text, got: %q", content)
445-
}
446-
if !strings.Contains(content, "Additional info can go on the marker line") {
447-
t.Errorf("api content should include marker line content, got: %q", content)
448-
}
449-
}
440+
// Second api entry (Initialize function) - should include marker line content
441+
if len(apiEntries) > 1 {
442+
content := apiEntries[1].Content
443+
if !strings.Contains(content, "Initialize creates a new instance") {
444+
t.Errorf("api content missing expected text, got: %q", content)
445+
}
446+
if !strings.Contains(content, "Additional info can go on the marker line") {
447+
t.Errorf("api content should include marker line content, got: %q", content)
448+
}
449+
}
450450
}
451451

452452
func TestMixedCommentFormats(t *testing.T) {
453-
tmpDir := t.TempDir()
453+
tmpDir := t.TempDir()
454454

455-
// Test file that mixes all three formats
456-
testFile := filepath.Join(tmpDir, "test.go")
455+
// Test file that mixes all three formats
456+
testFile := filepath.Join(tmpDir, "test.go")
457457
content := `// Format 1: Marker at end
458458
// This uses the cleanest syntax.
459459
//lion:format1
@@ -474,32 +474,32 @@ func format3example() {}
474474
func example() {}
475475
`
476476

477-
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
478-
t.Fatalf("failed to create test file: %v", err)
479-
}
477+
if err := os.WriteFile(testFile, []byte(content), 0644); err != nil {
478+
t.Fatalf("failed to create test file: %v", err)
479+
}
480480

481-
docs, err := Extract(tmpDir)
482-
if err != nil {
483-
t.Fatalf("Extract failed: %v", err)
484-
}
481+
docs, err := Extract(tmpDir)
482+
if err != nil {
483+
t.Fatalf("Extract failed: %v", err)
484+
}
485485

486-
// Should have 3 topics
487-
if len(docs) != 3 {
488-
t.Errorf("expected 3 topics, got %d", len(docs))
489-
}
486+
// Should have 3 topics
487+
if len(docs) != 3 {
488+
t.Errorf("expected 3 topics, got %d", len(docs))
489+
}
490490

491-
// Verify format1 has 2 entries
492-
if len(docs["format1"]) != 2 {
493-
t.Errorf("expected 2 format1 entries, got %d", len(docs["format1"]))
494-
}
491+
// Verify format1 has 2 entries
492+
if len(docs["format1"]) != 2 {
493+
t.Errorf("expected 2 format1 entries, got %d", len(docs["format1"]))
494+
}
495495

496-
// Verify format2 has 1 entry
497-
if len(docs["format2"]) != 1 {
498-
t.Errorf("expected 1 format2 entry, got %d", len(docs["format2"]))
499-
}
496+
// Verify format2 has 1 entry
497+
if len(docs["format2"]) != 1 {
498+
t.Errorf("expected 1 format2 entry, got %d", len(docs["format2"]))
499+
}
500500

501-
// Verify format3 has 1 entry
502-
if len(docs["format3"]) != 1 {
503-
t.Errorf("expected 1 format3 entry, got %d", len(docs["format3"]))
504-
}
501+
// Verify format3 has 1 entry
502+
if len(docs["format3"]) != 1 {
503+
t.Errorf("expected 1 format3 entry, got %d", len(docs["format3"]))
504+
}
505505
}

0 commit comments

Comments
 (0)