lsp-go.el (12545B)
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-string-vector 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 '(repeat 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 (string :tag "A custom website")) 235 :group 'lsp-go 236 :package-version '(lsp-mode "7.0.1")) 237 238 (defcustom lsp-go-links-in-hover t 239 "If non-nil, hover documentation includes links." 240 :type 'boolean 241 :group 'lsp-go 242 :package-version '(lsp-mode "8.0.0")) 243 244 (defcustom lsp-go-use-gofumpt nil 245 "If non-nil, use gofumpt formatting." 246 :type 'boolean 247 :group 'lsp-go 248 :package-version '(lsp-mode "8.0.0")) 249 250 (defcustom lsp-go-goimports-local "" 251 "Equivalent of the goimports -local flag, which puts imports beginning with 252 this string after third-party packages. It should be the prefix of the import 253 path whose imports should be grouped separately." 254 :type 'string 255 :group 'lsp-go 256 :package-version '(lsp-mode "8.0.0")) 257 258 (defcustom lsp-go-analyses nil 259 "Specify analyses that the user would like to enable or disable. A map of the 260 names of analysis passes that should be enabled/disabled. A full list of 261 analyzers that gopls uses can be found at 262 https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md" 263 :type '(alist :key-type (string :tag "analyzer name") :value-type (boolean :tag "value")) 264 :group 'lsp-go 265 :risky t 266 :package-version '(lsp-mode "8.0.0")) 267 268 (defcustom lsp-go-import-shortcut "Both" 269 "Specifies whether import statements should link to documentation or go to 270 definitions." 271 :type '(choice (const "Both") 272 (const "Link") 273 (const "Definition")) 274 :group 'lsp-go 275 :risky t 276 :package-version '(lsp-mode "8.0.0")) 277 278 (defcustom lsp-go-symbol-matcher "Fuzzy" 279 "Sets the algorithm that is used when finding workspace symbols." 280 :type '(choice (const "Fuzzy") 281 (const "CaseInsensitive") 282 (const "CaseSensitive")) 283 :group 'lsp-go 284 :risky t 285 :package-version '(lsp-mode "8.0.0")) 286 287 (defcustom lsp-go-symbol-style "Dynamic" 288 "Controls how symbols are qualified in symbol responses. 289 290 `Dynamic' uses whichever qualifier results in the highest scoring match for 291 the given symbol query. Here a `qualifier' is any `/' or '.' delimited suffix 292 of the fully qualified symbol. i.e. `to/pkg.Foo.Field' or just `Foo.Field'. 293 294 `Full' is fully qualified symbols, i.e. `path/to/pkg.Foo.Field'. 295 296 `Package' is package qualified symbols i.e. `pkg.Foo.Field'." 297 :type '(choice (const "Dynamic") 298 (const "Full") 299 (const "Package")) 300 :group 'lsp-go 301 :risky t 302 :package-version '(lsp-mode "8.0.0")) 303 304 (lsp-register-custom-settings 305 '(("gopls.usePlaceholders" lsp-go-use-placeholders t) 306 ("gopls.hoverKind" lsp-go-hover-kind) 307 ("gopls.buildFlags" lsp-go-build-flags) 308 ("gopls.env" lsp-go-env) 309 ("gopls.linkTarget" lsp-go-link-target) 310 ("gopls.codelenses" lsp-go-codelenses) 311 ("gopls.linksInHover" lsp-go-links-in-hover t) 312 ("gopls.gofumpt" lsp-go-use-gofumpt t) 313 ("gopls.local" lsp-go-goimports-local) 314 ("gopls.directoryFilters" lsp-go-directory-filters) 315 ("gopls.analyses" lsp-go-analyses) 316 ("gopls.importShortcut" lsp-go-import-shortcut) 317 ("gopls.symbolMatcher" lsp-go-symbol-matcher) 318 ("gopls.symbolStyle" lsp-go-symbol-style))) 319 320 (defcustom lsp-go-server-wrapper-function 321 #'identity 322 "Function to wrap the language server process started by lsp-go. 323 324 For example, you can pick a go binary provided by a repository's 325 flake.nix file with: 326 327 (use-package nix-sandbox) 328 (defun my/nix--lsp-go-wrapper (args) 329 (if-let ((sandbox (nix-current-sandbox))) 330 (apply `nix-shell-command sandbox args) 331 args)) 332 (setq lsp-go-server-path \"gopls\" 333 lsp-go-server-wrapper-function `my/nix--lsp-go-wrapper)" 334 :group 'lsp-go 335 :type '(choice 336 (function-item :tag "None" :value identity) 337 (function :tag "Custom function"))) 338 339 (defun lsp-go--server-command () 340 "Command and arguments for launching the inferior language server process. 341 These are assembled from the customizable variables `lsp-go-server-path' 342 and `lsp-go-server-wrapper-function'." 343 (funcall lsp-go-server-wrapper-function (append (list lsp-go-gopls-server-path) lsp-go-gopls-server-args))) 344 345 (lsp-register-client 346 (make-lsp-client :new-connection (lsp-stdio-connection 'lsp-go--server-command) 347 :activation-fn (lsp-activate-on "go" "go.mod") 348 :language-id "go" 349 :priority 0 350 :server-id 'gopls 351 :completion-in-comments? t 352 :library-folders-fn #'lsp-go--library-default-directories 353 :after-open-fn (lambda () 354 ;; https://github.com/golang/tools/commit/b2d8b0336 355 (setq-local lsp-completion-filter-on-incomplete nil)))) 356 357 (lsp-consistency-check lsp-go) 358 359 (provide 'lsp-go) 360 ;;; lsp-go.el ends here