Skip to content

Commit

Permalink
support hover on the resource def to show the doc
Browse files Browse the repository at this point in the history
  • Loading branch information
ms-henglu committed Jul 10, 2024
1 parent c9b9cee commit 2a4a24f
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 13 deletions.
53 changes: 40 additions & 13 deletions internal/langserver/handlers/hover/hover.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func HoverAtPos(data []byte, filename string, pos hcl.Pos, logger *log.Logger) *
if resource == nil {
return nil
}
// hover on an attribute
if attribute := parser.AttributeAtPos(block, pos); attribute != nil {
property := resource.GetProperty(attribute.Name)
if property == nil {
Expand Down Expand Up @@ -73,21 +74,47 @@ func HoverAtPos(data []byte, filename string, pos hcl.Pos, logger *log.Logger) *
}
return Hover(property.Name, property.Modifier, property.Type, property.Description, attribute.NameRange)
}
} else {
if subBody := parser.BlockAtPos(block.Body, pos); subBody != nil {
property := resource.GetProperty(subBody.Type)
if property == nil {
return nil
}
if attribute := parser.AttributeAtPos(subBody, pos); attribute != nil {
for _, p := range property.NestedProperties {
if p.Name == attribute.Name {
return Hover(p.Name, p.Modifier, p.Type, p.Description, attribute.NameRange)
}
}

// hover on a block
if nestedBlock := parser.BlockAtPos(block.Body, pos); nestedBlock != nil {
property := resource.GetProperty(nestedBlock.Type)
if property == nil {
return nil
}
if attribute := parser.AttributeAtPos(nestedBlock, pos); attribute != nil {
for _, p := range property.NestedProperties {
if p.Name == attribute.Name {
return Hover(p.Name, p.Modifier, p.Type, p.Description, attribute.NameRange)
}
} else {
return Hover(property.Name, property.Modifier, property.Type, property.Description, subBody.TypeRange)
}
} else {
return Hover(property.Name, property.Modifier, property.Type, property.Description, nestedBlock.TypeRange)
}
}

// hover on the resource definition
if block.DefRange().ContainsPos(pos) {
typeValue := ""
if typeAttribute := parser.AttributeWithName(block, "type"); typeAttribute != nil {
if v := parser.ToLiteral(typeAttribute.Expr); v != nil && len(*v) != 0 {
typeValue = *v
}
}
azureResourceType := ""
if parts := strings.Split(typeValue, "@"); len(parts) >= 2 {
azureResourceType = parts[0]
}
if azureResourceType == "" {
return nil
}
return &lsp.Hover{
Range: ilsp.HCLRangeToLSP(block.DefRange()),
Contents: lsp.MarkupContent{
Kind: lsp.Markdown,
Value: fmt.Sprintf(`%s %s '%s'
[View Documentation](https://learn.microsoft.com/en-us/azure/templates/%s?pivots=deployment-language-terraform)`, block.Type, strings.Join(block.Labels, "."), typeValue, strings.ToLower(azureResourceType)),
},
}
}
}
Expand Down
82 changes: 82 additions & 0 deletions internal/langserver/handlers/hover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,88 @@ func TestHover_payload_propInArray(t *testing.T) {
}, string(expectRaw))
}

func TestHover_identity(t *testing.T) {
tmpDir := TempDir(t)
InitPluginCache(t, tmpDir.Dir())

ls := langserver.NewLangServerMock(t, NewMockSession(&MockSessionInput{}))
stop := ls.Start(t)
defer stop()

config, err := os.ReadFile(fmt.Sprintf("./testdata/%s/main.tf", t.Name()))
if err != nil {
t.Fatal(err)
}

expectRaw, err := os.ReadFile(fmt.Sprintf("./testdata/%s/expect.json", t.Name()))
if err != nil {
t.Fatal(err)
}

ls.Call(t, &langserver.CallRequest{
Method: "initialize",
ReqParams: fmt.Sprintf(`{
"capabilities": {},
"rootUri": %q,
"processId": 12345
}`, TempDir(t).URI()),
})
ls.Notify(t, &langserver.CallRequest{
Method: "initialized",
ReqParams: "{}",
})
ls.Call(t, &langserver.CallRequest{
Method: "textDocument/didOpen",
ReqParams: buildReqParamsTextDocument(string(config), tmpDir.URI()),
})

ls.CallAndExpectResponse(t, &langserver.CallRequest{
Method: "textDocument/hover",
ReqParams: buildReqParamsHover(7, 8, tmpDir.URI()),
}, string(expectRaw))
}

func TestHover_resource_title(t *testing.T) {
tmpDir := TempDir(t)
InitPluginCache(t, tmpDir.Dir())

ls := langserver.NewLangServerMock(t, NewMockSession(&MockSessionInput{}))
stop := ls.Start(t)
defer stop()

config, err := os.ReadFile(fmt.Sprintf("./testdata/%s/main.tf", t.Name()))
if err != nil {
t.Fatal(err)
}

expectRaw, err := os.ReadFile(fmt.Sprintf("./testdata/%s/expect.json", t.Name()))
if err != nil {
t.Fatal(err)
}

ls.Call(t, &langserver.CallRequest{
Method: "initialize",
ReqParams: fmt.Sprintf(`{
"capabilities": {},
"rootUri": %q,
"processId": 12345
}`, TempDir(t).URI()),
})
ls.Notify(t, &langserver.CallRequest{
Method: "initialized",
ReqParams: "{}",
})
ls.Call(t, &langserver.CallRequest{
Method: "textDocument/didOpen",
ReqParams: buildReqParamsTextDocument(string(config), tmpDir.URI()),
})

ls.CallAndExpectResponse(t, &langserver.CallRequest{
Method: "textDocument/hover",
ReqParams: buildReqParamsHover(1, 16, tmpDir.URI()),
}, string(expectRaw))
}

func buildReqParamsHover(line int, character int, uri string) string {
param := make(map[string]interface{})
textDocument := make(map[string]interface{})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"contents": {
"kind": "markdown",
"value": "```\ntype: Required(string)\n```\nThe Type of Identity which should be used for this azure resource. Possible values are `SystemAssigned`, `UserAssigned` and `SystemAssigned, UserAssigned`."
},
"range": {
"start": {
"line": 6,
"character": 4
},
"end": {
"line": 6,
"character": 8
}
}
}
}
23 changes: 23 additions & 0 deletions internal/langserver/handlers/testdata/TestHover_identity/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
resource "azapi_resource" "cluster" {
type = "Microsoft.ContainerService/managedClusters@2024-02-01"
parent_id = azapi_resource.resourceGroup.id
name = "example"
location = azapi_resource.resourceGroup.location
identity {
type = "SystemAssigned"
identity_ids = []
}
body = {
properties = {
agentPoolProfiles = [
{
count = 1
mode = "System"
name = "default"
vmSize = "Standard_DS2_v2"
},
]
dnsPrefix = "example"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"contents": {
"kind": "markdown",
"value": "resource azapi_resource.test 'Microsoft.DataFactory/factories@2018-06-01' \n[View Documentation](https://learn.microsoft.com/en-us/azure/templates/microsoft.datafactory/factories?pivots=deployment-language-terraform)"
},
"range": {
"start": {
"line": 0,
"character": 0
},
"end": {
"line": 0,
"character": 34
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
resource "azapi_resource" "test" {
name = "acctest1774"
parent_id = azurerm_batch_account.test.id
type = "Microsoft.DataFactory/factories@2018-06-01"
body = jsonencode({
identity = {
type = "SystemAssigned"
}
properties = {
encryption = {
identity = {

}
}
}
})
}

0 comments on commit 2a4a24f

Please sign in to comment.