Skip to content

Commit 3687018

Browse files
authored
Merge pull request #322 from lets-cli/codex/fix-lsp-goto-def-on
Fix LSP go-to-definition for command aliases
2 parents caa90c6 + cdd37d0 commit 3687018

6 files changed

Lines changed: 371 additions & 67 deletions

File tree

docs/docs/changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ title: Changelog
1818
* `[Added]` Add `lets self doc` command to open the online documentation in a browser.
1919
* `[Added]` Show background update notifications for interactive sessions, with Homebrew-aware guidance and `LETS_CHECK_UPDATE` opt-out.
2020
* `[Changed]` Centralize the `lets:` log prefix in the formatter and render debug messages in blue.
21+
* `[Fixed]` Resolve `go to definition` from YAML merge aliases such as `<<: *test` to the referenced command in `lets self lsp`.
2122

2223
## [0.0.59](https://github.com/lets-cli/lets/releases/tag/v0.0.59)
2324

internal/cli/cli.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ func Main(version string, buildDate string) int {
136136
if errors.As(err, &depErr) {
137137
log.Errorf("%s", depErr.TreeMessage())
138138
log.Errorf("%s", depErr.FailureMessage())
139+
139140
return getExitCode(err, 1)
140141
}
141142

internal/lsp/handlers.go

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,19 @@ func (h *definitionHandler) findMixinsDefinition(doc *string, params *lsp.Defini
6868

6969
filename := h.parser.extractFilenameFromMixins(doc, params.Position)
7070
if filename == "" {
71+
h.parser.log.Debugf("no mixin filename resolved at %s:%d:%d", path, params.Position.Line, params.Position.Character)
7172
return nil, nil
7273
}
7374

7475
absFilename := replacePathFilename(path, filename)
7576

7677
if !util.FileExists(absFilename) {
78+
h.parser.log.Debugf("mixin target does not exist: %s", absFilename)
7779
return nil, nil
7880
}
7981

82+
h.parser.log.Debugf("resolved mixin definition %q -> %s", filename, absFilename)
83+
8084
return []lsp.Location{
8185
{
8286
URI: pathToURI(absFilename),
@@ -86,21 +90,28 @@ func (h *definitionHandler) findMixinsDefinition(doc *string, params *lsp.Defini
8690
}
8791

8892
func (h *definitionHandler) findCommandDefinition(doc *string, params *lsp.DefinitionParams) (any, error) {
89-
line := getLine(doc, params.Position.Line)
90-
if line == "" {
91-
return nil, nil
92-
}
93+
path := normalizePath(params.TextDocument.URI)
9394

94-
word := wordUnderCursor(line, &params.Position)
95-
if word == "" {
95+
commandName := h.parser.extractCommandReference(doc, params.Position)
96+
if commandName == "" {
97+
h.parser.log.Debugf("no command reference resolved at %s:%d:%d", path, params.Position.Line, params.Position.Character)
9698
return nil, nil
9799
}
98100

99-
command := h.parser.findCommand(doc, word)
101+
command := h.parser.findCommand(doc, commandName)
100102
if command == nil {
103+
h.parser.log.Debugf("command reference %q did not match any local command", commandName)
101104
return nil, nil
102105
}
103106

107+
h.parser.log.Debugf(
108+
"resolved command definition %q -> %s:%d:%d",
109+
commandName,
110+
path,
111+
command.position.Line,
112+
command.position.Character,
113+
)
114+
104115
// TODO: theoretically we can have multiple commands with the same name if we have mixins
105116
return []lsp.Location{
106117
{
@@ -159,13 +170,22 @@ func (s *lspServer) textDocumentDefinition(context *glsp.Context, params *lsp.De
159170
doc := s.storage.GetDocument(params.TextDocument.URI)
160171

161172
p := newParser(s.log)
162-
163-
switch p.getPositionType(doc, params.Position) {
173+
positionType := p.getPositionType(doc, params.Position)
174+
s.log.Debugf(
175+
"definition request uri=%s line=%d char=%d type=%s",
176+
normalizePath(params.TextDocument.URI),
177+
params.Position.Line,
178+
params.Position.Character,
179+
positionType,
180+
)
181+
182+
switch positionType {
164183
case PositionTypeMixins:
165184
return definitionHandler.findMixinsDefinition(doc, params)
166-
case PositionTypeDepends:
185+
case PositionTypeDepends, PositionTypeCommandAlias:
167186
return definitionHandler.findCommandDefinition(doc, params)
168187
default:
188+
s.log.Debugf("definition request ignored: unsupported cursor position")
169189
return nil, nil
170190
}
171191
}

internal/lsp/server.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package lsp
33
import (
44
"context"
55

6+
"github.com/lets-cli/lets/internal/env"
67
"github.com/tliron/commonlog"
78
_ "github.com/tliron/commonlog/simple"
89
lsp "github.com/tliron/glsp/protocol_3_16"
@@ -24,8 +25,22 @@ func (s *lspServer) Run() error {
2425
return s.server.RunStdio()
2526
}
2627

28+
func lspLogVerbosity() int {
29+
verbosity := 1
30+
31+
defer func() {
32+
_ = recover()
33+
}()
34+
35+
if env.DebugLevel() > 0 {
36+
verbosity = 2
37+
}
38+
39+
return verbosity
40+
}
41+
2742
func Run(ctx context.Context, version string) error {
28-
commonlog.Configure(1, nil)
43+
commonlog.Configure(lspLogVerbosity(), nil)
2944

3045
logger := commonlog.GetLogger(lsName)
3146
logger.Infof("Lets LSP server starting %s", version)

0 commit comments

Comments
 (0)