better multi file variable support

This commit is contained in:
Martino Ferrari
2026-01-30 18:45:11 +01:00
parent f121f7c15d
commit d4075ff809
5 changed files with 96 additions and 14 deletions

View File

@@ -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,

View File

@@ -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

View 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")
} }

View File

@@ -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")
} }
} }

View 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
}