config

Personal configuration.
git clone git://code.dwrz.net/config
Log | Files | Refs

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