diff --git a/internal/index/index.go b/internal/index/index.go index 660f6c3..930ca5a 100644 --- a/internal/index/index.go +++ b/internal/index/index.go @@ -182,19 +182,13 @@ func (pt *ProjectTree) AddFile(file string, config *parser.Configuration) { } if config.Package == nil { - node := &ProjectNode{ - Children: make(map[string]*ProjectNode), - Metadata: make(map[string]string), - Variables: make(map[string]VariableInfo), - } - pt.IsolatedFiles[file] = node - pt.populateNode(node, file, config) + pt.populateNode(pt.Root, file, config) return } node := pt.Root parts := strings.Split(config.Package.URI, ".") - + for i := 0; i < len(parts); i++ { part := strings.TrimSpace(parts[i]) if part == "" { @@ -399,8 +393,9 @@ func (pt *ProjectTree) indexValue(file string, val parser.Value) { File: file, }) case *parser.VariableReferenceValue: + name := strings.TrimPrefix(v.Name, "@") pt.References = append(pt.References, Reference{ - Name: strings.TrimPrefix(v.Name, "@"), + Name: name, Position: v.Position, File: file, IsVariable: true, diff --git a/test/lsp_completion_test.go b/test/lsp_completion_test.go index dcc3565..000f177 100644 --- a/test/lsp_completion_test.go +++ b/test/lsp_completion_test.go @@ -193,8 +193,8 @@ $App = { } } } - if foundProjectDS { - t.Error("Did not expect ProjectDS in isolated file suggestions") + if !foundProjectDS { + t.Error("Expected ProjectDS in isolated file suggestions (now shared root)") } // Completion in a project file diff --git a/test/lsp_signal_test.go b/test/lsp_signal_test.go index 81a0826..013d5e4 100644 --- a/test/lsp_signal_test.go +++ b/test/lsp_signal_test.go @@ -45,7 +45,7 @@ func TestLSPSignalReferences(t *testing.T) { v.ValidateProject() // Find definition of MySig in MyDS - root := idx.IsolatedFiles["signal_refs.marte"] + root := idx.Root if root == nil { t.Fatal("Root node not found") } diff --git a/test/validator_multifile_test.go b/test/validator_multifile_test.go index 5b1c833..e02820e 100644 --- a/test/validator_multifile_test.go +++ b/test/validator_multifile_test.go @@ -194,7 +194,7 @@ func TestIsolatedFileValidation(t *testing.T) { t.Fatal("Reference SharedObj not found in index") } - if ref.Target != nil { - t.Errorf("Expected reference in isolated file to be unresolved, but got target in %s", ref.Target.Fragments[0].File) + if ref.Target == nil { + t.Errorf("Expected reference in root file (iso.marte) to resolve to global SharedObj") } } diff --git a/test/variable_multifile_test.go b/test/variable_multifile_test.go new file mode 100644 index 0000000..e33f3bf --- /dev/null +++ b/test/variable_multifile_test.go @@ -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 +}