config

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

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