Skip to content

Improve handling configuration settings #439

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 22, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions R/completion.R
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ completion_reply <- function(id, uri, workspace, document, point, capabilities)

t0 <- Sys.time()
snippet_support <- isTRUE(capabilities$completionItem$snippetSupport) &&
getOption("languageserver.snippet_support", TRUE)
lsp_settings$get("snippet_support")

token_result <- document$detect_token(point, forward = FALSE)

Expand Down Expand Up @@ -502,7 +502,7 @@ completion_reply <- function(id, uri, workspace, document, point, capabilities)
}

init_count <- length(completions)
nmax <- getOption("languageserver.max_completions", 200)
nmax <- lsp_settings$get("max_completions")

if (init_count > nmax) {
isIncomplete <- TRUE
Expand Down
2 changes: 1 addition & 1 deletion R/diagnostics.R
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ diagnose_file <- function(uri, content) {
content <- c(content, "")
}

lint_cache <- getOption("languageserver.lint_cache", TRUE)
lint_cache <- lsp_settings$get("lint_cache")
if (lintr_is_new_enough()) {
lints <- lintr::lint(path, cache = lint_cache, text = content)
} else {
Expand Down
4 changes: 2 additions & 2 deletions R/handlers-general.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
on_initialize <- function(self, id, params) {
trace <- params$trace
if (!is.null(trace) && trace %in% c("messages", "verbose")) {
logger$enable_debug()
lsp_settings$set("debug", TRUE)
}

logger$info("session: ", list(
Expand Down Expand Up @@ -36,7 +36,7 @@ on_initialize <- function(self, id, params) {
ServerCapabilities, self$ClientCapabilities)
server_capabilities <- merge_list(
server_capabilities,
getOption("languageserver.server_capabilities"))
lsp_settings$get("server_capabilities"))
self$ServerCapabilities <- server_capabilities
self$deliver(Response$new(id = id, result = list(capabilities = server_capabilities)))
}
Expand Down
4 changes: 2 additions & 2 deletions R/handlers-protocol.R
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
protocol_set_trace <- function(self, id, params) {
value <- params$value
if (value == "off") {
logger$disable_debug()
lsp_settings$set("debug", FALSE)
} else {
logger$enable_debug()
lsp_settings$set("debug", TRUE)
}
}
11 changes: 1 addition & 10 deletions R/handlers-workspace.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,7 @@ workspace_did_change_configuration <- function(self, params) {

logger$info("settings ", settings)

debug <- settings$debug
if (isTRUE(debug) || is.character(debug)) {
log_file <- if (is.character(debug)) debug else NULL
logger$enable_debug(file = log_file)
}

if (!is.null(settings$diagnostics) && !isTRUE(settings$diagnostics)) {
logger$info("disable diagnostics")
self$run_lintr <- FALSE
}
lsp_settings$update_from_workspace(settings)
}

#' `workspace/didChangeWatchedFiles` notification handler
Expand Down
14 changes: 8 additions & 6 deletions R/languageserver.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ LanguageServer <- R6::R6Class("LanguageServer",
documents = NULL,
workspace = NULL,

run_lintr = TRUE,

processId = NULL,
rootUri = NULL,
rootPath = NULL,
Expand Down Expand Up @@ -104,7 +102,7 @@ LanguageServer <- R6::R6Class("LanguageServer",
))
}

if (run_lintr && self$run_lintr) {
if (run_lintr && lsp_settings$get("diagnostics")) {
temp_root <- dirname(tempdir())
if (path_has_parent(self$rootPath, temp_root) ||
!path_has_parent(path_from_uri(uri), temp_root)) {
Expand Down Expand Up @@ -249,9 +247,13 @@ LanguageServer$set("public", "register_handlers", function() {
run <- function(debug = FALSE, host = "localhost", port = NULL) {
tools::Rd2txt_options(underline_titles = FALSE)
tools::Rd2txt_options(itemBullet = "* ")
if (isTRUE(debug) || is.character(debug)) {
log_file <- if (is.character(debug)) debug else NULL
logger$enable_debug(file = log_file)
lsp_settings$update_from_options()
if (isTRUE(debug)) {
lsp_settings$set("debug", TRUE)
lsp_settings$set("log_file", NULL)
} else if (is.character(debug)) {
lsp_settings$set("debug", TRUE)
lsp_settings$set("log_file", debug)
}
langserver <- LanguageServer$new(host, port)
langserver$run()
Expand Down
2 changes: 1 addition & 1 deletion R/link.R
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ document_link_resolve_reply <- function(id, workspace, params) {
path <- params$data$path
file_size <- file.size(path)
if (is.finite(file_size)) {
link_file_size_limit <- getOption("languageserver.link_file_size_limit", 16 * 1024^2)
link_file_size_limit <- lsp_settings$get("link_file_size_limit")
if (file_size <= link_file_size_limit) {
params$target <- path_to_uri(path)
params$data <- NULL
Expand Down
24 changes: 7 additions & 17 deletions R/log.R
Original file line number Diff line number Diff line change
Expand Up @@ -35,34 +35,24 @@ to_string <- function(...) {
#' @param ... anything
#'
#' @keywords internal
log_write <- function(..., file = stderr()) {
log_write <- function(..., log_file = NULL) {
if (is.null(log_file)) {
log_file <- stderr()
}
txt <- paste0("[", format(Sys.time(), "%Y-%m-%d %H:%M:%OS3"), "] ", to_string(...))
writeLines(txt, file, sep = "", useBytes = TRUE)
writeLines(txt, log_file, sep = "", useBytes = TRUE)
}

#' A basic logger class
#'
#' @keywords internal
Logger <- R6::R6Class("Logger",
private = list(
debug = FALSE,
file = stderr()
),
public = list(
enable_debug = function(file = NULL) {
private$debug <- TRUE
if (!is.null(file)) {
private$file <- file
}
},
disable_debug = function() {
private$debug <- FALSE
},
error = function(...) {
log_write(..., file = private$file)
log_write(..., log_file = lsp_settings$get("log_file"))
},
info = function(...) {
if (private$debug) log_write(..., file = private$file)
if (lsp_settings$get("debug")) log_write(..., log_file = lsp_settings$get("log_file"))
}
)
)
Expand Down
50 changes: 50 additions & 0 deletions R/settings.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
Settings <- R6::R6Class("Settings",
private = list(
settings = list(
debug = FALSE,
log_file = NULL,
diagnostics = TRUE,
rich_documentation = TRUE,
snippet_support = TRUE,
max_completions = 200,
lint_cache = TRUE,
server_capabilities = list(),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we should have an individual switch for each provider rather than to expose the capabilities.

link_file_size_limit = 16L * 1024L^2
)
),
public = list(
update_from_options = function() {
# update default settings
for (key in names(private$settings)) {
prefixed_key <- paste0("languageserver.", key)
if (hasName(options(), prefixed_key)) {
value <- getOption(prefixed_key)
logger$info("Update setting", key, "to", value)
self$set(key, value)
}
}
},
update_from_workspace = function(settings) {
setting_keys <- names(settings)
for (key in setting_keys) {
prefixed_key <- paste0("languageserver.", key)
if (hasName(options(), prefixed_key)) {
logger$info("Setting", key, "is masked by options(...).")
} else {
self$set(key, settings[[key]])
}
}
},
get = function(key) {
return(private$settings[[key]])
},
set = function(key, value) {
private$settings[[key]] <- value
return(self)
}
)
)


# create the settings object
lsp_settings <- Settings$new()
5 changes: 3 additions & 2 deletions R/workspace.R
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,9 @@ Workspace <- R6::R6Class("Workspace",
} else {
result <- NULL

if (requireNamespace("rmarkdown", quietly = TRUE) &&
rmarkdown::pandoc_available()) {
if (lsp_settings$get("rich_documentation") &&
requireNamespace("rmarkdown", quietly = TRUE) &&
rmarkdown::pandoc_available()) {
html <- enc2utf8(repr::repr_html(hfile))
# Make header look prettier:
pattern <- "<table.*?<td>(.*?)\\s*{(.*?)}<\\/td>.*?<\\/table>\\n*<h2>\\s*(.*?)\\s*<\\/h2>"
Expand Down
49 changes: 30 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,22 +109,27 @@ These editors are supported by installing the corresponding package.

## Settings

`languageserver` exposes the following settings via `workspace/didChangeConfiguration`
`languageserver` exposes the following settings via LSP configuration.

settings | default | description
---- | ----- | -----
`debug` | `false` | increase verbosity for debug purpose
`log_file` | `nil` | file to log debug messages, fallback to stderr if empty
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is nil, not null?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. Too much golang this week.

`diagnostics` | `true` | enable file diagnostics via [lintr](https://github.com/jimhester/lintr)
`rich_documentation` | `true` | rich documentation with enhanced markdown features
`snippet_support` | `true` | enable snippets in auto completion
`max_completions` | 200 | maximum number of completion items
`lint_cache` | `true` | toggle caching of lint results
`server_capabilities` | `{}` | override server capabilities defined in [capabilities.R](https://github.com/REditorSupport/languageserver/blob/master/R/capabilities.R). See FAQ below.
`link_file_size_limit` | 16384 | maximum file size (in bytes) that supports document links

These settings could also specified in `.Rprofile` file via `options(languageserver.<SETTING_NAME> = <VALUE>)`. For example,

```json
{
"r.lsp.debug": {
"type": "boolean",
"default": false,
"description": "Debug R Language Server"
},
"r.lsp.diagnostics": {
"type": "boolean",
"default": true,
"description": "Enable Diagnostics"
}
}
```r
options(languageserver.snippet_support = FALSE)
```
will turn off snippet support globally. LSP configuration settings are always overriden by `options()`.


## FAQ

Expand All @@ -134,9 +139,17 @@ With [lintr](https://github.com/jimhester/lintr) v2.0.0, the linters can be spec

### Customizing server capbabilities

Server capabilities are defined in [capabilities.R](https://github.com/REditorSupport/languageserver/blob/master/R/capabilities.R). Users could override the settings by specifiying `languageserver.server_capabilities` option in `.Rprofile`. For example,
the following code will turn off `definitionProvider`,

Server capabilities are defined in
[capabilities.R](https://github.com/REditorSupport/languageserver/blob/master/R/capabilities.R).
Users could override the capabilities by specifying the LSP configuration setting
`server_capabilities` or
`options(languageserver.server_capabilities)` in `.Rprofile`. For example, to turn off `definitionProvider`, one could either use LSP configuration
```json
"server_capabilities": {
"definitionProvider": false
}
```
or R options
```r
options(
languageserver.server_capabilities = list(
Expand All @@ -145,8 +158,6 @@ options(
)
```

Please only use this option to disable providers and do not enable any providers that have not been implemented. Changing any other entries may cause unexpected behaviors on the server.

### Customizing formatting style

The language server uses [`styler`](https://github.com/r-lib/styler) to perform code formatting. It uses `styler::tidyverse_style(indent_by = options$tabSize)` as the default style where `options` is the [formatting
Expand Down
2 changes: 1 addition & 1 deletion man/log_write.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.