Moved tests in test folder (and made methods public in server.go)
This commit is contained in:
@@ -47,10 +47,10 @@ type CompletionList struct {
|
||||
Items []CompletionItem `json:"items"`
|
||||
}
|
||||
|
||||
var tree = index.NewProjectTree()
|
||||
var documents = make(map[string]string)
|
||||
var projectRoot string
|
||||
var globalSchema *schema.Schema
|
||||
var Tree = index.NewProjectTree()
|
||||
var Documents = make(map[string]string)
|
||||
var ProjectRoot string
|
||||
var GlobalSchema *schema.Schema
|
||||
|
||||
type JsonRpcMessage struct {
|
||||
Jsonrpc string `json:"jsonrpc"`
|
||||
@@ -184,7 +184,7 @@ func RunServer() {
|
||||
continue
|
||||
}
|
||||
|
||||
handleMessage(msg)
|
||||
HandleMessage(msg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ func readMessage(reader *bufio.Reader) (*JsonRpcMessage, error) {
|
||||
return &msg, err
|
||||
}
|
||||
|
||||
func handleMessage(msg *JsonRpcMessage) {
|
||||
func HandleMessage(msg *JsonRpcMessage) {
|
||||
switch msg.Method {
|
||||
case "initialize":
|
||||
var params InitializeParams
|
||||
@@ -227,13 +227,13 @@ func handleMessage(msg *JsonRpcMessage) {
|
||||
}
|
||||
|
||||
if root != "" {
|
||||
projectRoot = root
|
||||
ProjectRoot = root
|
||||
logger.Printf("Scanning workspace: %s\n", root)
|
||||
if err := tree.ScanDirectory(root); err != nil {
|
||||
if err := Tree.ScanDirectory(root); err != nil {
|
||||
logger.Printf("ScanDirectory failed: %v\n", err)
|
||||
}
|
||||
tree.ResolveReferences()
|
||||
globalSchema = schema.LoadFullSchema(projectRoot)
|
||||
Tree.ResolveReferences()
|
||||
GlobalSchema = schema.LoadFullSchema(ProjectRoot)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,18 +258,18 @@ func handleMessage(msg *JsonRpcMessage) {
|
||||
case "textDocument/didOpen":
|
||||
var params DidOpenTextDocumentParams
|
||||
if err := json.Unmarshal(msg.Params, ¶ms); err == nil {
|
||||
handleDidOpen(params)
|
||||
HandleDidOpen(params)
|
||||
}
|
||||
case "textDocument/didChange":
|
||||
var params DidChangeTextDocumentParams
|
||||
if err := json.Unmarshal(msg.Params, ¶ms); err == nil {
|
||||
handleDidChange(params)
|
||||
HandleDidChange(params)
|
||||
}
|
||||
case "textDocument/hover":
|
||||
var params HoverParams
|
||||
if err := json.Unmarshal(msg.Params, ¶ms); err == nil {
|
||||
logger.Printf("Hover: %s:%d", params.TextDocument.URI, params.Position.Line)
|
||||
res := handleHover(params)
|
||||
res := HandleHover(params)
|
||||
if res != nil {
|
||||
logger.Printf("Res: %v", res.Contents)
|
||||
} else {
|
||||
@@ -283,22 +283,22 @@ func handleMessage(msg *JsonRpcMessage) {
|
||||
case "textDocument/definition":
|
||||
var params DefinitionParams
|
||||
if err := json.Unmarshal(msg.Params, ¶ms); err == nil {
|
||||
respond(msg.ID, handleDefinition(params))
|
||||
respond(msg.ID, HandleDefinition(params))
|
||||
}
|
||||
case "textDocument/references":
|
||||
var params ReferenceParams
|
||||
if err := json.Unmarshal(msg.Params, ¶ms); err == nil {
|
||||
respond(msg.ID, handleReferences(params))
|
||||
respond(msg.ID, HandleReferences(params))
|
||||
}
|
||||
case "textDocument/completion":
|
||||
var params CompletionParams
|
||||
if err := json.Unmarshal(msg.Params, ¶ms); err == nil {
|
||||
respond(msg.ID, handleCompletion(params))
|
||||
respond(msg.ID, HandleCompletion(params))
|
||||
}
|
||||
case "textDocument/formatting":
|
||||
var params DocumentFormattingParams
|
||||
if err := json.Unmarshal(msg.Params, ¶ms); err == nil {
|
||||
respond(msg.ID, handleFormatting(params))
|
||||
respond(msg.ID, HandleFormatting(params))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -307,9 +307,9 @@ func uriToPath(uri string) string {
|
||||
return strings.TrimPrefix(uri, "file://")
|
||||
}
|
||||
|
||||
func handleDidOpen(params DidOpenTextDocumentParams) {
|
||||
func HandleDidOpen(params DidOpenTextDocumentParams) {
|
||||
path := uriToPath(params.TextDocument.URI)
|
||||
documents[params.TextDocument.URI] = params.TextDocument.Text
|
||||
Documents[params.TextDocument.URI] = params.TextDocument.Text
|
||||
p := parser.NewParser(params.TextDocument.Text)
|
||||
config, err := p.Parse()
|
||||
|
||||
@@ -320,18 +320,18 @@ func handleDidOpen(params DidOpenTextDocumentParams) {
|
||||
}
|
||||
|
||||
if config != nil {
|
||||
tree.AddFile(path, config)
|
||||
tree.ResolveReferences()
|
||||
Tree.AddFile(path, config)
|
||||
Tree.ResolveReferences()
|
||||
runValidation(params.TextDocument.URI)
|
||||
}
|
||||
}
|
||||
|
||||
func handleDidChange(params DidChangeTextDocumentParams) {
|
||||
func HandleDidChange(params DidChangeTextDocumentParams) {
|
||||
if len(params.ContentChanges) == 0 {
|
||||
return
|
||||
}
|
||||
text := params.ContentChanges[0].Text
|
||||
documents[params.TextDocument.URI] = text
|
||||
Documents[params.TextDocument.URI] = text
|
||||
path := uriToPath(params.TextDocument.URI)
|
||||
p := parser.NewParser(text)
|
||||
config, err := p.Parse()
|
||||
@@ -343,15 +343,15 @@ func handleDidChange(params DidChangeTextDocumentParams) {
|
||||
}
|
||||
|
||||
if config != nil {
|
||||
tree.AddFile(path, config)
|
||||
tree.ResolveReferences()
|
||||
Tree.AddFile(path, config)
|
||||
Tree.ResolveReferences()
|
||||
runValidation(params.TextDocument.URI)
|
||||
}
|
||||
}
|
||||
|
||||
func handleFormatting(params DocumentFormattingParams) []TextEdit {
|
||||
func HandleFormatting(params DocumentFormattingParams) []TextEdit {
|
||||
uri := params.TextDocument.URI
|
||||
text, ok := documents[uri]
|
||||
text, ok := Documents[uri]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
@@ -383,7 +383,7 @@ func handleFormatting(params DocumentFormattingParams) []TextEdit {
|
||||
}
|
||||
|
||||
func runValidation(uri string) {
|
||||
v := validator.NewValidator(tree, projectRoot)
|
||||
v := validator.NewValidator(Tree, ProjectRoot)
|
||||
v.ValidateProject()
|
||||
v.CheckUnused()
|
||||
|
||||
@@ -392,7 +392,7 @@ func runValidation(uri string) {
|
||||
|
||||
// Collect all known files to ensure we clear diagnostics for fixed files
|
||||
knownFiles := make(map[string]bool)
|
||||
collectFiles(tree.Root, knownFiles)
|
||||
collectFiles(Tree.Root, knownFiles)
|
||||
|
||||
// Initialize all known files with empty diagnostics
|
||||
for f := range knownFiles {
|
||||
@@ -501,12 +501,12 @@ func mustMarshal(v any) json.RawMessage {
|
||||
return b
|
||||
}
|
||||
|
||||
func handleHover(params HoverParams) *Hover {
|
||||
func HandleHover(params HoverParams) *Hover {
|
||||
path := uriToPath(params.TextDocument.URI)
|
||||
line := params.Position.Line + 1
|
||||
col := params.Position.Character + 1
|
||||
|
||||
res := tree.Query(path, line, col)
|
||||
res := Tree.Query(path, line, col)
|
||||
if res == nil {
|
||||
logger.Printf("No object/node/reference found")
|
||||
return nil
|
||||
@@ -553,10 +553,10 @@ func handleHover(params HoverParams) *Hover {
|
||||
}
|
||||
}
|
||||
|
||||
func handleCompletion(params CompletionParams) *CompletionList {
|
||||
func HandleCompletion(params CompletionParams) *CompletionList {
|
||||
uri := params.TextDocument.URI
|
||||
path := uriToPath(uri)
|
||||
text, ok := documents[uri]
|
||||
text, ok := Documents[uri]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
@@ -591,7 +591,7 @@ func handleCompletion(params CompletionParams) *CompletionList {
|
||||
return suggestClasses()
|
||||
}
|
||||
|
||||
container := tree.GetNodeContaining(path, parser.Position{Line: params.Position.Line + 1, Column: col + 1})
|
||||
container := Tree.GetNodeContaining(path, parser.Position{Line: params.Position.Line + 1, Column: col + 1})
|
||||
if container != nil {
|
||||
return suggestFieldValues(container, key, path)
|
||||
}
|
||||
@@ -599,7 +599,7 @@ func handleCompletion(params CompletionParams) *CompletionList {
|
||||
}
|
||||
|
||||
// Case 2: Typing a key inside an object
|
||||
container := tree.GetNodeContaining(path, parser.Position{Line: params.Position.Line + 1, Column: col + 1})
|
||||
container := Tree.GetNodeContaining(path, parser.Position{Line: params.Position.Line + 1, Column: col + 1})
|
||||
if container != nil {
|
||||
return suggestFields(container)
|
||||
}
|
||||
@@ -608,11 +608,11 @@ func handleCompletion(params CompletionParams) *CompletionList {
|
||||
}
|
||||
|
||||
func suggestClasses() *CompletionList {
|
||||
if globalSchema == nil {
|
||||
if GlobalSchema == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
classesVal := globalSchema.Value.LookupPath(cue.ParsePath("#Classes"))
|
||||
classesVal := GlobalSchema.Value.LookupPath(cue.ParsePath("#Classes"))
|
||||
if classesVal.Err() != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -647,11 +647,11 @@ func suggestFields(container *index.ProjectNode) *CompletionList {
|
||||
}}}
|
||||
}
|
||||
|
||||
if globalSchema == nil {
|
||||
if GlobalSchema == nil {
|
||||
return nil
|
||||
}
|
||||
classPath := cue.ParsePath(fmt.Sprintf("#Classes.%s", cls))
|
||||
classVal := globalSchema.Value.LookupPath(classPath)
|
||||
classVal := GlobalSchema.Value.LookupPath(classPath)
|
||||
if classVal.Err() != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -711,10 +711,10 @@ func suggestFields(container *index.ProjectNode) *CompletionList {
|
||||
|
||||
func suggestFieldValues(container *index.ProjectNode, field string, path string) *CompletionList {
|
||||
var root *index.ProjectNode
|
||||
if iso, ok := tree.IsolatedFiles[path]; ok {
|
||||
if iso, ok := Tree.IsolatedFiles[path]; ok {
|
||||
root = iso
|
||||
} else {
|
||||
root = tree.Root
|
||||
root = Tree.Root
|
||||
}
|
||||
|
||||
if field == "DataSource" {
|
||||
@@ -779,12 +779,12 @@ func isDataSource(node *index.ProjectNode) bool {
|
||||
return hasSignals
|
||||
}
|
||||
|
||||
func handleDefinition(params DefinitionParams) any {
|
||||
func HandleDefinition(params DefinitionParams) any {
|
||||
path := uriToPath(params.TextDocument.URI)
|
||||
line := params.Position.Line + 1
|
||||
col := params.Position.Character + 1
|
||||
|
||||
res := tree.Query(path, line, col)
|
||||
res := Tree.Query(path, line, col)
|
||||
if res == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -819,12 +819,12 @@ func handleDefinition(params DefinitionParams) any {
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleReferences(params ReferenceParams) []Location {
|
||||
func HandleReferences(params ReferenceParams) []Location {
|
||||
path := uriToPath(params.TextDocument.URI)
|
||||
line := params.Position.Line + 1
|
||||
col := params.Position.Character + 1
|
||||
|
||||
res := tree.Query(path, line, col)
|
||||
res := Tree.Query(path, line, col)
|
||||
if res == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -862,7 +862,7 @@ func handleReferences(params ReferenceParams) []Location {
|
||||
}
|
||||
|
||||
// 1. References from index (Aliases)
|
||||
for _, ref := range tree.References {
|
||||
for _, ref := range Tree.References {
|
||||
if ref.Target == canonical {
|
||||
locations = append(locations, Location{
|
||||
URI: "file://" + ref.File,
|
||||
@@ -875,7 +875,7 @@ func handleReferences(params ReferenceParams) []Location {
|
||||
}
|
||||
|
||||
// 2. References from Node Targets (Direct References)
|
||||
tree.Walk(func(node *index.ProjectNode) {
|
||||
Tree.Walk(func(node *index.ProjectNode) {
|
||||
if node.Target == canonical {
|
||||
for _, frag := range node.Fragments {
|
||||
if frag.IsObject {
|
||||
@@ -929,9 +929,9 @@ func formatNodeInfo(node *index.ProjectNode) string {
|
||||
|
||||
// Find references
|
||||
var refs []string
|
||||
for _, ref := range tree.References {
|
||||
for _, ref := range Tree.References {
|
||||
if ref.Target == node {
|
||||
container := tree.GetNodeContaining(ref.File, ref.Position)
|
||||
container := Tree.GetNodeContaining(ref.File, ref.Position)
|
||||
if container != nil {
|
||||
threadName := ""
|
||||
stateName := ""
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
package lsp
|
||||
package integration
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/marte-community/marte-dev-tools/internal/index"
|
||||
"github.com/marte-community/marte-dev-tools/internal/lsp"
|
||||
"github.com/marte-community/marte-dev-tools/internal/parser"
|
||||
"github.com/marte-community/marte-dev-tools/internal/schema"
|
||||
)
|
||||
|
||||
func TestHandleCompletion(t *testing.T) {
|
||||
setup := func() {
|
||||
tree = index.NewProjectTree()
|
||||
documents = make(map[string]string)
|
||||
|
||||
projectRoot = "."
|
||||
globalSchema = schema.NewSchema()
|
||||
lsp.Tree = index.NewProjectTree()
|
||||
lsp.Documents = make(map[string]string)
|
||||
lsp.ProjectRoot = "."
|
||||
lsp.GlobalSchema = schema.NewSchema()
|
||||
}
|
||||
|
||||
uri := "file://test.marte"
|
||||
@@ -24,14 +24,14 @@ func TestHandleCompletion(t *testing.T) {
|
||||
t.Run("Suggest Classes", func(t *testing.T) {
|
||||
setup()
|
||||
content := "+Obj = { Class = "
|
||||
documents[uri] = content
|
||||
lsp.Documents[uri] = content
|
||||
|
||||
params := CompletionParams{
|
||||
TextDocument: TextDocumentIdentifier{URI: uri},
|
||||
Position: Position{Line: 0, Character: len(content)},
|
||||
params := lsp.CompletionParams{
|
||||
TextDocument: lsp.TextDocumentIdentifier{URI: uri},
|
||||
Position: lsp.Position{Line: 0, Character: len(content)},
|
||||
}
|
||||
|
||||
list := handleCompletion(params)
|
||||
list := lsp.HandleCompletion(params)
|
||||
if list == nil || len(list.Items) == 0 {
|
||||
t.Fatal("Expected class suggestions, got none")
|
||||
}
|
||||
@@ -53,21 +53,21 @@ func TestHandleCompletion(t *testing.T) {
|
||||
content := `
|
||||
+MyApp = {
|
||||
Class = RealTimeApplication
|
||||
|
||||
|
||||
}
|
||||
`
|
||||
documents[uri] = content
|
||||
lsp.Documents[uri] = content
|
||||
p := parser.NewParser(content)
|
||||
cfg, _ := p.Parse()
|
||||
tree.AddFile(path, cfg)
|
||||
lsp.Tree.AddFile(path, cfg)
|
||||
|
||||
// Position at line 3 (empty line inside MyApp)
|
||||
params := CompletionParams{
|
||||
TextDocument: TextDocumentIdentifier{URI: uri},
|
||||
Position: Position{Line: 3, Character: 4},
|
||||
params := lsp.CompletionParams{
|
||||
TextDocument: lsp.TextDocumentIdentifier{URI: uri},
|
||||
Position: lsp.Position{Line: 3, Character: 4},
|
||||
}
|
||||
|
||||
list := handleCompletion(params)
|
||||
list := lsp.HandleCompletion(params)
|
||||
if list == nil || len(list.Items) == 0 {
|
||||
t.Fatal("Expected field suggestions, got none")
|
||||
}
|
||||
@@ -106,19 +106,19 @@ $App = {
|
||||
}
|
||||
}
|
||||
`
|
||||
documents[uri] = content
|
||||
lsp.Documents[uri] = content
|
||||
p := parser.NewParser(content)
|
||||
cfg, _ := p.Parse()
|
||||
tree.AddFile(path, cfg)
|
||||
tree.ResolveReferences()
|
||||
lsp.Tree.AddFile(path, cfg)
|
||||
lsp.Tree.ResolveReferences()
|
||||
|
||||
// Position at end of "DataSource = "
|
||||
params := CompletionParams{
|
||||
TextDocument: TextDocumentIdentifier{URI: uri},
|
||||
Position: Position{Line: 14, Character: 28},
|
||||
params := lsp.CompletionParams{
|
||||
TextDocument: lsp.TextDocumentIdentifier{URI: uri},
|
||||
Position: lsp.Position{Line: 14, Character: 28},
|
||||
}
|
||||
|
||||
list := handleCompletion(params)
|
||||
list := lsp.HandleCompletion(params)
|
||||
if list == nil || len(list.Items) == 0 {
|
||||
t.Fatal("Expected DataSource suggestions, got none")
|
||||
}
|
||||
@@ -141,21 +141,21 @@ $App = {
|
||||
+MyThread = {
|
||||
Class = RealTimeThread
|
||||
Functions = { }
|
||||
|
||||
|
||||
}
|
||||
`
|
||||
documents[uri] = content
|
||||
lsp.Documents[uri] = content
|
||||
p := parser.NewParser(content)
|
||||
cfg, _ := p.Parse()
|
||||
tree.AddFile(path, cfg)
|
||||
lsp.Tree.AddFile(path, cfg)
|
||||
|
||||
// Position at line 4
|
||||
params := CompletionParams{
|
||||
TextDocument: TextDocumentIdentifier{URI: uri},
|
||||
Position: Position{Line: 4, Character: 4},
|
||||
params := lsp.CompletionParams{
|
||||
TextDocument: lsp.TextDocumentIdentifier{URI: uri},
|
||||
Position: lsp.Position{Line: 4, Character: 4},
|
||||
}
|
||||
|
||||
list := handleCompletion(params)
|
||||
list := lsp.HandleCompletion(params)
|
||||
for _, item := range list.Items {
|
||||
if item.Label == "Functions" || item.Label == "Class" {
|
||||
t.Errorf("Did not expect already defined field %s in suggestions", item.Label)
|
||||
@@ -163,27 +163,27 @@ $App = {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Scope-aware suggestions", func(t *testing.T) {
|
||||
t.Run("Scope-aware suggestions", func(t *testing.T) {
|
||||
setup()
|
||||
// Define a project DataSource in one file
|
||||
cfg1, _ := parser.NewParser("#package MYPROJ.Data\n+ProjectDS = { Class = FileReader +Signals = { S1 = { Type = int32 } } }").Parse()
|
||||
tree.AddFile("project_ds.marte", cfg1)
|
||||
lsp.Tree.AddFile("project_ds.marte", cfg1)
|
||||
|
||||
// Define an isolated file
|
||||
contentIso := "+MyGAM = { Class = IOGAM +InputSignals = { S1 = { DataSource = } } }"
|
||||
documents["file://iso.marte"] = contentIso
|
||||
lsp.Documents["file://iso.marte"] = contentIso
|
||||
cfg2, _ := parser.NewParser(contentIso).Parse()
|
||||
tree.AddFile("iso.marte", cfg2)
|
||||
lsp.Tree.AddFile("iso.marte", cfg2)
|
||||
|
||||
tree.ResolveReferences()
|
||||
lsp.Tree.ResolveReferences()
|
||||
|
||||
// Completion in isolated file
|
||||
params := CompletionParams{
|
||||
TextDocument: TextDocumentIdentifier{URI: "file://iso.marte"},
|
||||
Position: Position{Line: 0, Character: strings.Index(contentIso, "DataSource = ") + len("DataSource = ") + 1},
|
||||
params := lsp.CompletionParams{
|
||||
TextDocument: lsp.TextDocumentIdentifier{URI: "file://iso.marte"},
|
||||
Position: lsp.Position{Line: 0, Character: strings.Index(contentIso, "DataSource = ") + len("DataSource = ") + 1},
|
||||
}
|
||||
|
||||
list := handleCompletion(params)
|
||||
list := lsp.HandleCompletion(params)
|
||||
foundProjectDS := false
|
||||
if list != nil {
|
||||
for _, item := range list.Items {
|
||||
@@ -200,21 +200,21 @@ $App = {
|
||||
// Completion in a project file
|
||||
lineContent := "+MyGAM = { Class = IOGAM +InputSignals = { S1 = { DataSource = Dummy } } }"
|
||||
contentPrj := "#package MYPROJ.App\n" + lineContent
|
||||
documents["file://prj.marte"] = contentPrj
|
||||
lsp.Documents["file://prj.marte"] = contentPrj
|
||||
pPrj := parser.NewParser(contentPrj)
|
||||
cfg3, err := pPrj.Parse()
|
||||
if err != nil {
|
||||
t.Logf("Parser error in contentPrj: %v", err)
|
||||
}
|
||||
tree.AddFile("prj.marte", cfg3)
|
||||
tree.ResolveReferences()
|
||||
lsp.Tree.AddFile("prj.marte", cfg3)
|
||||
lsp.Tree.ResolveReferences()
|
||||
|
||||
paramsPrj := CompletionParams{
|
||||
TextDocument: TextDocumentIdentifier{URI: "file://prj.marte"},
|
||||
Position: Position{Line: 1, Character: strings.Index(lineContent, "Dummy")},
|
||||
paramsPrj := lsp.CompletionParams{
|
||||
TextDocument: lsp.TextDocumentIdentifier{URI: "file://prj.marte"},
|
||||
Position: lsp.Position{Line: 1, Character: strings.Index(lineContent, "Dummy")},
|
||||
}
|
||||
|
||||
listPrj := handleCompletion(paramsPrj)
|
||||
listPrj := lsp.HandleCompletion(paramsPrj)
|
||||
foundProjectDS = false
|
||||
if listPrj != nil {
|
||||
for _, item := range listPrj.Items {
|
||||
@@ -1,4 +1,4 @@
|
||||
package lsp
|
||||
package integration
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/marte-community/marte-dev-tools/internal/index"
|
||||
"github.com/marte-community/marte-dev-tools/internal/lsp"
|
||||
"github.com/marte-community/marte-dev-tools/internal/parser"
|
||||
)
|
||||
|
||||
@@ -24,50 +25,38 @@ func TestInitProjectScan(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// File 2: Reference
|
||||
// +Source = { Class = C Link = Target }
|
||||
// Link = Target starts at index ...
|
||||
// #package Test.Common (21 chars including newline)
|
||||
// +Source = { Class = C Link = Target }
|
||||
// 012345678901234567890123456789012345
|
||||
// Previous offset was 29.
|
||||
// Now add 21?
|
||||
// #package Test.Common\n
|
||||
// +Source = ...
|
||||
// So add 21 to Character? Or Line 1?
|
||||
// It's on Line 1 (0-based 1).
|
||||
if err := os.WriteFile(filepath.Join(tmpDir, "ref.marte"), []byte("#package Test.Common\n+Source = { Class = C Link = Target }"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// 2. Initialize
|
||||
tree = index.NewProjectTree() // Reset global tree
|
||||
lsp.Tree = index.NewProjectTree() // Reset global tree
|
||||
|
||||
initParams := InitializeParams{RootPath: tmpDir}
|
||||
initParams := lsp.InitializeParams{RootPath: tmpDir}
|
||||
paramsBytes, _ := json.Marshal(initParams)
|
||||
|
||||
msg := &JsonRpcMessage{
|
||||
msg := &lsp.JsonRpcMessage{
|
||||
Method: "initialize",
|
||||
Params: paramsBytes,
|
||||
ID: 1,
|
||||
}
|
||||
|
||||
handleMessage(msg)
|
||||
lsp.HandleMessage(msg)
|
||||
|
||||
// Query the reference in ref.marte at "Target"
|
||||
// Target starts at index 29 (0-based) on Line 1
|
||||
defParams := DefinitionParams{
|
||||
TextDocument: TextDocumentIdentifier{URI: "file://" + filepath.Join(tmpDir, "ref.marte")},
|
||||
Position: Position{Line: 1, Character: 29},
|
||||
defParams := lsp.DefinitionParams{
|
||||
TextDocument: lsp.TextDocumentIdentifier{URI: "file://" + filepath.Join(tmpDir, "ref.marte")},
|
||||
Position: lsp.Position{Line: 1, Character: 29},
|
||||
}
|
||||
|
||||
res := handleDefinition(defParams)
|
||||
res := lsp.HandleDefinition(defParams)
|
||||
if res == nil {
|
||||
t.Fatal("Definition not found via LSP after initialization")
|
||||
}
|
||||
|
||||
locs, ok := res.([]Location)
|
||||
locs, ok := res.([]lsp.Location)
|
||||
if !ok {
|
||||
t.Fatalf("Expected []Location, got %T", res)
|
||||
t.Fatalf("Expected []lsp.Location, got %T", res)
|
||||
}
|
||||
|
||||
if len(locs) == 0 {
|
||||
@@ -83,7 +72,7 @@ func TestInitProjectScan(t *testing.T) {
|
||||
|
||||
func TestHandleDefinition(t *testing.T) {
|
||||
// Reset tree for test
|
||||
tree = index.NewProjectTree()
|
||||
lsp.Tree = index.NewProjectTree()
|
||||
|
||||
content := `
|
||||
+MyObject = {
|
||||
@@ -100,28 +89,28 @@ func TestHandleDefinition(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Parse failed: %v", err)
|
||||
}
|
||||
tree.AddFile(path, config)
|
||||
tree.ResolveReferences()
|
||||
lsp.Tree.AddFile(path, config)
|
||||
lsp.Tree.ResolveReferences()
|
||||
|
||||
t.Logf("Refs: %d", len(tree.References))
|
||||
for _, r := range tree.References {
|
||||
t.Logf("Refs: %d", len(lsp.Tree.References))
|
||||
for _, r := range lsp.Tree.References {
|
||||
t.Logf(" %s at %d:%d", r.Name, r.Position.Line, r.Position.Column)
|
||||
}
|
||||
|
||||
// Test Go to Definition on MyObject reference
|
||||
params := DefinitionParams{
|
||||
TextDocument: TextDocumentIdentifier{URI: "file://" + path},
|
||||
Position: Position{Line: 6, Character: 15}, // "MyObject" in RefField = MyObject
|
||||
params := lsp.DefinitionParams{
|
||||
TextDocument: lsp.TextDocumentIdentifier{URI: "file://" + path},
|
||||
Position: lsp.Position{Line: 6, Character: 15}, // "MyObject" in RefField = MyObject
|
||||
}
|
||||
|
||||
result := handleDefinition(params)
|
||||
result := lsp.HandleDefinition(params)
|
||||
if result == nil {
|
||||
t.Fatal("handleDefinition returned nil")
|
||||
t.Fatal("HandleDefinition returned nil")
|
||||
}
|
||||
|
||||
locations, ok := result.([]Location)
|
||||
locations, ok := result.([]lsp.Location)
|
||||
if !ok {
|
||||
t.Fatalf("Expected []Location, got %T", result)
|
||||
t.Fatalf("Expected []lsp.Location, got %T", result)
|
||||
}
|
||||
|
||||
if len(locations) != 1 {
|
||||
@@ -135,7 +124,7 @@ func TestHandleDefinition(t *testing.T) {
|
||||
|
||||
func TestHandleReferences(t *testing.T) {
|
||||
// Reset tree for test
|
||||
tree = index.NewProjectTree()
|
||||
lsp.Tree = index.NewProjectTree()
|
||||
|
||||
content := `
|
||||
+MyObject = {
|
||||
@@ -155,17 +144,17 @@ func TestHandleReferences(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Parse failed: %v", err)
|
||||
}
|
||||
tree.AddFile(path, config)
|
||||
tree.ResolveReferences()
|
||||
lsp.Tree.AddFile(path, config)
|
||||
lsp.Tree.ResolveReferences()
|
||||
|
||||
// Test Find References for MyObject (triggered from its definition)
|
||||
params := ReferenceParams{
|
||||
TextDocument: TextDocumentIdentifier{URI: "file://" + path},
|
||||
Position: Position{Line: 1, Character: 1}, // "+MyObject"
|
||||
Context: ReferenceContext{IncludeDeclaration: true},
|
||||
params := lsp.ReferenceParams{
|
||||
TextDocument: lsp.TextDocumentIdentifier{URI: "file://" + path},
|
||||
Position: lsp.Position{Line: 1, Character: 1}, // "+MyObject"
|
||||
Context: lsp.ReferenceContext{IncludeDeclaration: true},
|
||||
}
|
||||
|
||||
locations := handleReferences(params)
|
||||
locations := lsp.HandleReferences(params)
|
||||
if len(locations) != 3 { // 1 declaration + 2 references
|
||||
t.Fatalf("Expected 3 locations, got %d", len(locations))
|
||||
}
|
||||
@@ -181,15 +170,15 @@ Field=1
|
||||
`
|
||||
uri := "file:///test.marte"
|
||||
|
||||
// Open (populate documents map)
|
||||
documents[uri] = content
|
||||
// Open (populate Documents map)
|
||||
lsp.Documents[uri] = content
|
||||
|
||||
// Format
|
||||
params := DocumentFormattingParams{
|
||||
TextDocument: TextDocumentIdentifier{URI: uri},
|
||||
params := lsp.DocumentFormattingParams{
|
||||
TextDocument: lsp.TextDocumentIdentifier{URI: uri},
|
||||
}
|
||||
|
||||
edits := handleFormatting(params)
|
||||
edits := lsp.HandleFormatting(params)
|
||||
|
||||
if len(edits) != 1 {
|
||||
t.Fatalf("Expected 1 edit, got %d", len(edits))
|
||||
Reference in New Issue
Block a user