-
Notifications
You must be signed in to change notification settings - Fork 7
/
complete.go
76 lines (71 loc) · 2.62 KB
/
complete.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package complete
import (
"fmt"
"log"
"strings"
"github.com/Azure/azapi-lsp/internal/langserver/handlers/tfschema"
ilsp "github.com/Azure/azapi-lsp/internal/lsp"
"github.com/Azure/azapi-lsp/internal/parser"
lsp "github.com/Azure/azapi-lsp/internal/protocol"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
)
func CandidatesAtPos(data []byte, filename string, pos hcl.Pos, logger *log.Logger) []lsp.CompletionItem {
file, _ := hclsyntax.ParseConfig(data, filename, hcl.InitialPos)
body, isHcl := file.Body.(*hclsyntax.Body)
if !isHcl {
logger.Printf("file is not hcl")
return nil
}
block := parser.BlockAtPos(body, pos)
candidateList := make([]lsp.CompletionItem, 0)
if block != nil && len(block.Labels) != 0 && strings.HasPrefix(block.Labels[0], "azapi") {
resourceName := fmt.Sprintf("%s.%s", block.Type, block.Labels[0])
resource := tfschema.GetResourceSchema(resourceName)
if resource == nil {
return candidateList
}
if attribute := parser.AttributeAtPos(block, pos); attribute != nil {
property := resource.GetProperty(attribute.Name)
if property != nil {
if property.GenericCandidatesFunc != nil {
candidateList = append(candidateList, property.GenericCandidatesFunc(data, filename, block, attribute, pos, property)...)
} else if property.ValueCandidatesFunc != nil {
prefix := parser.ToLiteral(attribute.Expr)
candidateList = append(candidateList, property.ValueCandidatesFunc(prefix, editRangeFromExprRange(attribute.Expr, pos))...)
}
}
} 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 && p.ValueCandidatesFunc != nil {
candidateList = append(candidateList, p.ValueCandidatesFunc(nil, editRangeFromExprRange(attribute.Expr, pos))...)
break
}
}
}
} else {
//input a top level property
editRange := lsp.Range{
Start: ilsp.HCLPosToLSP(pos),
End: ilsp.HCLPosToLSP(pos),
}
editRange.Start.Character = 2
candidateList = append(candidateList, tfschema.PropertiesCandidates(resource.Properties, editRange)...)
}
}
}
return candidateList
}
func editRangeFromExprRange(expression hclsyntax.Expression, pos hcl.Pos) lsp.Range {
expRange := expression.Range()
if expRange.Start.Line != expRange.End.Line && expRange.End.Column == 1 && expRange.End.Line-1 == pos.Line {
expRange.End = pos
}
return ilsp.HCLRangeToLSP(expRange)
}