|
diff --git a/editor.go b/editor.go
|
| ... |
| 2066 |
e.centerCursor() |
2066 |
e.centerCursor() |
| 2067 |
} |
2067 |
} |
| 2068 |
|
2068 |
|
|
|
2069 |
func (e *Editor) gotoImplementation() { |
|
|
2070 |
b := e.activeBuffer() |
|
|
2071 |
if b == nil || b.lspClient == nil { |
|
|
2072 |
return |
|
|
2073 |
} |
|
|
2074 |
|
|
|
2075 |
e.pushJump() |
|
|
2076 |
|
|
|
2077 |
// Sync buffer content with LSP server before requesting implementation. |
|
|
2078 |
b.lspClient.SendDidChange(b.toString()) |
|
|
2079 |
|
|
|
2080 |
locs, err := b.lspClient.Implementation(b.PrimaryCursor().Y, b.PrimaryCursor().X) |
|
|
2081 |
if err != nil { |
|
|
2082 |
e.addLog("Editor", fmt.Sprintf("gotoImplementation error: %v", err)) |
|
|
2083 |
return |
|
|
2084 |
} |
|
|
2085 |
|
|
|
2086 |
if len(locs) == 0 { |
|
|
2087 |
e.addLog("Editor", "gotoImplementation: No implementation found") |
|
|
2088 |
return |
|
|
2089 |
} |
|
|
2090 |
|
|
|
2091 |
loc := locs[0] |
|
|
2092 |
targetPath := strings.TrimPrefix(loc.URI, "file://") |
|
|
2093 |
|
|
|
2094 |
// Find if buffer is already open |
|
|
2095 |
found := false |
|
|
2096 |
for i, buf := range e.buffers { |
|
|
2097 |
absT, _ := filepath.Abs(targetPath) |
|
|
2098 |
absB, _ := filepath.Abs(buf.filename) |
|
|
2099 |
if absT == absB { |
|
|
2100 |
e.activeBufferIndex = i |
|
|
2101 |
found = true |
|
|
2102 |
break |
|
|
2103 |
} |
|
|
2104 |
} |
|
|
2105 |
|
|
|
2106 |
if !found { |
|
|
2107 |
if err := e.LoadFile(targetPath); err != nil { |
|
|
2108 |
e.addLog("Editor", fmt.Sprintf("gotoImplementation: Failed to load %s: %v", targetPath, err)) |
|
|
2109 |
return |
|
|
2110 |
} |
|
|
2111 |
} |
|
|
2112 |
|
|
|
2113 |
b = e.activeBuffer() |
|
|
2114 |
b.PrimaryCursor().Y = loc.Range.Start.Line |
|
|
2115 |
b.PrimaryCursor().X = loc.Range.Start.Character |
|
|
2116 |
|
|
|
2117 |
// Ensure cursor is within bounds |
|
|
2118 |
if b.PrimaryCursor().Y < 0 { |
|
|
2119 |
b.PrimaryCursor().Y = 0 |
|
|
2120 |
} |
|
|
2121 |
if b.PrimaryCursor().Y >= len(b.buffer) { |
|
|
2122 |
b.PrimaryCursor().Y = len(b.buffer) - 1 |
|
|
2123 |
} |
|
|
2124 |
if b.PrimaryCursor().X < 0 { |
|
|
2125 |
b.PrimaryCursor().X = 0 |
|
|
2126 |
} |
|
|
2127 |
if b.PrimaryCursor().X > len(b.buffer[b.PrimaryCursor().Y]) { |
|
|
2128 |
b.PrimaryCursor().X = len(b.buffer[b.PrimaryCursor().Y]) |
|
|
2129 |
} |
|
|
2130 |
e.centerCursor() |
|
|
2131 |
} |
|
|
2132 |
|
| 2069 |
func (e *Editor) pushJump() { |
2133 |
func (e *Editor) pushJump() { |
| 2070 |
b := e.activeBuffer() |
2134 |
b := e.activeBuffer() |
| 2071 |
if b == nil { |
2135 |
if b == nil { |
| ... |
|
diff --git a/lsp.go b/lsp.go
|
| ... |
| 481 |
"dynamicRegistration": false, |
481 |
"dynamicRegistration": false, |
| 482 |
"linkSupport": false, |
482 |
"linkSupport": false, |
| 483 |
}, |
483 |
}, |
|
|
484 |
"implementation": map[string]interface{}{ |
|
|
485 |
"dynamicRegistration": false, |
|
|
486 |
"linkSupport": false, |
|
|
487 |
}, |
| 484 |
}, |
488 |
}, |
| 485 |
"workspace": map[string]interface{}{ |
489 |
"workspace": map[string]interface{}{ |
| 486 |
"configuration": true, |
490 |
"configuration": true, |
| ... |
| 572 |
resJSON, _ := json.Marshal(result) |
576 |
resJSON, _ := json.Marshal(result) |
| 573 |
|
577 |
|
| 574 |
// Definition can return a single Location or an array of them. |
578 |
// Definition can return a single Location or an array of them. |
|
|
579 |
var loc Location |
|
|
580 |
if err := json.Unmarshal(resJSON, &loc); err == nil && loc.URI != "" { |
|
|
581 |
return []Location{loc}, nil |
|
|
582 |
} |
|
|
583 |
|
|
|
584 |
var locs []Location |
|
|
585 |
if err := json.Unmarshal(resJSON, &locs); err == nil { |
|
|
586 |
return locs, nil |
|
|
587 |
} |
|
|
588 |
|
|
|
589 |
return nil, nil |
|
|
590 |
} |
|
|
591 |
|
|
|
592 |
// Implementation requests the location of the implementation of the symbol at cursor. |
|
|
593 |
func (c *LSPClient) Implementation(line, character int) ([]Location, error) { |
|
|
594 |
params := map[string]interface{}{ |
|
|
595 |
"textDocument": map[string]interface{}{ |
|
|
596 |
"uri": c.uri, |
|
|
597 |
}, |
|
|
598 |
"position": map[string]interface{}{ |
|
|
599 |
"line": line, |
|
|
600 |
"character": character, |
|
|
601 |
}, |
|
|
602 |
} |
|
|
603 |
|
|
|
604 |
resp, err := c.Request("textDocument/implementation", params) |
|
|
605 |
if err != nil { |
|
|
606 |
return nil, err |
|
|
607 |
} |
|
|
608 |
|
|
|
609 |
result := resp["result"] |
|
|
610 |
if result == nil { |
|
|
611 |
return nil, nil |
|
|
612 |
} |
|
|
613 |
|
|
|
614 |
resJSON, _ := json.Marshal(result) |
|
|
615 |
|
|
|
616 |
// Implementation can return a single Location or an array of them. |
| 575 |
var loc Location |
617 |
var loc Location |
| 576 |
if err := json.Unmarshal(resJSON, &loc); err == nil && loc.URI != "" { |
618 |
if err := json.Unmarshal(resJSON, &loc); err == nil && loc.URI != "" { |
| 577 |
return []Location{loc}, nil |
619 |
return []Location{loc}, nil |
| ... |