lsp-go.el (15507B)
1 ;;; lsp-go.el --- Go Client settings -*- lexical-binding: t; -*- 2 3 ;; Copyright (C) 2019 Muir Manders 4 5 ;; Author: Muir Manders <muir@mnd.rs> 6 ;; Keywords: 7 8 ;; This program is free software; you can redistribute it and/or modify 9 ;; it under the terms of the GNU General Public License as published by 10 ;; the Free Software Foundation, either version 3 of the License, or 11 ;; (at your option) any later version. 12 13 ;; This program is distributed in the hope that it will be useful, 14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 ;; GNU General Public License for more details. 17 18 ;; You should have received a copy of the GNU General Public License 19 ;; along with this program. If not, see <https://www.gnu.org/licenses/>. 20 21 ;;; Commentary: 22 23 ;; lsp-go client 24 25 ;;; Code: 26 27 (require 'lsp-mode) 28 (require 'lsp-completion) 29 30 (defgroup lsp-go nil 31 "LSP support for the Go Programming Language, using the gopls language server." 32 :link '(url-link "https://github.com/golang/tools/blob/master/gopls/README.md") 33 :group 'lsp-mode 34 :package-version '(lsp-mode . "6.3.2")) 35 36 (define-obsolete-variable-alias 37 'lsp-gopls-server-path 38 'lsp-go-gopls-server-path 39 "lsp-mode 7.0.1") 40 41 (defcustom lsp-go-gopls-server-path "gopls" 42 "Path to gopls server binary." 43 :type 'string 44 :group 'lsp-go) 45 46 (define-obsolete-variable-alias 47 'lsp-gopls-server-args 48 'lsp-go-gopls-server-args 49 "lsp-mode 7.0.1") 50 51 (defcustom lsp-go-gopls-server-args '("-remote=auto") 52 "Extra CLI arguments for gopls." 53 :type '(repeat string) 54 :group 'lsp-go) 55 56 (define-obsolete-variable-alias 57 'lsp-gopls-use-placeholders 58 'lsp-go-use-placeholders 59 "lsp-mode 7.0.1") 60 61 (defcustom lsp-go-use-placeholders t 62 "Cause gopls to provide placeholder parameter snippets when 63 completing function calls." 64 :type 'boolean 65 :group 'lsp-go) 66 67 (define-obsolete-variable-alias 68 'lsp-gopls-build-flags 69 'lsp-go-build-flags 70 "lsp-mode 7.0.1") 71 72 (defcustom lsp-go-build-flags [] 73 "A vector of flags passed on to the build system when invoked, 74 applied to queries like `go list'." 75 :type '(lsp-repeatable-vector string) 76 :group 'lsp-go 77 :risky t 78 :package-version '(lsp-mode "6.2")) 79 80 (define-obsolete-variable-alias 81 'lsp-gopls-env 82 'lsp-go-env 83 "lsp-mode 7.0.1") 84 85 (defcustom lsp-go-env nil 86 "`gopls' has the unusual ability to set environment variables, 87 intended to affect the behavior of commands invoked by `gopls' 88 on the user's behalf. This variable takes a hash table of env 89 var names to desired values." 90 :type '(alist :key-type (symbol :tag "env var name") :value-type (string :tag "value")) 91 :group 'lsp-go 92 :risky t 93 :package-version '(lsp-mode "6.2")) 94 95 (defcustom lsp-go-directory-filters [] 96 "A vector of directory filters." 97 :link '(url-link "https://github.com/golang/tools/blob/67e49ef2d0f326051e22a4a55bdf9344ae1a8ed8/gopls/doc/settings.md#directoryfilters-string") 98 :group 'lsp-go 99 :type 'lsp-string-vector 100 :package-version '(lsp-mode "8.0.0")) 101 102 (define-obsolete-variable-alias 103 'lsp-gopls-hover-kind 104 'lsp-go-hover-kind 105 "lsp-mode 7.0.1") 106 107 (defcustom lsp-go-hover-kind "SynopsisDocumentation" 108 "`gopls' allows the end user to select the desired amount of 109 documentation returned during e.g. hover and thing-at-point 110 operations." 111 :type '(choice (const "SynopsisDocumentation") 112 (const "NoDocumentation") 113 (const "FullDocumentation") 114 (const "SingleLine") 115 (const "Structured")) 116 :group 'lsp-go 117 :risky t 118 :package-version '(lsp-mode "6.2")) 119 120 (define-obsolete-variable-alias 121 'lsp-gopls-available-codelens 122 'lsp-go-available-codelenses 123 "lsp-mode 7.0.1") 124 125 (define-obsolete-variable-alias 126 'lsp-go-available-codelens 127 'lsp-go-available-codelenses 128 "lsp-mode 7.0.1") 129 130 (defvar lsp-go-available-codelenses 131 '( 132 (gc_details . "Toggle the calculation of gc annotations") 133 (generate . "Run `go generate` for a directory") 134 (regenerate_cgo . "Regenerate cgo definitions") 135 (test . "Run `go test` for a specific set of test or benchmark functions (legacy)") 136 (tidy . "Run `go mod tidy` for a module") 137 (upgrade_dependency . "Upgrade a dependency") 138 (vendor . "Runs `go mod vendor' for a module")) 139 "Available codelenses that can be further enabled or disabled 140 through `lsp-go-codelenses'.") 141 142 (defun lsp-go--defcustom-available-as-alist-type (alist) 143 "Return a list for the `:type' field in `defcustom' used to populate an alist. 144 145 The input ALIST has the form `((\"name\" . \"documentation sentence\") [...])' 146 147 The returned type provides a tri-state that either: 148 - does not include the element in the alist 149 - sets element to false (actually, :json-false) 150 - sets element to true \(actually, t)" 151 (let ((list '())) 152 (dolist (v alist) 153 (push `(cons 154 :tag ,(cdr v) 155 (const :format "" ,(car v)) 156 (choice (const :tag "Enable" t) (const :tag "Disable" :json-false))) 157 list)) 158 (push 'set list) 159 list)) 160 161 (define-obsolete-variable-alias 162 'lsp-gopls-codelens 163 'lsp-go-codelenses 164 "lsp-mode 7.0.1") 165 166 (define-obsolete-variable-alias 167 'lsp-go-codelens 168 'lsp-go-codelenses 169 "lsp-mode 7.0.1") 170 171 (defcustom lsp-go-codelenses '((gc_details . :json-false) 172 (generate . t) 173 (regenerate_cgo . t) 174 (tidy . t) 175 (upgrade_dependency . t) 176 (test . t) 177 (vendor . t)) 178 "Select what codelenses should be enabled or not. 179 180 The codelenses can be found at https://github.com/golang/tools/blob/3fa0e8f87c1aae0a9adc2a63af1a1945d16d9359/internal/lsp/source/options.go#L106-L112." 181 :type (lsp-go--defcustom-available-as-alist-type lsp-go-available-codelenses) 182 :group 'lsp-go 183 :risky t 184 :package-version '(lsp-mode "7.0")) 185 186 (define-obsolete-variable-alias 187 'lsp-clients-go-library-directories 188 'lsp-go-library-directories 189 "lsp-mode 7.0.1") 190 191 (defcustom lsp-go-library-directories ["/usr"] 192 "List of directories which will be considered to be libraries." 193 :group 'lsp-go 194 :risky t 195 :type '(lsp-repeatable-vector string)) 196 197 (define-obsolete-variable-alias 198 'lsp-clients-go-library-directories-include-go-modules 199 'lsp-go-library-directories-include-go-modules 200 "lsp-mode 7.0.1") 201 202 (defcustom lsp-go-library-directories-include-go-modules t 203 "Whether or not $GOPATH/pkg/mod should be included as a library directory." 204 :type 'boolean 205 :group 'lsp-go) 206 207 (defun lsp-go--library-default-directories (_workspace) 208 "Calculate go library directories. 209 210 If `lsp-go-library-directories-include-go-modules' is non-nil 211 and the environment variable GOPATH is set this function will return 212 $GOPATH/pkg/mod along with the value of 213 `lsp-go-library-directories'." 214 (let ((library-dirs lsp-go-library-directories)) 215 (when (and lsp-go-library-directories-include-go-modules 216 (or (and (not (file-remote-p default-directory)) (executable-find "go")) 217 (and (version<= "27.0" emacs-version) (with-no-warnings (executable-find "go" (file-remote-p default-directory)))))) 218 (with-temp-buffer 219 (when (zerop (process-file "go" nil t nil "env" "GOPATH")) 220 (setq library-dirs 221 (append 222 library-dirs 223 (list 224 (concat 225 (string-trim-right (buffer-substring (point-min) (point-max))) 226 "/pkg/mod"))))))) 227 (if (file-remote-p default-directory) 228 (mapcar (lambda (path) (concat (file-remote-p default-directory) path)) library-dirs) 229 library-dirs))) 230 231 (defcustom lsp-go-link-target "pkg.go.dev" 232 "Which website to use for displaying Go documentation." 233 :type '(choice (const "pkg.go.dev") 234 (const "godoc.org") 235 (string :tag "A custom website")) 236 :group 'lsp-go 237 :package-version '(lsp-mode "7.0.1")) 238 239 (defcustom lsp-go-links-in-hover t 240 "If non-nil, hover documentation includes links." 241 :type 'boolean 242 :group 'lsp-go 243 :package-version '(lsp-mode "8.0.0")) 244 245 (defcustom lsp-go-use-gofumpt nil 246 "If non-nil, use gofumpt formatting." 247 :type 'boolean 248 :group 'lsp-go 249 :package-version '(lsp-mode "8.0.0")) 250 251 (defcustom lsp-go-goimports-local "" 252 "Equivalent of the goimports -local flag, which puts imports beginning with 253 this string after third-party packages. It should be the prefix of the import 254 path whose imports should be grouped separately." 255 :type 'string 256 :group 'lsp-go 257 :package-version '(lsp-mode "8.0.0")) 258 259 (defcustom lsp-go-analyses nil 260 "Specify analyses that the user would like to enable or disable. A map of the 261 names of analysis passes that should be enabled/disabled. A full list of 262 analyzers that gopls uses can be found at 263 https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md" 264 :type '(alist :key-type (string :tag "analyzer name") :value-type (boolean :tag "value")) 265 :group 'lsp-go 266 :risky t 267 :package-version '(lsp-mode "8.0.0")) 268 269 (defcustom lsp-go-import-shortcut "Both" 270 "Specifies whether import statements should link to documentation or go to 271 definitions." 272 :type '(choice (const "Both") 273 (const "Link") 274 (const "Definition")) 275 :group 'lsp-go 276 :risky t 277 :package-version '(lsp-mode "8.0.0")) 278 279 (defcustom lsp-go-symbol-matcher "FastFuzzy" 280 "Sets the algorithm that is used when finding workspace symbols." 281 :type '(choice (const "Fuzzy") 282 (const "FastFuzzy") 283 (const "CaseInsensitive") 284 (const "CaseSensitive")) 285 :group 'lsp-go 286 :risky t 287 :package-version '(lsp-mode "8.0.0")) 288 289 (defcustom lsp-go-symbol-style "Dynamic" 290 "Controls how symbols are qualified in symbol responses. 291 292 `Dynamic' uses whichever qualifier results in the highest scoring match for 293 the given symbol query. Here a `qualifier' is any `/' or '.' delimited suffix 294 of the fully qualified symbol. i.e. `to/pkg.Foo.Field' or just `Foo.Field'. 295 296 `Full' is fully qualified symbols, i.e. `path/to/pkg.Foo.Field'. 297 298 `Package' is package qualified symbols i.e. `pkg.Foo.Field'." 299 :type '(choice (const "Dynamic") 300 (const "Full") 301 (const "Package")) 302 :group 'lsp-go 303 :risky t 304 :package-version '(lsp-mode "8.0.0")) 305 306 (defcustom lsp-go-template-extensions [] 307 "The extensions of file names that are treated as template files. 308 309 The extension is the part of the file name after the final dot." 310 :type '(lsp-repeatable-vector string) 311 :group 'lsp-go 312 :package-version '(lsp-mode "9.1")) 313 314 (defcustom lsp-go-standalone-tags ["ignore"] 315 "Specifies a set of build constraints that identify individual Go 316 source files that make up the entire main package of an 317 executable." 318 :type '(lsp-repeatable-vector string) 319 :group 'lsp-go 320 :package-version '(lsp-mode "9.1")) 321 322 (defcustom lsp-go-completion-budget "100ms" 323 "Soft latency goal for completion requests" 324 :type 'string 325 :group 'lsp-go 326 :package-version '(lsp-mode "9.1")) 327 328 (defcustom lsp-go-matcher "Fuzzy" 329 "Sets the algorithm that is used when calculating completion candidates." 330 :type '(choice (const "CaseInsensitive") 331 (const "CaseSensitive") 332 (const "Fuzzy")) 333 :group 'lsp-go 334 :package-version '(lsp-mode "9.1")) 335 336 (defcustom lsp-go-complete-function-calls t 337 "Enables function call completion. 338 339 When completing a statement, or when a function return type 340 matches the expected of the expression being completed, 341 completion may suggest call expressions." 342 :type 'boolean 343 :group 'lsp-go 344 :package-version '(lsp-mode "9.1")) 345 346 (defcustom lsp-go-diagnostics-delay "1s" 347 "Controls the amount of time that gopls waits after the most 348 recent file modification before computing deep diagnostics." 349 :type 'string 350 :group 'lsp-go 351 :package-version '(lsp-mode "9.1")) 352 353 (defcustom lsp-go-analysis-progress-reporting t 354 "Controls whether gopls sends progress notifications when 355 construction of its index of analysis facts is taking a long 356 time." 357 :type 'boolean 358 :group 'lsp-go 359 :package-version '(lsp-mode "9.1")) 360 361 (defcustom lsp-go-symbol-scope "all" 362 "Controls which packages are searched for workspace/symbol 363 requests. 364 365 When the scope is \"workspace\", gopls searches only workspace 366 packages. 367 368 When the scope is \"all\", gopls searches all loaded packages, 369 including dependencies and the standard library." 370 :type '(choice (const "all") 371 (const "workspace")) 372 :group 'lsp-go 373 :package-version '(lsp-mode "9.1")) 374 375 (defcustom lsp-go-verbose-output t 376 "Enables additional debug logging." 377 :type 'boolean 378 :group 'lsp-go 379 :package-version '(lsp-mode "9.1")) 380 381 (lsp-register-custom-settings 382 '(("gopls.analyses" lsp-go-analyses) 383 ("gopls.analysisProgressReporting" lsp-go-analysis-progress-reporting t) 384 ("gopls.buildFlags" lsp-go-build-flags) 385 ("gopls.codelenses" lsp-go-codelenses) 386 ("gopls.completeFunctionCalls" lsp-go-complete-function-calls t) 387 ("gopls.completionBudget" lsp-go-completion-budget) 388 ("gopls.diagnosticsDelay" lsp-go-diagnostics-delay) 389 ("gopls.directoryFilters" lsp-go-directory-filters) 390 ("gopls.env" lsp-go-env) 391 ("gopls.gofumpt" lsp-go-use-gofumpt t) 392 ("gopls.hoverKind" lsp-go-hover-kind) 393 ("gopls.importShortcut" lsp-go-import-shortcut) 394 ("gopls.linkTarget" lsp-go-link-target) 395 ("gopls.linksInHover" lsp-go-links-in-hover t) 396 ("gopls.local" lsp-go-goimports-local) 397 ("gopls.matcher" lsp-go-matcher) 398 ("gopls.standaloneTags" lsp-go-standalone-tags) 399 ("gopls.symbolMatcher" lsp-go-symbol-matcher) 400 ("gopls.symbolScope" lsp-go-symbol-scope) 401 ("gopls.symbolStyle" lsp-go-symbol-style) 402 ("gopls.templateExtensions" lsp-go-template-extensions) 403 ("gopls.usePlaceholders" lsp-go-use-placeholders t) 404 ("gopls.verboseOutput" lsp-go-verbose-output t))) 405 406 (defcustom lsp-go-server-wrapper-function 407 #'identity 408 "Function to wrap the language server process started by lsp-go. 409 410 For example, you can pick a go binary provided by a repository's 411 flake.nix file with: 412 413 (use-package nix-sandbox) 414 (defun my/nix--lsp-go-wrapper (args) 415 (if-let ((sandbox (nix-current-sandbox))) 416 (apply `nix-shell-command sandbox args) 417 args)) 418 (setq lsp-go-server-path \"gopls\" 419 lsp-go-server-wrapper-function `my/nix--lsp-go-wrapper)" 420 :group 'lsp-go 421 :type '(choice 422 (function-item :tag "None" :value identity) 423 (function :tag "Custom function"))) 424 425 (defun lsp-go--server-command () 426 "Command and arguments for launching the inferior language server process. 427 These are assembled from the customizable variables `lsp-go-server-path' 428 and `lsp-go-server-wrapper-function'." 429 (funcall lsp-go-server-wrapper-function (append (list lsp-go-gopls-server-path) lsp-go-gopls-server-args))) 430 431 (lsp-register-client 432 (make-lsp-client :new-connection (lsp-stdio-connection 'lsp-go--server-command) 433 :activation-fn (lsp-activate-on "go" "go.mod") 434 :language-id "go" 435 :priority 0 436 :server-id 'gopls 437 :completion-in-comments? t 438 :library-folders-fn #'lsp-go--library-default-directories 439 :after-open-fn (lambda () 440 ;; https://github.com/golang/tools/commit/b2d8b0336 441 (setq-local lsp-completion-filter-on-incomplete nil)))) 442 443 (lsp-consistency-check lsp-go) 444 445 (provide 'lsp-go) 446 ;;; lsp-go.el ends here