diff --git a/R/capabilities.R b/R/capabilities.R index 19f8db7b..abc4d103 100644 --- a/R/capabilities.R +++ b/R/capabilities.R @@ -58,7 +58,7 @@ ServerCapabilities <- list( documentHighlightProvider = TRUE, documentSymbolProvider = TRUE, workspaceSymbolProvider = TRUE, - # codeActionProvider = FALSE, + codeActionProvider = TRUE, # codeLensProvider = CodeLensOptions, documentFormattingProvider = TRUE, documentRangeFormattingProvider = TRUE, diff --git a/R/code_action.R b/R/code_action.R new file mode 100644 index 00000000..de2cb783 --- /dev/null +++ b/R/code_action.R @@ -0,0 +1,66 @@ +CodeActionKind <- list( + Empty = "", + QuickFix = "quickfix", + Refactor = "refactor", + RefactorExtract = "refactor.extract", + RefactorInline = "refactor.inline", + RefactorRewrite = "refactor.rewrite", + Source = "source", + SourceOrganizeImports = "source.organizeImports" +) + +#' The response to a textDocument/codeAction Request +#' +#' @keywords internal +document_code_action_reply <- function(id, uri, workspace, document, range, context) { + # result <- NULL + + # if (is.null(document$diagnostics) || + # (!is.null(document$diagnostics$version) && document$diagnostics$version != document$version)) { + # return(NULL) + # } + + # diagnostics <- document$diagnostics$data + + result <- list() + + for (item in context$diagnostics) { + if (length(item$data$fix) == 0) next + item_range <- list( + start = document$from_lsp_position(item$range$start), + end = document$from_lsp_position(item$range$end) + ) + logger$info(item_range) + text <- get_range_text( + document$content, + item_range$start$row + 1, item_range$start$col + 1, + item_range$end$row + 1, item_range$end$col + ) + changes <- list( + list( + text_edit(range = item$range, new_text = item$data$fix) + ) + ) + names(changes) <- uri + action <- list( + title = sprintf("Replace '%s' with '%s'", + text, + item$data$fix + ), + kind = CodeActionKind$QuickFix, + edit = list( + changes = changes + ) + ) + result <- c(result, list(action)) + } + + logger$info("document_code_action_reply: ", list( + uri = uri, + range = range, + context = context, + result = result + )) + + Response$new(id, result = result) +} diff --git a/R/diagnostics.R b/R/diagnostics.R index 17c4f099..4fd6e5cb 100644 --- a/R/diagnostics.R +++ b/R/diagnostics.R @@ -50,7 +50,10 @@ diagnostic_from_lint <- function(result, content) { range = diagnostic_range(result, content), severity = diagnostic_severity(result), source = result$linter, - message = result$message + message = result$message, + data = list( + fix = result$fix + ) ) } @@ -103,12 +106,12 @@ diagnose_file <- function(uri, content) { diagnostics_callback <- function(self, uri, version, diagnostics) { if (is.null(diagnostics) || !self$workspace$documents$has(uri)) return(NULL) logger$info("diagnostics_callback called:", list(uri = uri, version = version)) - # logger$info("diagnostics:", diagnostics) self$deliver( Notification$new( method = "textDocument/publishDiagnostics", params = list( uri = uri, + version = version, diagnostics = diagnostics ) ) diff --git a/R/handlers-langfeatures.R b/R/handlers-langfeatures.R index ea99398f..84e36839 100644 --- a/R/handlers-langfeatures.R +++ b/R/handlers-langfeatures.R @@ -126,7 +126,16 @@ text_document_document_symbol <- function(self, id, params) { #' Handler to the `textDocument/codeAction` [Request]. #' @keywords internal text_document_code_action <- function(self, id, params) { - + logger$info("text_document_code_action: ", params) + textDocument <- params$textDocument + uri <- uri_escape_unicode(textDocument$uri) + document <- self$workspace$documents$get(uri) + range <- list( + start = document$from_lsp_position(params$range$start), + end = document$from_lsp_position(params$range$end) + ) + context <- params$context + self$deliver(document_code_action_reply(id, uri, self$workspace, document, range, context)) } #' `textDocument/codeLens` request handler diff --git a/R/languageserver.R b/R/languageserver.R index 6c5c0834..555c8f99 100644 --- a/R/languageserver.R +++ b/R/languageserver.R @@ -207,6 +207,7 @@ LanguageServer$set("public", "register_handlers", function() { `textDocument/documentHighlight` = text_document_document_highlight, `textDocument/documentLink` = text_document_document_link, `textDocument/documentColor` = text_document_document_color, + `textDocument/codeAction` = text_document_code_action, `textDocument/colorPresentation` = text_document_color_presentation, `textDocument/foldingRange` = text_document_folding_range, `textDocument/references` = text_document_references, diff --git a/README.md b/README.md index 5387cfb6..a152d993 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ These editors are supported by installing the corresponding package. - [x] [documentHighlightProvider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight) - [x] [documentSymbolProvider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol) - [x] [workspaceSymbolProvider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_symbol) -- [ ] [codeActionProvider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction) +- [x] [codeActionProvider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction) - [ ] [codeLensProvider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeLens) - [x] [documentFormattingProvider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting) - [x] [documentRangeFormattingProvider](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rangeFormatting)