Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ All notable changes to the Docker Language Server will be documented in this fil
- textDocument/documentLink
- add anchor resolution for all supported document links ([#348](https://github.com/docker/docker-language-server/issues/348))
- return document links for the `file` attribute of a service object's `extends` attribute object ([#172](https://github.com/docker/docker-language-server/issues/172))
- textDocument/hover
- support hovering over referenced models ([#343](https://github.com/docker/docker-language-server/issues/343))

### Fixed

Expand Down
54 changes: 34 additions & 20 deletions internal/compose/hover.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ func Hover(ctx context.Context, params *protocol.HoverParams, doc document.Compo
if result != nil {
return result, nil
}
result = modelHover(doc, mappingNode, nodePath)
if result != nil {
return result, nil
}
result = hover(composeSchema, nodePath, line, character, len(lines[params.Position.Line])+1)
if result != nil {
return result, nil
Expand Down Expand Up @@ -149,26 +153,6 @@ func networkHover(doc document.ComposeDocument, mappingNode *ast.MappingNode, no
return nil
}

func createDependencyHover(doc document.ComposeDocument, mappingNode *ast.MappingNode, hovered *token.Token, dependencyType, dependencyName string) *protocol.Hover {
for _, node := range mappingNode.Values {
if s, ok := node.Key.(*ast.StringNode); ok && s.Value == dependencyType {
if mappingNode, ok := node.Value.(*ast.MappingNode); ok {
for _, service := range mappingNode.Values {
if service.Key.GetToken().Value == dependencyName {
return createYamlHover(service, hovered)
}
}
}
}
}

node, _ := dependencyLookup(doc, dependencyType, dependencyName)
if node != nil {
return createYamlHover(node, hovered)
}
return nil
}

func configHover(doc document.ComposeDocument, mappingNode *ast.MappingNode, nodePath []ast.Node) *protocol.Hover {
if len(nodePath) == 4 && nodePath[0].GetToken().Value == "services" {
// array string
Expand Down Expand Up @@ -249,6 +233,36 @@ func volumeHover(doc document.ComposeDocument, params *protocol.HoverParams, map
return nil
}

func modelHover(doc document.ComposeDocument, mappingNode *ast.MappingNode, nodePath []ast.Node) *protocol.Hover {
if len(nodePath) == 4 && nodePath[0].GetToken().Value == "services" {
if nodePath[2].GetToken().Value == "models" {
t := nodePath[3].GetToken()
return createDependencyHover(doc, mappingNode, t, "models", t.Value)
}
}
return nil
}

func createDependencyHover(doc document.ComposeDocument, mappingNode *ast.MappingNode, hovered *token.Token, dependencyType, dependencyName string) *protocol.Hover {
for _, node := range mappingNode.Values {
if s, ok := node.Key.(*ast.StringNode); ok && s.Value == dependencyType {
if mappingNode, ok := node.Value.(*ast.MappingNode); ok {
for _, service := range mappingNode.Values {
if service.Key.GetToken().Value == dependencyName {
return createYamlHover(service, hovered)
}
}
}
}
}

node, _ := dependencyLookup(doc, dependencyType, dependencyName)
if node != nil {
return createYamlHover(node, hovered)
}
return nil
}

func hover(schema *jsonschema.Schema, nodes []ast.Node, line, column, lineLength int) *protocol.Hover {
for _, match := range nodes {
if schema.Ref != nil {
Expand Down
83 changes: 83 additions & 0 deletions internal/compose/hover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,89 @@ services:
character: 10,
result: nil,
},
{
name: "models hover with a single item",
content: `
services:
app:
models:
- ai_model

models:
ai_model:
model: ai/model`,
line: 4,
character: 12,
result: &protocol.Hover{
Contents: protocol.MarkupContent{
Kind: protocol.MarkupKindMarkdown,
Value: "```YAML\n" + `ai_model:
model: ai/model` +
"\n```",
},
Range: &protocol.Range{
Start: protocol.Position{Line: 4, Character: 8},
End: protocol.Position{Line: 4, Character: 16},
},
},
},
{
name: "models hover with multiple items",
content: `
services:
app:
models:
- model1
- model2

models:
model1:
model: ai/model
model2:
model: ai/all-minilm`,
line: 5,
character: 12,
result: &protocol.Hover{
Contents: protocol.MarkupContent{
Kind: protocol.MarkupKindMarkdown,
Value: "```YAML\n" + `model2:
model: ai/all-minilm` +
"\n```",
},
Range: &protocol.Range{
Start: protocol.Position{Line: 5, Character: 8},
End: protocol.Position{Line: 5, Character: 14},
},
},
},
{
name: "models hover on an object reference",
content: `
services:
test:
models:
my_model:
endpoint_var: MODEL_URL
model_var: MODEL

models:
my_model:
model: ai/model`,
line: 4,
character: 12,
result: &protocol.Hover{
Contents: protocol.MarkupContent{
Kind: protocol.MarkupKindMarkdown,
Value: "```YAML\n" + `my_model:
model: ai/model` +
"\n```",
},
Range: &protocol.Range{
Start: protocol.Position{Line: 4, Character: 6},
End: protocol.Position{Line: 4, Character: 14},
},
},
},
}

composeFile := fmt.Sprintf("file:///%v", strings.TrimPrefix(filepath.ToSlash(filepath.Join(os.TempDir(), "compose.yaml")), "/"))
Expand Down
Loading