better multi file variable support
This commit is contained in:
@@ -182,13 +182,7 @@ func (pt *ProjectTree) AddFile(file string, config *parser.Configuration) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config.Package == nil {
|
if config.Package == nil {
|
||||||
node := &ProjectNode{
|
pt.populateNode(pt.Root, file, config)
|
||||||
Children: make(map[string]*ProjectNode),
|
|
||||||
Metadata: make(map[string]string),
|
|
||||||
Variables: make(map[string]VariableInfo),
|
|
||||||
}
|
|
||||||
pt.IsolatedFiles[file] = node
|
|
||||||
pt.populateNode(node, file, config)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,8 +393,9 @@ func (pt *ProjectTree) indexValue(file string, val parser.Value) {
|
|||||||
File: file,
|
File: file,
|
||||||
})
|
})
|
||||||
case *parser.VariableReferenceValue:
|
case *parser.VariableReferenceValue:
|
||||||
|
name := strings.TrimPrefix(v.Name, "@")
|
||||||
pt.References = append(pt.References, Reference{
|
pt.References = append(pt.References, Reference{
|
||||||
Name: strings.TrimPrefix(v.Name, "@"),
|
Name: name,
|
||||||
Position: v.Position,
|
Position: v.Position,
|
||||||
File: file,
|
File: file,
|
||||||
IsVariable: true,
|
IsVariable: true,
|
||||||
|
|||||||
@@ -193,8 +193,8 @@ $App = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if foundProjectDS {
|
if !foundProjectDS {
|
||||||
t.Error("Did not expect ProjectDS in isolated file suggestions")
|
t.Error("Expected ProjectDS in isolated file suggestions (now shared root)")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Completion in a project file
|
// Completion in a project file
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ func TestLSPSignalReferences(t *testing.T) {
|
|||||||
v.ValidateProject()
|
v.ValidateProject()
|
||||||
|
|
||||||
// Find definition of MySig in MyDS
|
// Find definition of MySig in MyDS
|
||||||
root := idx.IsolatedFiles["signal_refs.marte"]
|
root := idx.Root
|
||||||
if root == nil {
|
if root == nil {
|
||||||
t.Fatal("Root node not found")
|
t.Fatal("Root node not found")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ func TestIsolatedFileValidation(t *testing.T) {
|
|||||||
t.Fatal("Reference SharedObj not found in index")
|
t.Fatal("Reference SharedObj not found in index")
|
||||||
}
|
}
|
||||||
|
|
||||||
if ref.Target != nil {
|
if ref.Target == nil {
|
||||||
t.Errorf("Expected reference in isolated file to be unresolved, but got target in %s", ref.Target.Fragments[0].File)
|
t.Errorf("Expected reference in root file (iso.marte) to resolve to global SharedObj")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
87
test/variable_multifile_test.go
Normal file
87
test/variable_multifile_test.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/marte-community/marte-dev-tools/internal/index"
|
||||||
|
"github.com/marte-community/marte-dev-tools/internal/parser"
|
||||||
|
"github.com/marte-community/marte-dev-tools/internal/validator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMultiFileVariableResolution(t *testing.T) {
|
||||||
|
// File 1: Defines a variable in the root scope (no package)
|
||||||
|
file1Content := `#package Test
|
||||||
|
#var GlobalVal: int = 42`
|
||||||
|
|
||||||
|
// File 2: Uses the variable (no package)
|
||||||
|
file2Content := `
|
||||||
|
#package Test
|
||||||
|
+App = {
|
||||||
|
Class = RealTimeApplication
|
||||||
|
Field = @GlobalVal
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
pt := index.NewProjectTree()
|
||||||
|
|
||||||
|
// Parse and add File 1
|
||||||
|
p1 := parser.NewParser(file1Content)
|
||||||
|
cfg1, err := p1.Parse()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse file1 error: %v", err)
|
||||||
|
}
|
||||||
|
pt.AddFile("vars.marte", cfg1)
|
||||||
|
|
||||||
|
// Parse and add File 2
|
||||||
|
p2 := parser.NewParser(file2Content)
|
||||||
|
cfg2, err := p2.Parse()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Parse file2 error: %v", err)
|
||||||
|
}
|
||||||
|
pt.AddFile("main.marte", cfg2)
|
||||||
|
|
||||||
|
pt.ResolveReferences()
|
||||||
|
|
||||||
|
// Validate
|
||||||
|
// We need a dummy schema for CheckVariables to work, or we check References directly.
|
||||||
|
// CheckVariables validates types. CheckUnresolvedVariables validates existence.
|
||||||
|
// We want to check if $GlobalVal is resolved.
|
||||||
|
|
||||||
|
t.Logf("Root Variables keys: %v", getKeys(pt.Root.Variables))
|
||||||
|
|
||||||
|
v := validator.NewValidator(pt, ".")
|
||||||
|
v.CheckUnresolvedVariables()
|
||||||
|
|
||||||
|
for _, d := range v.Diagnostics {
|
||||||
|
if strings.Contains(d.Message, "Unresolved variable") {
|
||||||
|
t.Errorf("Unexpected unresolved variable error: %s", d.Message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify reference target directly
|
||||||
|
found := false
|
||||||
|
for _, ref := range pt.References {
|
||||||
|
if ref.Name == "GlobalVal" {
|
||||||
|
found = true
|
||||||
|
if ref.TargetVariable == nil {
|
||||||
|
t.Error("Reference 'GlobalVal' TargetVariable is nil (not resolved)")
|
||||||
|
} else {
|
||||||
|
if ref.TargetVariable.Name != "GlobalVal" {
|
||||||
|
t.Errorf("Reference resolved to wrong variable: %s", ref.TargetVariable.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Error("Reference 'GlobalVal' not found in index")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getKeys(m map[string]index.VariableInfo) []string {
|
||||||
|
keys := []string{}
|
||||||
|
for k := range m {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
return keys
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user