Skip to content

Commit 9d5325f

Browse files
committed
Support _test.gox files by generating _gox_test.go output
Go requires test files to end with _test.go. This maps foo_test.gox → foo_gox_test.go so the test runner picks them up.
1 parent 146aa3c commit 9d5325f

6 files changed

Lines changed: 29 additions & 10 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ cmd/gox/gox
88
# so consumers can `go get` without needing gox installed.
99
# See README.md for details.
1010
*_gox.go
11+
*_gox_test.go
1112
*_gox.go.map
13+
*_gox_test.go.map
1214

1315
# IDE
1416
.idea/

CLAUDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ go build -o /tmp/gox ./cmd/gox
3737

3838
## Code Generation
3939

40-
Generated files use the `_gox.go` suffix (e.g., `app.gox``app_gox.go`).
40+
Generated files use the `_gox.go` suffix (e.g., `app.gox``app_gox.go`). Test files use `_gox_test.go` (e.g., `features_test.gox``features_gox_test.go`).
4141

4242
The generator produces code like:
4343
```go
@@ -69,4 +69,4 @@ The LSP proxies to gopls for Go intelligence. Key behaviors:
6969

7070
Generated files should NOT be committed. They are:
7171
- Created in temp directories during `gox run/build` (overlay mode)
72-
- Gitignored via `*_gox.go` pattern
72+
- Gitignored via `*_gox.go` and `*_gox_test.go` patterns

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,9 @@ Example `.gitignore` for applications:
172172

173173
```gitignore
174174
*_gox.go
175+
*_gox_test.go
175176
*_gox.go.map
177+
*_gox_test.go.map
176178
```
177179

178180
## Typed Props

cmd/gox/main.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -342,10 +342,19 @@ func processFile(inputPath string, cfg *generateConfig) error {
342342
}
343343

344344
// getOutputPath determines the output path for a .gox file.
345+
// Test files get special handling: foo_test.gox → foo_gox_test.go
346+
// so that Go's test runner recognizes them.
345347
func getOutputPath(inputPath, outputDir string) string {
346-
// Replace .gox with _gox.go
347348
baseName := strings.TrimSuffix(filepath.Base(inputPath), ".gox")
348-
outputName := baseName + "_gox.go"
349+
350+
var outputName string
351+
if strings.HasSuffix(baseName, "_test") {
352+
// foo_test.gox → foo_gox_test.go
353+
outputName = strings.TrimSuffix(baseName, "_test") + "_gox_test.go"
354+
} else {
355+
// foo.gox → foo_gox.go
356+
outputName = baseName + "_gox.go"
357+
}
349358

350359
if outputDir != "" {
351360
return filepath.Join(outputDir, outputName)
@@ -602,7 +611,7 @@ func runGoCommand(goCmd string, args []string) error {
602611

603612
// Write generated files to source directories for vet compatibility.
604613
// go vet doesn't read files through the overlay, so the files must exist
605-
// on disk. These are gitignored via *_gox.go and cleaned up after the command.
614+
// on disk. These are gitignored via *_gox.go / *_gox_test.go and cleaned up after the command.
606615
overlayData, err := os.ReadFile(overlayFile.Name())
607616
if err != nil {
608617
return fmt.Errorf("reading overlay: %w", err)
@@ -688,8 +697,8 @@ func remapErrorLine(line string, sourceMaps map[string]*generator.SourceMap) str
688697
colNum, _ := strconv.Atoi(matches[3])
689698
message := matches[4]
690699

691-
// Check if this is a generated _gox.go file
692-
if !strings.HasSuffix(filePath, "_gox.go") {
700+
// Check if this is a generated gox file (_gox.go or _gox_test.go)
701+
if !strings.HasSuffix(filePath, "_gox.go") && !strings.HasSuffix(filePath, "_gox_test.go") {
693702
return line
694703
}
695704

lsp/proxy.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -430,9 +430,13 @@ func (p *Proxy) generateAndCache(uri, text string) string {
430430

431431
// goxToGoPath converts a .gox path to the generated .go path.
432432
// The .go file is placed next to the .gox file for same-package context.
433+
// Test files get special handling: foo_test.gox → foo_gox_test.go
433434
func (p *Proxy) goxToGoPath(goxPath string) string {
434-
// e.g., /path/to/app.gox -> /path/to/app_gox.go
435-
return strings.TrimSuffix(goxPath, ".gox") + "_gox.go"
435+
base := strings.TrimSuffix(goxPath, ".gox")
436+
if strings.HasSuffix(base, "_test") {
437+
return strings.TrimSuffix(base, "_test") + "_gox_test.go"
438+
}
439+
return base + "_gox.go"
436440
}
437441

438442
// rewriteURIs rewrites file URIs in a message.
@@ -447,7 +451,7 @@ func (p *Proxy) rewriteURIs(obj any, toGo bool) {
447451
goxPath := uriToPath(uri)
448452
goPath := p.goxToGoPath(goxPath)
449453
v[key] = pathToURI(goPath)
450-
} else if !toGo && strings.HasSuffix(uri, "_gox.go") {
454+
} else if !toGo && (strings.HasSuffix(uri, "_gox.go") || strings.HasSuffix(uri, "_gox_test.go")) {
451455
// Find original .gox file from source map
452456
goPath := uriToPath(uri)
453457
p.mu.RLock()

lsp/proxy_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ func TestGoxToGoPath(t *testing.T) {
200200
{"/path/to/app.gox", "/path/to/app_gox.go"},
201201
{"/Users/test/component.gox", "/Users/test/component_gox.go"},
202202
{"relative/path.gox", "relative/path_gox.go"},
203+
{"/path/to/features_test.gox", "/path/to/features_gox_test.go"},
204+
{"relative/app_test.gox", "relative/app_gox_test.go"},
203205
}
204206

205207
for _, tt := range tests {

0 commit comments

Comments
 (0)