143 lines
3.5 KiB
Go
143 lines
3.5 KiB
Go
package integration
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"testing"
|
|
|
|
"github.com/marte-dev/marte-dev-tools/internal/index"
|
|
"github.com/marte-dev/marte-dev-tools/internal/parser"
|
|
"github.com/marte-dev/marte-dev-tools/internal/validator"
|
|
)
|
|
|
|
// Helper to load and parse a file
|
|
func loadConfig(t *testing.T, filename string) *parser.Configuration {
|
|
content, err := ioutil.ReadFile(filename)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read %s: %v", filename, err)
|
|
}
|
|
p := parser.NewParser(string(content))
|
|
config, err := p.Parse()
|
|
if err != nil {
|
|
t.Fatalf("Parse failed: %v", err)
|
|
}
|
|
return config
|
|
}
|
|
|
|
func TestLSPDiagnostics(t *testing.T) {
|
|
inputFile := "integration/check_dup.marte"
|
|
config := loadConfig(t, inputFile)
|
|
|
|
// Simulate LSP logic: Build Index -> Validate
|
|
idx := index.NewProjectTree()
|
|
idx.AddFile(inputFile, config)
|
|
|
|
v := validator.NewValidator(idx, ".")
|
|
v.ValidateProject()
|
|
|
|
// Check for expected diagnostics
|
|
found := false
|
|
for _, d := range v.Diagnostics {
|
|
if d.Message == "Duplicate Field Definition: 'Field' is already defined in integration/check_dup.marte" {
|
|
found = true
|
|
if d.Position.Line != 5 {
|
|
t.Errorf("Expected diagnostic at line 5, got %d", d.Position.Line)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Error("LSP Diagnostic for duplicate field not found")
|
|
}
|
|
}
|
|
|
|
// For GoToDefinition and References, we need to test the Indexer's ability to resolve symbols.
|
|
// Currently, my Indexer (ProjectTree) stores structure but doesn't explicitly track
|
|
// "references" in a way that maps a source position to a target symbol yet.
|
|
// The ProjectTree is built for structure merging.
|
|
// To support LSP "Go To Definition", we need to map usage -> definition.
|
|
|
|
// Let's verify what we have implemented.
|
|
// `internal/index/index.go`:
|
|
// ProjectTree has Fragments.
|
|
// It does NOT have a "Lookup(position)" method or a reference map.
|
|
// Previously (before rewrite), `index.go` had `References []Reference`.
|
|
// I removed it during the rewrite to ProjectTree!
|
|
|
|
// I need to re-implement reference tracking in `ProjectTree` or a parallel structure
|
|
// to support LSP features.
|
|
func TestLSPDefinition(t *testing.T) {
|
|
// Create a virtual file content with a definition and a reference
|
|
content := `
|
|
+MyObject = {
|
|
Class = Type
|
|
}
|
|
+RefObject = {
|
|
Class = Type
|
|
RefField = MyObject
|
|
}
|
|
`
|
|
p := parser.NewParser(content)
|
|
config, err := p.Parse()
|
|
if err != nil {
|
|
t.Fatalf("Parse failed: %v", err)
|
|
}
|
|
|
|
idx := index.NewProjectTree()
|
|
idx.AddFile("memory.marte", config)
|
|
idx.ResolveReferences()
|
|
|
|
// Find the reference to "MyObject"
|
|
var foundRef *index.Reference
|
|
for _, ref := range idx.References {
|
|
if ref.Name == "MyObject" {
|
|
foundRef = &ref
|
|
break
|
|
}
|
|
}
|
|
|
|
if foundRef == nil {
|
|
t.Fatal("Reference to MyObject not found in index")
|
|
}
|
|
|
|
if foundRef.Target == nil {
|
|
t.Fatal("Reference to MyObject was not resolved to a target")
|
|
}
|
|
|
|
if foundRef.Target.RealName != "+MyObject" {
|
|
t.Errorf("Expected target to be +MyObject, got %s", foundRef.Target.RealName)
|
|
}
|
|
}
|
|
|
|
func TestLSPHover(t *testing.T) {
|
|
content := `
|
|
+MyObject = {
|
|
Class = Type
|
|
}
|
|
`
|
|
p := parser.NewParser(content)
|
|
config, err := p.Parse()
|
|
if err != nil {
|
|
t.Fatalf("Parse failed: %v", err)
|
|
}
|
|
|
|
idx := index.NewProjectTree()
|
|
file := "hover.marte"
|
|
idx.AddFile(file, config)
|
|
|
|
// +MyObject is at line 2.
|
|
// Query at line 2, col 2 (on 'M' of MyObject)
|
|
res := idx.Query(file, 2, 2)
|
|
|
|
if res == nil {
|
|
t.Fatal("Query returned nil")
|
|
}
|
|
|
|
if res.Node == nil {
|
|
t.Fatal("Expected Node result")
|
|
}
|
|
|
|
if res.Node.RealName != "+MyObject" {
|
|
t.Errorf("Expected +MyObject, got %s", res.Node.RealName)
|
|
}
|
|
}
|