[agent/codex:gpt-5.4-mini] Update the code against the AX (Agent Experience) design pri... #4
2 changed files with 72 additions and 11 deletions
|
|
@ -59,6 +59,7 @@ type DocblockResult struct {
|
|||
Total int `json:"total"`
|
||||
Documented int `json:"documented"`
|
||||
Missing []MissingDocblock `json:"missing,omitempty"`
|
||||
Warnings []DocblockWarning `json:"warnings,omitempty"`
|
||||
Passed bool `json:"passed"`
|
||||
}
|
||||
|
||||
|
|
@ -71,6 +72,13 @@ type MissingDocblock struct {
|
|||
Reason string `json:"reason,omitempty"`
|
||||
}
|
||||
|
||||
// DocblockWarning captures a partial parse failure while still preserving
|
||||
// the successfully parsed files in the same directory.
|
||||
type DocblockWarning struct {
|
||||
Path string `json:"path"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// RunDocblockCheck checks docblock coverage for the given packages.
|
||||
func RunDocblockCheck(paths []string, threshold float64, verbose, jsonOutput bool) error {
|
||||
result, err := CheckDocblockCoverage(paths)
|
||||
|
|
@ -92,14 +100,6 @@ func RunDocblockCheck(paths []string, threshold float64, verbose, jsonOutput boo
|
|||
return nil
|
||||
}
|
||||
|
||||
// Sort missing by file then line
|
||||
slices.SortFunc(result.Missing, func(a, b MissingDocblock) int {
|
||||
return cmp.Or(
|
||||
cmp.Compare(a.File, b.File),
|
||||
cmp.Compare(a.Line, b.Line),
|
||||
)
|
||||
})
|
||||
|
||||
// Print result
|
||||
if verbose && len(result.Missing) > 0 {
|
||||
cli.Print("%s\n\n", i18n.T("cmd.qa.docblock.missing_docs"))
|
||||
|
|
@ -114,6 +114,13 @@ func RunDocblockCheck(paths []string, threshold float64, verbose, jsonOutput boo
|
|||
cli.Blank()
|
||||
}
|
||||
|
||||
if len(result.Warnings) > 0 {
|
||||
for _, warning := range result.Warnings {
|
||||
cli.Warnf("failed to parse %s: %s", warning.Path, warning.Error)
|
||||
}
|
||||
cli.Blank()
|
||||
}
|
||||
|
||||
// Summary
|
||||
coverageStr := fmt.Sprintf("%.1f%%", result.Coverage)
|
||||
thresholdStr := fmt.Sprintf("%.1f%%", threshold)
|
||||
|
|
@ -167,9 +174,12 @@ func CheckDocblockCoverage(patterns []string) (*DocblockResult, error) {
|
|||
return !strings.HasSuffix(fi.Name(), "_test.go")
|
||||
}, parser.ParseComments)
|
||||
if err != nil {
|
||||
// Log parse errors but continue to check other directories
|
||||
cli.Warnf("failed to parse %s: %v", dir, err)
|
||||
continue
|
||||
// Preserve partial results when a directory contains both valid and
|
||||
// invalid files. The caller decides how to present the warning.
|
||||
result.Warnings = append(result.Warnings, DocblockWarning{
|
||||
Path: dir,
|
||||
Error: err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
for _, pkg := range pkgs {
|
||||
|
|
@ -183,6 +193,21 @@ func CheckDocblockCoverage(patterns []string) (*DocblockResult, error) {
|
|||
result.Coverage = float64(result.Documented) / float64(result.Total) * 100
|
||||
}
|
||||
|
||||
slices.SortFunc(result.Missing, func(a, b MissingDocblock) int {
|
||||
return cmp.Or(
|
||||
cmp.Compare(a.File, b.File),
|
||||
cmp.Compare(a.Line, b.Line),
|
||||
cmp.Compare(a.Kind, b.Kind),
|
||||
cmp.Compare(a.Name, b.Name),
|
||||
)
|
||||
})
|
||||
slices.SortFunc(result.Warnings, func(a, b DocblockWarning) int {
|
||||
return cmp.Or(
|
||||
cmp.Compare(a.Path, b.Path),
|
||||
cmp.Compare(a.Error, b.Error),
|
||||
)
|
||||
})
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
36
cmd/qa/cmd_docblock_test.go
Normal file
36
cmd/qa/cmd_docblock_test.go
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
package qa
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRunDocblockCheckJSONOutput_IsDeterministicAndKeepsWarnings(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
writeTestFile(t, filepath.Join(dir, "b.go"), "package sample\n\nfunc Beta() {}\n")
|
||||
writeTestFile(t, filepath.Join(dir, "a.go"), "package sample\n\nfunc Alpha() {}\n")
|
||||
writeTestFile(t, filepath.Join(dir, "broken.go"), "package sample\n\nfunc Broken(\n")
|
||||
|
||||
restoreWorkingDir(t, dir)
|
||||
|
||||
var result DocblockResult
|
||||
output := captureStdout(t, func() {
|
||||
err := RunDocblockCheck([]string{"."}, 100, false, true)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
require.NoError(t, json.Unmarshal([]byte(output), &result))
|
||||
assert.False(t, result.Passed)
|
||||
assert.Equal(t, 2, result.Total)
|
||||
assert.Equal(t, 0, result.Documented)
|
||||
require.Len(t, result.Missing, 2)
|
||||
assert.Equal(t, "a.go", result.Missing[0].File)
|
||||
assert.Equal(t, "b.go", result.Missing[1].File)
|
||||
require.Len(t, result.Warnings, 1)
|
||||
assert.Equal(t, ".", result.Warnings[0].Path)
|
||||
assert.NotEmpty(t, result.Warnings[0].Error)
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue