lsp-wgsl.el (7951B)
1 ;;; lsp-wgsl.el --- description -*- lexical-binding: t; -*- 2 3 ;; Copyright (C) 2023 emacs-lsp maintainers 4 5 ;; Author: emacs-lsp maintainers 6 ;; Keywords: lsp, wgsl, shaders, graphics programming, 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 Clients for WGSL (WebGPU Shading Language). 24 25 ;;; Code: 26 27 (require 'lsp-mode) 28 29 (defgroup lsp-wgsl nil 30 "LSP support for wgsl, using wgsl-analyzer." 31 :group 'lsp-mode 32 :link '(url-link "https://github.com/wgsl-analyzer/wgsl-analyzer") 33 :package-version '(lsp-mode . "9.0.0")) 34 35 36 (defcustom lsp-wgsl-server-command "wgsl_analyzer" 37 "Command to run the wgsl-analyzer executable." 38 :type 'boolean 39 :group 'lsp-wgsl 40 :package-version '(lsp-mode . "9.0.0")) 41 42 ;; Various toggling settings for the lsp server 43 (defcustom lsp-wgsl-diagnostics-type-errors t 44 "Whether to show type errors in diagnostics or not." 45 :type 'boolean 46 :group 'lsp-wgsl 47 :package-version '(lsp-mode . "9.0.0")) 48 49 (defcustom lsp-wgsl-diagnostics-naga-parsing-errors t 50 "Whether to show naga parsing errors in diagnostics or not." 51 :type 'boolean 52 :group 'lsp-wgsl 53 :package-version '(lsp-mode . "9.0.0")) 54 55 (defcustom lsp-wgsl-diagnostics-naga-validation-errors t 56 "Whether to show naga validation errors in diagnostics or not." 57 :type 'boolean 58 :group 'lsp-wgsl 59 :package-version '(lsp-mode . "9.0.0")) 60 61 (defcustom lsp-wgsl-diagnostics-naga-version "main" 62 "Naga version to use." 63 :type 'string 64 :group 'lsp-wgsl 65 :package-version '(lsp-mode . "9.0.0")) 66 67 (defcustom lsp-wgsl-inlayhints-enabled t 68 "Whether to enable inlay hints or not." 69 :type 'boolean 70 :group 'lsp-wgsl 71 :package-version '(lsp-mode . "9.0.0")) 72 73 (defcustom lsp-wgsl-inlayhints-typehints t 74 "Whether to enable type hints or not when using inlay hints." 75 :type 'boolean 76 :group 'lsp-wgsl 77 :package-version '(lsp-mode . "9.0.0")) 78 79 (defcustom lsp-wgsl-inlayhints-parameterhints t 80 "Whether to enable parameter hints or not when using inlay hints." 81 :type 'boolean 82 :group 'lsp-wgsl 83 :package-version '(lsp-mode . "9.0.0")) 84 85 (defcustom lsp-wgsl-inlayhints-structlayout t 86 "Whether to enable struct layout hints or not when using inlay hints." 87 :type 'boolean 88 :group 'lsp-wgsl 89 :package-version '(lsp-mode . "9.0.0")) 90 91 ;; TODO: maybe type choice instead? 92 (defcustom lsp-wgsl-inlayhints-type-verbosity "compact" 93 "The type verbosity to use for inlay hints." 94 :type '(choice (string "full") 95 (string "compact") 96 (string "inner")) 97 :group 'lsp-wgsl 98 :package-version '(lsp-mode . "9.0.0")) 99 100 (defcustom lsp-wgsl-custom-imports (lsp-ht) 101 "List of custom imports in the style of Bevy" 102 :type 'ht 103 :group 'lsp-wgsl 104 :package-version '(lsp-mode . "9.0.0")) 105 106 (defcustom lsp-wgsl-shaderdefs [] 107 "Defines that should be valid for preprocessor operations like ifdef, 108 e.g, ['USE_TYPES', 'DEBUG']" 109 :type 'lsp-string-vector 110 :group 'lsp-wgsl 111 :package-version '(lsp-mode . "9.0.0")) 112 113 ;; wgsl-analyzer is a bit weird with how it gets config. 114 ;; Currently it relies on a custom extension to query the clients. 115 ;; (could not get standard custom-settings blocks to work) 116 (defun lsp-wgsl--send-configuration (&rest _) 117 ;; TODO: why doesnt this behave like the normal lists?!?!? I cant just send a list?!?!?! why the fuck?!?! 118 (list :customImports lsp-wgsl-custom-imports 119 :diagnostics (list :typeErrors (lsp-json-bool lsp-wgsl-diagnostics-type-errors) 120 :nagaParsingErrors (lsp-json-bool lsp-wgsl-diagnostics-naga-parsing-errors) 121 :nagaValidationErrors (lsp-json-bool lsp-wgsl-diagnostics-naga-validation-errors) 122 :nagaVersion lsp-wgsl-diagnostics-naga-version) 123 :inlayHints (list :enabled (lsp-json-bool lsp-wgsl-inlayhints-enabled) 124 :typeHints (lsp-json-bool lsp-wgsl-inlayhints-typehints) 125 :parameterHints (lsp-json-bool lsp-wgsl-inlayhints-parameterhints) 126 :structLayoutHints (lsp-json-bool lsp-wgsl-inlayhints-structlayout) 127 :typeVerbosity lsp-wgsl-inlayhints-type-verbosity) 128 :shaderDefs lsp-wgsl-shaderdefs 129 ;; not configurable at the moment, as they don't seem to have much effect. 130 ;; Fails if not given. 131 :trace (list :extension t 132 :server t))) 133 134 (defvar wgsl-font-lock-keywords) 135 136 ;; Various interactive functions to use the custom LSP extensions from the server 137 (defun lsp-wgsl-full-source () 138 "Gets the full source of the file with all imports and preprocessor 139 definitions resolved." 140 (interactive) 141 (lsp-request-async 142 "wgsl-analyzer/fullSource" 143 (list :textDocument (list :uri (lsp--buffer-uri))) 144 (lambda (source) 145 (let ((buffer (get-buffer-create "*WGSL-full-source*"))) 146 (with-current-buffer buffer 147 (setq-local buffer-read-only nil) 148 (erase-buffer) 149 (insert source) 150 (read-only-mode) 151 ;; activate only syntax highlighting 152 (font-lock-add-keywords nil wgsl-font-lock-keywords) 153 (font-lock-mode)) 154 (switch-to-buffer buffer))))) 155 156 (defun lsp-wgsl-syntax-tree () 157 "Gets the syntax tree of the current buffer." 158 (interactive) 159 (lsp-request-async 160 "wgsl-analyzer/syntaxTree" 161 (list :textDocument (list :uri (lsp--buffer-uri)) 162 :range (if (use-region-p) 163 (lsp--region-to-range (region-beginning) (region-end)) 164 (lsp--region-to-range (point-min) (point-max)))) 165 (lambda (syntax-tree) 166 (let ((buffer (get-buffer-create (format "*WGSL-syntax-tree %s*" (lsp--buffer-uri))))) 167 (with-current-buffer buffer 168 (setq-local buffer-read-only nil) 169 (erase-buffer) 170 (insert syntax-tree) 171 (read-only-mode)) 172 (switch-to-buffer buffer))))) 173 174 175 (lsp-dependency 'wgsl-analyzer 176 '(:system lsp-wgsl-server-command) 177 '(:cargo :package "wgsl_analyzer" 178 :path "wgsl_analyzer" 179 :git "https://github.com/wgsl-analyzer/wgsl-analyzer")) 180 181 (lsp-register-client 182 (make-lsp-client :new-connection (lsp-stdio-connection 183 (lambda () 184 (or (lsp-package-path 'wgsl-analyzer) 185 lsp-wgsl-server-command))) 186 :initialized-fn (lambda (workspace) 187 (with-lsp-workspace workspace 188 ;; wgsl-analyzer handles configuration in a VERY non-standard way 189 ;; https://github.com/wgsl-analyzer/wgsl-analyzer/issues/77 190 (lsp--set-configuration '()))) 191 :request-handlers (lsp-ht ("wgsl-analyzer/requestConfiguration" #'lsp-wgsl--send-configuration)) 192 :major-modes '(wgsl-mode) 193 :activation-fn (lsp-activate-on "wgsl") 194 :download-server-fn (lambda (_client callback error-callback _update?) 195 (lsp-package-ensure 'wgsl-analyzer 196 callback error-callback)) 197 :priority -1 198 :server-id 'wgsl-analyzer)) 199 200 201 (lsp-consistency-check lsp-wgsl) 202 203 (provide 'lsp-wgsl) 204 ;;; lsp-wgsl.el ends here