项目文件夹

文件
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

101 行
3.7 KiB
Go

package lsp
import (
"encoding/json"
"os"
"path/filepath"
"sync/atomic"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/zzet/gortex/internal/graph"
"github.com/zzet/gortex/internal/graph/store_sqlite"
"github.com/zzet/gortex/internal/semantic"
)
// TestLSP_Provider_SkipsAlreadyStampedNodes_LightScan mirrors
// TestLSP_Provider_SkipsAlreadyStampedNodes but backs the graph with a real
// sqlite Store, which implements graph.LightNodeReader — exercising the
// repoScopedNodesLight branch the in-memory-graph test never reaches. The
// critical extra assertion: a non-promoted meta key present on the fresh
// node before enrichment must survive the light-scan → candidate refetch
// (GetNodesByIDs) → hover-stamp → AddBatch round trip. Losing it would mean
// the light scan's stripped-down Meta got persisted back in place of the
// full one — silently discarding whatever else the graph had recorded for
// that node.
func TestLSP_Provider_SkipsAlreadyStampedNodes_LightScan(t *testing.T) {
t.Setenv("GORTEX_LSP_SWEEP", "full")
repoRoot := t.TempDir()
require.NoError(t, os.WriteFile(
filepath.Join(repoRoot, "main.go"),
[]byte("package main\n\nfunc F() string { return \"hi\" }\n\nfunc G() int { return 0 }\n"),
0o644,
))
var hoverCalls atomic.Int64
server := newFakeLSPServer()
server.handle("textDocument/hover", func(params json.RawMessage) (any, *jsonRPCError) {
hoverCalls.Add(1)
return map[string]any{
"contents": map[string]any{"kind": "plaintext", "value": "func G() int"},
}, nil
})
p, cleanup := providerWithFakeServer(t, server, []string{"go"})
defer cleanup()
g, err := store_sqlite.Open(filepath.Join(t.TempDir(), "enrich.sqlite"))
require.NoError(t, err)
defer g.Close()
var _ graph.LightNodeReader = g // the branch this test targets
// F is already stamped by a prior pass — must not be re-hovered.
g.AddNode(&graph.Node{
ID: "main.go::F", Kind: graph.KindFunction, Name: "F",
FilePath: "main.go", StartLine: 3, EndLine: 3, Language: "go",
Meta: map[string]any{"semantic_type": "func F() string", "semantic_source": "lsp-prior"},
})
// G is fresh — must be hovered and stamped. Carries a non-promoted meta
// key that has nothing to do with enrichment, standing in for whatever
// else the graph recorded for this node (e.g. a DI-contract tag).
g.AddNode(&graph.Node{
ID: "main.go::G", Kind: graph.KindFunction, Name: "G",
FilePath: "main.go", StartLine: 5, EndLine: 5, Language: "go",
Meta: map[string]any{"unrelated_tag": "keep-me"},
})
done := make(chan *semantic.EnrichResult, 1)
go func() {
res, err := p.Enrich(g, repoRoot)
require.NoError(t, err)
done <- res
}()
var res *semantic.EnrichResult
select {
case res = <-done:
case <-time.After(3 * time.Second):
t.Fatal("Enrich timed out")
}
assert.Equal(t, int64(1), hoverCalls.Load(), "only the fresh node is hovered")
assert.Equal(t, 1, res.HoverCandidates, "post-filter candidate count excludes the stamped node")
assert.Equal(t, 2, res.SymbolsTotal)
assert.Equal(t, 2, res.SymbolsCovered)
// F keeps its prior stamp (a re-hover would have overwritten it).
fNode := g.GetNode("main.go::F")
assert.Equal(t, "func F() string", fNode.Meta["semantic_type"])
assert.Equal(t, "lsp-prior", fNode.Meta["semantic_source"])
// G is now stamped by this pass, AND its pre-existing non-promoted meta
// key survived the light-scan candidate's full refetch + AddBatch.
gNode := g.GetNode("main.go::G")
assert.Equal(t, "func G() int", gNode.Meta["semantic_type"])
assert.Equal(t, "lsp-fake-lsp", gNode.Meta["semantic_source"])
assert.Equal(t, "keep-me", gNode.Meta["unrelated_tag"],
"non-promoted meta present before enrichment must survive the light-scan round trip")
}