From c6fcd1ae07a22a87220bfadcb5ee4eef9797b468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Andrieux?= Date: Tue, 2 Jan 2024 17:37:44 +0100 Subject: [PATCH 1/2] feat: add code-action quickfix fix: do not use struct for missing attributes --- .../validations/missing_required_attribute.go | 4 ++ internal/langserver/handlers/code_action.go | 54 +++++++++++++++++++ internal/lsp/code_actions.go | 2 + internal/lsp/diagnostics.go | 1 + 4 files changed, 61 insertions(+) diff --git a/internal/decoder/validations/missing_required_attribute.go b/internal/decoder/validations/missing_required_attribute.go index 4485d68b..5b485899 100644 --- a/internal/decoder/validations/missing_required_attribute.go +++ b/internal/decoder/validations/missing_required_attribute.go @@ -49,7 +49,11 @@ func (mra MissingRequiredAttribute) Visit(ctx context.Context, node hclsyntax.No Summary: fmt.Sprintf("Required attribute %q not specified", name), Detail: fmt.Sprintf("An attribute named %q is required here", name), Subject: nodeType.SrcRange.Ptr(), + Extra: map[string]interface{}{ + "MissingAttribute": name, + }, }) + } } } diff --git a/internal/langserver/handlers/code_action.go b/internal/langserver/handlers/code_action.go index e062eec7..90709dc8 100644 --- a/internal/langserver/handlers/code_action.go +++ b/internal/langserver/handlers/code_action.go @@ -74,6 +74,60 @@ func (svc *service) textDocumentCodeAction(ctx context.Context, params lsp.CodeA }, }, }) + case ilsp.Quickfix: + + var extractedMissingAttrs []string + + for _, diag := range params.Context.Diagnostics { + diagExtra, ok := diag.Data.(map[string]interface{}) + if !ok { + svc.logger.Printf("Diagnostic Data does not have the expected type, skipping") + continue + } + missingAttributeRaw, found := diagExtra["MissingAttribute"] + if !found { + continue + } + missingAttribute, ok := missingAttributeRaw.(string) + if !ok { + svc.logger.Printf("MissingAttribute does not have the expected type, skipping") + continue + } + extractedMissingAttrs = append(extractedMissingAttrs, missingAttribute) + } + + if len(extractedMissingAttrs) == 0 { + svc.logger.Printf("No missing attributes found") + return ca, err + } + + var edits []lsp.TextEdit + + rng := params.Range + rng.Start.Line = rng.End.Line + rng.Start.Character = 0 + rng.End.Character = 0 + + newText := "" + + for _, missingAttr := range extractedMissingAttrs { + newText = newText + fmt.Sprintf(" %s = null\n", missingAttr) + } + + edits = append(edits, lsp.TextEdit{ + Range: rng, + NewText: newText, + }) + + ca = append(ca, lsp.CodeAction{ + Title: "Add missing attributes", + Kind: action, + Edit: lsp.WorkspaceEdit{ + Changes: map[lsp.DocumentURI][]lsp.TextEdit{ + lsp.DocumentURI(dh.FullURI()): edits, + }, + }, + }) } } diff --git a/internal/lsp/code_actions.go b/internal/lsp/code_actions.go index b4dc6bf6..c08429c1 100644 --- a/internal/lsp/code_actions.go +++ b/internal/lsp/code_actions.go @@ -12,6 +12,7 @@ import ( const ( // SourceFormatAllTerraform is a Terraform specific format code action. SourceFormatAllTerraform = "source.formatAll.terraform" + Quickfix = "quickfix" ) type CodeActions map[lsp.CodeActionKind]bool @@ -35,6 +36,7 @@ var ( // files to be formatted, but not terraform files (or vice versa). SupportedCodeActions = CodeActions{ SourceFormatAllTerraform: true, + Quickfix: true, } ) diff --git a/internal/lsp/diagnostics.go b/internal/lsp/diagnostics.go index 656652ea..bbe5bb6c 100644 --- a/internal/lsp/diagnostics.go +++ b/internal/lsp/diagnostics.go @@ -38,6 +38,7 @@ func HCLDiagsToLSP(hclDiags hcl.Diagnostics, source string) []lsp.Diagnostic { Severity: HCLSeverityToLSP(hclDiag.Severity), Source: source, Message: msg, + Data: hclDiag.Extra, }) } From 6431c57bdf65a485b17ae94b5a0c52b8bc0bc56d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Andrieux?= Date: Thu, 4 Jan 2024 21:10:19 +0100 Subject: [PATCH 2/2] fix: add quickfix to expected codeActionKinds --- internal/langserver/handlers/handlers_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/langserver/handlers/handlers_test.go b/internal/langserver/handlers/handlers_test.go index fa8d8b24..d4f1ff22 100644 --- a/internal/langserver/handlers/handlers_test.go +++ b/internal/langserver/handlers/handlers_test.go @@ -51,7 +51,7 @@ func initializeResponse(t *testing.T, commandPrefix string) string { "referencesProvider": true, "documentSymbolProvider": true, "codeActionProvider": { - "codeActionKinds": ["source.formatAll.terraform"] + "codeActionKinds": ["quickfix", "source.formatAll.terraform"] }, "codeLensProvider": {}, "documentLinkProvider": {},