Skip to content

Commit c6fcd1a

Browse files
committed
feat: add code-action quickfix
fix: do not use struct for missing attributes
1 parent c553330 commit c6fcd1a

File tree

4 files changed

+61
-0
lines changed

4 files changed

+61
-0
lines changed

internal/decoder/validations/missing_required_attribute.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ func (mra MissingRequiredAttribute) Visit(ctx context.Context, node hclsyntax.No
4949
Summary: fmt.Sprintf("Required attribute %q not specified", name),
5050
Detail: fmt.Sprintf("An attribute named %q is required here", name),
5151
Subject: nodeType.SrcRange.Ptr(),
52+
Extra: map[string]interface{}{
53+
"MissingAttribute": name,
54+
},
5255
})
56+
5357
}
5458
}
5559
}

internal/langserver/handlers/code_action.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,60 @@ func (svc *service) textDocumentCodeAction(ctx context.Context, params lsp.CodeA
7474
},
7575
},
7676
})
77+
case ilsp.Quickfix:
78+
79+
var extractedMissingAttrs []string
80+
81+
for _, diag := range params.Context.Diagnostics {
82+
diagExtra, ok := diag.Data.(map[string]interface{})
83+
if !ok {
84+
svc.logger.Printf("Diagnostic Data does not have the expected type, skipping")
85+
continue
86+
}
87+
missingAttributeRaw, found := diagExtra["MissingAttribute"]
88+
if !found {
89+
continue
90+
}
91+
missingAttribute, ok := missingAttributeRaw.(string)
92+
if !ok {
93+
svc.logger.Printf("MissingAttribute does not have the expected type, skipping")
94+
continue
95+
}
96+
extractedMissingAttrs = append(extractedMissingAttrs, missingAttribute)
97+
}
98+
99+
if len(extractedMissingAttrs) == 0 {
100+
svc.logger.Printf("No missing attributes found")
101+
return ca, err
102+
}
103+
104+
var edits []lsp.TextEdit
105+
106+
rng := params.Range
107+
rng.Start.Line = rng.End.Line
108+
rng.Start.Character = 0
109+
rng.End.Character = 0
110+
111+
newText := ""
112+
113+
for _, missingAttr := range extractedMissingAttrs {
114+
newText = newText + fmt.Sprintf(" %s = null\n", missingAttr)
115+
}
116+
117+
edits = append(edits, lsp.TextEdit{
118+
Range: rng,
119+
NewText: newText,
120+
})
121+
122+
ca = append(ca, lsp.CodeAction{
123+
Title: "Add missing attributes",
124+
Kind: action,
125+
Edit: lsp.WorkspaceEdit{
126+
Changes: map[lsp.DocumentURI][]lsp.TextEdit{
127+
lsp.DocumentURI(dh.FullURI()): edits,
128+
},
129+
},
130+
})
77131
}
78132
}
79133

internal/lsp/code_actions.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
const (
1313
// SourceFormatAllTerraform is a Terraform specific format code action.
1414
SourceFormatAllTerraform = "source.formatAll.terraform"
15+
Quickfix = "quickfix"
1516
)
1617

1718
type CodeActions map[lsp.CodeActionKind]bool
@@ -35,6 +36,7 @@ var (
3536
// files to be formatted, but not terraform files (or vice versa).
3637
SupportedCodeActions = CodeActions{
3738
SourceFormatAllTerraform: true,
39+
Quickfix: true,
3840
}
3941
)
4042

internal/lsp/diagnostics.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ func HCLDiagsToLSP(hclDiags hcl.Diagnostics, source string) []lsp.Diagnostic {
3838
Severity: HCLSeverityToLSP(hclDiag.Severity),
3939
Source: source,
4040
Message: msg,
41+
Data: hclDiag.Extra,
4142
})
4243

4344
}

0 commit comments

Comments
 (0)