internal/langserver/handlers/snippets/snippets_gen.go (134 lines of code) (raw):

package snippets import ( "fmt" "os" "strings" "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hclsyntax" "golang.org/x/exp/slices" ) func parseSnippet(filepath string) (*Snippet, error) { // #nosec G304 data, err := os.ReadFile(filepath) if err != nil { return nil, err } file, diags := hclsyntax.ParseConfig(data, filepath, hcl.InitialPos) if diags.HasErrors() { return nil, diags } blocks := file.Body.(*hclsyntax.Body).Blocks if len(blocks) == 0 { return nil, fmt.Errorf("no block found in %s", filepath) } addrTypeMap := make(map[string]string) for _, block := range blocks { if block.Type == "resource" || block.Type == "data" { typeValue := "" for _, attr := range block.Body.Attributes { if attr.Name == "type" { typeValue = strings.Trim(stringValue(data, attr.Expr.Range()), `"`) break } } addr := strings.Join(block.Labels, ".") if block.Type == "data" { addr = "data." + addr } addrTypeMap[addr] = typeValue } } lastBlock := blocks[len(blocks)-1] if lastBlock.Labels[0] != "azapi_resource" { // skip non azapi_resource block return nil, nil } typeValue := "" fields := make([]Field, 0) index := 1 for _, attr := range lastBlock.Body.Attributes { if attr.Name == "type" { typeValue = strings.Trim(stringValue(data, attr.Expr.Range()), `"`) } value := stringValue(data, attr.Range()) vars := attr.Expr.Variables() for _, variable := range vars { rawContent := stringValue(data, variable.SourceRange()) placeholder := placeholderContent(rawContent, addrTypeMap) format := `${%d:"%s"}` if attr.Name == "name" || attr.Name == "location" { format = `"${%d:%s}"` } value = strings.ReplaceAll(value, rawContent, fmt.Sprintf(format, index, placeholder)) index++ } fields = append(fields, Field{ Name: attr.Name, Value: value, }) } for _, block := range lastBlock.Body.Blocks { value := stringValue(data, block.Range()) for _, attr := range block.Body.Attributes { vars := attr.Expr.Variables() for _, variable := range vars { rawContent := stringValue(data, variable.SourceRange()) placeholder := placeholderContent(rawContent, addrTypeMap) value = strings.ReplaceAll(value, rawContent, fmt.Sprintf("${%d:%s}", index, placeholder)) index++ } } fields = append(fields, Field{ Name: block.Type, Value: value, }) } slices.SortFunc(fields, func(i, j Field) int { return i.Order() - j.Order() }) return &Snippet{ AzureResourceType: parseResourceType(typeValue), Fields: fields, }, nil } func placeholderContent(content string, typeMap map[string]string) string { out := "TODO" parts := strings.Split(content, ".") if len(parts) == 0 { return out } lastPart := parts[len(parts)-1] if lastPart == "subscription_id" { return "subscription id" } if lastPart == "tenant_id" { return "tenant id" } if lastPart == "output" { return out } switch parts[0] { case "var": if lastPart == "resource_name" { return "The name of the resource" } return lastPart case "local": return lastPart case "data": addr := strings.Join(parts[:len(parts)-1], ".") if typeValue, ok := typeMap[addr]; ok { return fmt.Sprintf("The %s of the %s resource", lastPart, typeValue) } case "azapi_resource", "azapi_resource_action", "azapi_update_resource": addr := strings.Join(parts[:len(parts)-1], ".") if len(parts) == 2 { addr = content } if typeValue, ok := typeMap[addr]; ok { return fmt.Sprintf("The %s of the %s resource", lastPart, typeValue) } } return out } func stringValue(data []byte, h hcl.Range) string { return string(data[h.Start.Byte:h.End.Byte]) }