emacs/code/elpa/lsp-mode-20240319.1043/lsp-wgsl.el

205 lines
7.8 KiB
EmacsLisp

;;; lsp-wgsl.el --- description -*- lexical-binding: t; -*-
;; Copyright (C) 2023 emacs-lsp maintainers
;; Author: emacs-lsp maintainers
;; Keywords: lsp, wgsl, shaders, graphics programming,
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; LSP Clients for WGSL (WebGPU Shading Language).
;;; Code:
(require 'lsp-mode)
(defgroup lsp-wgsl nil
"LSP support for wgsl, using wgsl-analyzer."
:group 'lsp-mode
:link '(url-link "https://github.com/wgsl-analyzer/wgsl-analyzer")
:package-version '(lsp-mode . "8.0.1"))
(defcustom lsp-wgsl-server-command "wgsl_analyzer"
"Command to run the wgsl-analyzer executable."
:type 'boolean
:group 'lsp-wgsl
:package-version '(lsp-mode . "8.0.1"))
;; Various toggling settings for the lsp server
(defcustom lsp-wgsl-diagnostics-type-errors t
"Whether to show type errors in diagnostics or not."
:type 'boolean
:group 'lsp-wgsl
:package-version '(lsp-mode . "8.0.1"))
(defcustom lsp-wgsl-diagnostics-naga-parsing-errors t
"Whether to show naga parsing errors in diagnostics or not."
:type 'boolean
:group 'lsp-wgsl
:package-version '(lsp-mode . "8.0.1"))
(defcustom lsp-wgsl-diagnostics-naga-validation-errors t
"Whether to show naga validation errors in diagnostics or not."
:type 'boolean
:group 'lsp-wgsl
:package-version '(lsp-mode . "8.0.1"))
(defcustom lsp-wgsl-diagnostics-naga-version "main"
"Naga version to use."
:type 'string
:group 'lsp-wgsl
:package-version '(lsp-mode . "8.0.1"))
(defcustom lsp-wgsl-inlayhints-enabled t
"Whether to enable inlay hints or not."
:type 'boolean
:group 'lsp-wgsl
:package-version '(lsp-mode . "8.0.1"))
(defcustom lsp-wgsl-inlayhints-typehints t
"Whether to enable type hints or not when using inlay hints."
:type 'boolean
:group 'lsp-wgsl
:package-version '(lsp-mode . "8.0.1"))
(defcustom lsp-wgsl-inlayhints-parameterhints t
"Whether to enable parameter hints or not when using inlay hints."
:type 'boolean
:group 'lsp-wgsl
:package-version '(lsp-mode . "8.0.1"))
(defcustom lsp-wgsl-inlayhints-structlayout t
"Whether to enable struct layout hints or not when using inlay hints."
:type 'boolean
:group 'lsp-wgsl
:package-version '(lsp-mode . "8.0.1"))
;; TODO: maybe type choice instead?
(defcustom lsp-wgsl-inlayhints-type-verbosity "compact"
"The type verbosity to use for inlay hints."
:type '(choice (string "full")
(string "compact")
(string "inner"))
:group 'lsp-wgsl
:package-version '(lsp-mode . "8.0.1"))
(defcustom lsp-wgsl-custom-imports (lsp-ht)
"List of custom imports in the style of Bevy"
:type 'ht
:group 'lsp-wgsl
:package-version '(lsp-mode . "8.0.1"))
(defcustom lsp-wgsl-shaderdefs []
"Defines that should be valid for preprocessor operations like ifdef,
e.g, ['USE_TYPES', 'DEBUG']"
:type 'lsp-string-vector
:group 'lsp-wgsl
:package-version '(lsp-mode . "8.0.1"))
;; wgsl-analyzer is a bit weird with how it gets config.
;; Currently it relies on a custom extension to query the clients.
;; (could not get standard custom-settings blocks to work)
(defun lsp-wgsl--send-configuration (&rest _)
;; TODO: why doesnt this behave like the normal lists?!?!? I cant just send a list?!?!?! why the fuck?!?!
(list :customImports lsp-wgsl-custom-imports
:diagnostics (list :typeErrors (lsp-json-bool lsp-wgsl-diagnostics-type-errors)
:nagaParsingErrors (lsp-json-bool lsp-wgsl-diagnostics-naga-parsing-errors)
:nagaValidationErrors (lsp-json-bool lsp-wgsl-diagnostics-naga-validation-errors)
:nagaVersion lsp-wgsl-diagnostics-naga-version)
:inlayHints (list :enabled (lsp-json-bool lsp-wgsl-inlayhints-enabled)
:typeHints (lsp-json-bool lsp-wgsl-inlayhints-typehints)
:parameterHints (lsp-json-bool lsp-wgsl-inlayhints-parameterhints)
:structLayoutHints (lsp-json-bool lsp-wgsl-inlayhints-structlayout)
:typeVerbosity lsp-wgsl-inlayhints-type-verbosity)
:shaderDefs lsp-wgsl-shaderdefs
;; not configurable at the moment, as they don't seem to have much effect.
;; Fails if not given.
:trace (list :extension t
:server t)))
(defvar wgsl-font-lock-keywords)
;; Various interactive functions to use the custom LSP extensions from the server
(defun lsp-wgsl-full-source ()
"Gets the full source of the file with all imports and preprocessor
definitions resolved."
(interactive)
(lsp-request-async
"wgsl-analyzer/fullSource"
(list :textDocument (list :uri (lsp--buffer-uri)))
(lambda (source)
(let ((buffer (get-buffer-create "*WGSL-full-source*")))
(with-current-buffer buffer
(setq-local buffer-read-only nil)
(erase-buffer)
(insert source)
(read-only-mode)
;; activate only syntax highlighting
(font-lock-add-keywords nil wgsl-font-lock-keywords)
(font-lock-mode))
(switch-to-buffer buffer)))))
(defun lsp-wgsl-syntax-tree ()
"Gets the syntax tree of the current buffer."
(interactive)
(lsp-request-async
"wgsl-analyzer/syntaxTree"
(list :textDocument (list :uri (lsp--buffer-uri))
:range (if (use-region-p)
(lsp--region-to-range (region-beginning) (region-end))
(lsp--region-to-range (point-min) (point-max))))
(lambda (syntax-tree)
(let ((buffer (get-buffer-create (format "*WGSL-syntax-tree %s*" (lsp--buffer-uri)))))
(with-current-buffer buffer
(setq-local buffer-read-only nil)
(erase-buffer)
(insert syntax-tree)
(read-only-mode))
(switch-to-buffer buffer)))))
(lsp-dependency 'wgsl-analyzer
'(:system lsp-wgsl-server-command)
'(:cargo :package "wgsl_analyzer"
:path "wgsl_analyzer"
:git "https://github.com/wgsl-analyzer/wgsl-analyzer"))
(lsp-register-client
(make-lsp-client :new-connection (lsp-stdio-connection
(lambda ()
(or (lsp-package-path 'wgsl-analyzer)
lsp-wgsl-server-command)))
:initialized-fn (lambda (workspace)
(with-lsp-workspace workspace
;; wgsl-analyzer handles configuration in a VERY non-standard way
;; https://github.com/wgsl-analyzer/wgsl-analyzer/issues/77
(lsp--set-configuration '())))
:request-handlers (lsp-ht ("wgsl-analyzer/requestConfiguration" #'lsp-wgsl--send-configuration))
:major-modes '(wgsl-mode)
:activation-fn (lsp-activate-on "wgsl")
:download-server-fn (lambda (_client callback error-callback _update?)
(lsp-package-ensure 'wgsl-analyzer
callback error-callback))
:priority -1
:server-id 'wgsl-analyzer))
(lsp-consistency-check lsp-wgsl)
(provide 'lsp-wgsl)
;;; lsp-wgsl.el ends here