Skip to content

Commit 45ace52

Browse files
nizosclaude
andcommitted
refactor(go): simplify codebase through systematic cleanup
- Removed unnecessary getter methods in MixedReader (Go anti-pattern) - Made struct fields public for direct access (idiomatic Go) - Extracted complex logic into focused, single-responsibility functions - Reduced nesting throughout codebase using early returns - Fixed potential panic bug with string slicing using strings.HasPrefix() - Removed setter pattern in Transformer for cleaner data flow - Simplified Transform method and reduced complexity - Improved separation of concerns in main process function All tests pass. Code is now more idiomatic Go, easier to maintain, and follows the principle of simplicity over premature abstraction. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent ec806f8 commit 45ace52

File tree

7 files changed

+295
-202
lines changed

7 files changed

+295
-202
lines changed

reporters/go/cmd/tdd-guard-go/main.go

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -24,48 +24,66 @@ func main() {
2424
}
2525

2626
func process(input io.Reader, projectRoot string) error {
27-
// Validate project root if provided
28-
if projectRoot != "" {
29-
if !filepath.IsAbs(projectRoot) {
30-
return errors.New("project root must be an absolute path")
31-
}
32-
33-
// Check if current directory is within project root
34-
cwd, _ := os.Getwd()
35-
if !strings.HasPrefix(cwd, projectRoot) {
36-
return errors.New("current directory must be within project root")
37-
}
27+
if err := validateProjectRoot(projectRoot); err != nil {
28+
return err
3829
}
3930

40-
// Use MixedReader to check for compilation errors
31+
// Parse test output
4132
mixedReader := parser.NewMixedReader(input)
33+
results, p, err := parseTestResults(mixedReader)
34+
if err != nil {
35+
return err
36+
}
4237

43-
p := parser.NewParser()
44-
45-
// Parse JSON lines
46-
jsonInput := strings.Join(mixedReader.GetJSONLines(), "\n")
47-
if jsonInput != "" {
48-
err := p.Parse(strings.NewReader(jsonInput))
49-
if err != nil {
50-
return err
51-
}
38+
// Add synthetic test for compilation errors
39+
if shouldAddCompilationError(results, mixedReader.CompilationError) {
40+
addCompilationError(results, mixedReader.CompilationError)
5241
}
5342

54-
// Only add syntthetic test if compilation error detected
55-
results := p.GetResults()
43+
// Transform and save results
5644
t := transformer.NewTransformer()
45+
result := t.Transform(results, p, mixedReader.CompilationError)
5746

58-
if len(results) == 0 && mixedReader.HasCompilationError() {
59-
pkg := mixedReader.GetCompilationErrorPackage()
60-
results[pkg] = parser.PackageResults{
61-
"CompilationError": parser.StateFailed,
47+
s := storage.NewStorage(projectRoot)
48+
return s.Save(result)
49+
}
50+
51+
func validateProjectRoot(projectRoot string) error {
52+
if projectRoot == "" {
53+
return nil
54+
}
55+
56+
if !filepath.IsAbs(projectRoot) {
57+
return errors.New("project root must be an absolute path")
58+
}
59+
60+
cwd, _ := os.Getwd()
61+
if !strings.HasPrefix(cwd, projectRoot) {
62+
return errors.New("current directory must be within project root")
63+
}
64+
65+
return nil
66+
}
67+
68+
func parseTestResults(mixedReader *parser.MixedReader) (parser.Results, *parser.Parser, error) {
69+
p := parser.NewParser()
70+
71+
jsonInput := strings.Join(mixedReader.JSONLines, "\n")
72+
if jsonInput != "" {
73+
if err := p.Parse(strings.NewReader(jsonInput)); err != nil {
74+
return nil, nil, err
6275
}
63-
// Pass error message to transformer
64-
t.SetCompilationErrorMessage(mixedReader.GetCompilationErrorMessage())
6576
}
6677

67-
result := t.Transform(results, p)
78+
return p.GetResults(), p, nil
79+
}
6880

69-
s := storage.NewStorage(projectRoot)
70-
return s.Save(result)
81+
func shouldAddCompilationError(results parser.Results, compilationError *parser.CompilationError) bool {
82+
return len(results) == 0 && compilationError != nil
83+
}
84+
85+
func addCompilationError(results parser.Results, compilationError *parser.CompilationError) {
86+
results[compilationError.Package] = parser.PackageResults{
87+
"CompilationError": parser.StateFailed,
88+
}
7189
}

reporters/go/cmd/tdd-guard-go/main_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ func TestProcess(t *testing.T) {
9999
outputPath := getTestFilePath(tempDir)
100100
data, _ := os.ReadFile(outputPath)
101101

102-
103102
if bytes.Contains(data, []byte(`"testModules":[]`)) {
104103
t.Fatalf("Expected non-empty testModules, got: %s", data)
105104
}

reporters/go/internal/parser/mixed_reader.go

Lines changed: 57 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,73 +4,90 @@ import (
44
"bufio"
55
"encoding/json"
66
"io"
7+
"strings"
78
)
89

910
// MixedReader handles both JSON and plain text input from go test
1011
type MixedReader struct {
11-
jsonLines []string
12-
nonJSONLines []string
13-
hasCompilationErr bool
14-
errorPackage string
15-
errorMessage string
12+
JSONLines []string
13+
NonJSONLines []string
14+
CompilationError *CompilationError
15+
}
16+
17+
// CompilationError represents a compilation error if one occurred
18+
type CompilationError struct {
19+
Package string
20+
Message string
1621
}
1722

1823
// NewMixedReader creates a new MixedReader and processes the input
1924
func NewMixedReader(reader io.Reader) *MixedReader {
2025
mr := &MixedReader{}
2126
scanner := bufio.NewScanner(reader)
2227
foundErrorHeader := false
28+
var errorPkg string
2329

2430
for scanner.Scan() {
2531
line := scanner.Text()
2632

2733
// Try to parse as JSON
28-
var event TestEvent
29-
if err := json.Unmarshal([]byte(line), &event); err == nil {
30-
// It's valid JSON
31-
mr.jsonLines = append(mr.jsonLines, line)
32-
} else {
33-
// It's not JSON
34-
mr.nonJSONLines = append(mr.nonJSONLines, line)
35-
36-
// Check for compilation error pattern
37-
if len(line) > 0 && line[0] == '#' {
38-
mr.hasCompilationErr = true
39-
foundErrorHeader = true
40-
// Extract package name (everything after "# ")
41-
if len(line) > 2 {
42-
mr.errorPackage = line[2:]
43-
}
44-
} else if foundErrorHeader && mr.errorMessage == "" && line != "" && line[:4] != "FAIL" {
45-
// The next non-empty line after # is the error message
46-
mr.errorMessage = line
47-
}
34+
if isJSON(line) {
35+
mr.JSONLines = append(mr.JSONLines, line)
36+
continue
37+
}
38+
39+
// Not JSON - store it
40+
mr.NonJSONLines = append(mr.NonJSONLines, line)
41+
42+
// Check for compilation error pattern
43+
if isErrorHeader(line) {
44+
foundErrorHeader = true
45+
errorPkg = extractPackageName(line)
46+
continue
47+
}
48+
49+
// Capture error message (first non-FAIL line after header)
50+
if foundErrorHeader && mr.CompilationError == nil && isErrorMessage(line) {
51+
mr.CompilationError = newCompilationError(errorPkg, line)
4852
}
4953
}
54+
55+
// If we found error header but no error message, still create CompilationError
56+
if foundErrorHeader && mr.CompilationError == nil {
57+
mr.CompilationError = newCompilationError(errorPkg, "")
58+
}
59+
5060
return mr
5161
}
5262

53-
// GetJSONLines returns the collected JSON lines
54-
func (mr *MixedReader) GetJSONLines() []string {
55-
return mr.jsonLines
63+
// isJSON checks if a line is valid JSON
64+
func isJSON(line string) bool {
65+
var event TestEvent
66+
return json.Unmarshal([]byte(line), &event) == nil
5667
}
5768

58-
// GetNonJSONLines returns the collected non-JSON lines
59-
func (mr *MixedReader) GetNonJSONLines() []string {
60-
return mr.nonJSONLines
69+
// isErrorHeader checks if line starts with # (compilation error header)
70+
func isErrorHeader(line string) bool {
71+
return len(line) > 0 && line[0] == '#'
6172
}
6273

63-
// HasCompilationError checks if compilation error was detected
64-
func (mr *MixedReader) HasCompilationError() bool {
65-
return mr.hasCompilationErr
74+
// extractPackageName extracts package name from error header line
75+
func extractPackageName(line string) string {
76+
if len(line) > 2 {
77+
return line[2:] // Everything after "# "
78+
}
79+
return ""
6680
}
6781

68-
// GetCompilationErrorPackage returns the package name from compilation error
69-
func (mr *MixedReader) GetCompilationErrorPackage() string {
70-
return mr.errorPackage
82+
// isErrorMessage checks if line is a valid error message
83+
func isErrorMessage(line string) bool {
84+
return line != "" && !strings.HasPrefix(line, "FAIL")
7185
}
7286

73-
// GetCompilationErrorMessage returns the compilation error message
74-
func (mr *MixedReader) GetCompilationErrorMessage() string {
75-
return mr.errorMessage
87+
// newCompilationError creates a new CompilationError
88+
func newCompilationError(pkg, msg string) *CompilationError {
89+
return &CompilationError{
90+
Package: pkg,
91+
Message: msg,
92+
}
7693
}

0 commit comments

Comments
 (0)