From 48a6852b4a3dacce40def29c538e90e57e651f69 Mon Sep 17 00:00:00 2001 From: Gonzalo Larumbe Date: Wed, 18 Oct 2023 13:07:58 +0200 Subject: [PATCH] Update defcustoms, defaults and cache serializing/deserializing --- verilog-ext-eglot.el | 24 ++++---- verilog-ext-flycheck.el | 2 +- verilog-ext-hierarchy.el | 27 +++------ verilog-ext-imenu.el | 7 ++- verilog-ext-tags.el | 128 +++++++++++++++++++++------------------ verilog-ext-utils.el | 36 ++++++----- 6 files changed, 117 insertions(+), 107 deletions(-) diff --git a/verilog-ext-eglot.el b/verilog-ext-eglot.el index d6b4b87..78f1681 100644 --- a/verilog-ext-eglot.el +++ b/verilog-ext-eglot.el @@ -38,69 +38,69 @@ ;;;; svlangserver ;; These customization values are copied from `lsp-verilog' to make `eglot' ;; config independent from `lsp-mode'. -(defgroup verilog-ext-eglot-svlangserver nil - "Settings for the SystemVerilog language server client." +(defgroup verilog-ext-eglot nil + "Verilog-ext eglot." :group 'verilog-ext :link '(url-link "https://github.com/imc-trading/svlangserver") :package-version '(lsp-mode . "8.0.0")) (defcustom verilog-ext-eglot-svlangserver-includeIndexing '["**/*.{sv,svh}"] "Files included for indexing (glob pattern)." - :group 'verilog-ext-eglot-svlangserver + :group 'verilog-ext-eglot :type '(lsp-repeatable-vector string) :safe (lambda (x) (seq-every-p #'stringp x))) (defcustom verilog-ext-eglot-svlangserver-excludeIndexing '["test/**/*.{sv,svh}"] "Files excluded for indexing (glob pattern)." - :group 'verilog-ext-eglot-svlangserver + :group 'verilog-ext-eglot :type '(lsp-repeatable-vector string) :safe (lambda (x) (seq-every-p #'stringp x))) (defcustom verilog-ext-eglot-svlangserver-defines nil "Defines needed for linting." - :group 'verilog-ext-eglot-svlangserver + :group 'verilog-ext-eglot :type '(lsp-repeatable-vector string) :safe (lambda (x) (seq-every-p #'stringp x))) (defcustom verilog-ext-eglot-svlangserver-launchConfiguration "verilator -sv --lint-only -Wall" "Verilator command used for linting." - :group 'verilog-ext-eglot-svlangserver + :group 'verilog-ext-eglot :type 'string :safe (lambda (x) (stringp x))) (defcustom verilog-ext-eglot-svlangserver-lintOnUnsaved t "Enable linting on unsaved files." - :group 'verilog-ext-eglot-svlangserver + :group 'verilog-ext-eglot :type 'boolean :safe (lambda (x) (booleanp x))) (defcustom verilog-ext-eglot-svlangserver-formatCommand "verible-verilog-format" "Verible verilog format command." - :group 'verilog-ext-eglot-svlangserver + :group 'verilog-ext-eglot :type 'string :safe (lambda (x) (stringp x))) (defcustom verilog-ext-eglot-svlangserver-disableCompletionProvider nil "Disable auto completion provided by the language server." - :group 'verilog-ext-eglot-svlangserver + :group 'verilog-ext-eglot :type 'boolean :safe (lambda (x) (booleanp x))) (defcustom verilog-ext-eglot-svlangserver-disableHoverProvider nil "Disable hover over help provided by the language server." - :group 'verilog-ext-eglot-svlangserver + :group 'verilog-ext-eglot :type 'boolean :safe (lambda (x) (booleanp x))) (defcustom verilog-ext-eglot-svlangserver-disableSignatureHelpProvider nil "Disable signature help provided by the language server." - :group 'verilog-ext-eglot-svlangserver + :group 'verilog-ext-eglot :type 'boolean :safe (lambda (x) (booleanp x))) (defcustom verilog-ext-eglot-svlangserver-disableLinting nil "Disable verilator linting." - :group 'verilog-ext-eglot-svlangserver + :group 'verilog-ext-eglot :type 'boolean :safe (lambda (x) (booleanp x))) diff --git a/verilog-ext-flycheck.el b/verilog-ext-flycheck.el index e981df6..53e518c 100644 --- a/verilog-ext-flycheck.el +++ b/verilog-ext-flycheck.el @@ -40,7 +40,7 @@ "Verilog-ext flycheck." :group 'verilog-ext) -(defcustom verilog-ext-flycheck-use-open-buffers t +(defcustom verilog-ext-flycheck-use-open-buffers nil "Set to non-nil to use list of open Verilog buffers/dirs for linters." :type 'boolean :group 'verilog-ext-flycheck) diff --git a/verilog-ext-hierarchy.el b/verilog-ext-hierarchy.el index 7b39f83..071d3c5 100644 --- a/verilog-ext-hierarchy.el +++ b/verilog-ext-hierarchy.el @@ -35,14 +35,16 @@ "Verilog-ext hierarchy." :group 'verilog-ext) -(defcustom verilog-ext-hierarchy-backend nil +(defcustom verilog-ext-hierarchy-backend (if (and (treesit-available-p) (treesit-language-available-p 'verilog)) + 'tree-sitter + 'builtin) "Verilog-ext hierarchy extraction backend." :type '(choice (const :tag "Verilog-Perl vhier" vhier) (const :tag "Tree-sitter" tree-sitter) (const :tag "Built-in" builtin)) :group 'verilog-ext-hierarchy) -(defcustom verilog-ext-hierarchy-frontend nil +(defcustom verilog-ext-hierarchy-frontend 'hierarchy "Verilog-ext hierarchy display and navigation frontend." :type '(choice (const :tag "Outshine" outshine) (const :tag "Hierarchy" hierarchy)) @@ -629,23 +631,10 @@ Expects HIERARCHY to be a indented string." (setq verilog-ext-hierarchy-module-alist (verilog-ext-unserialize verilog-ext-hierarchy-module-cache-file))) (defun verilog-ext-hierarchy-setup () - "Setup hierarchy backend/frontend depending on available binaries/packages. -If these have been set before, keep their values." - (let ((backend (or verilog-ext-hierarchy-backend - (cond ((executable-find "vhier") - 'vhier) - ((and (treesit-available-p) - (treesit-language-available-p 'verilog)) - 'tree-sitter) - (t - 'builtin)))) - (frontend (or verilog-ext-hierarchy-frontend - 'hierarchy))) - (setq verilog-ext-hierarchy-backend backend) - (setq verilog-ext-hierarchy-frontend frontend) - ;; Cache - (when verilog-ext-cache-enable - (verilog-ext-hierarchy-unserialize)))) + "Setup hierarchy feature. +Read hierarchy cache if enabled." + (when verilog-ext-cache-enable + (verilog-ext-hierarchy-unserialize))) (defun verilog-ext-hierarchy-clear-cache (&optional all) "Clear hierarchy cache files for current project. diff --git a/verilog-ext-imenu.el b/verilog-ext-imenu.el index 876e211..683f3fb 100644 --- a/verilog-ext-imenu.el +++ b/verilog-ext-imenu.el @@ -30,11 +30,16 @@ (require 'verilog-ext-nav) +(defgroup verilog-ext-imenu nil + "Verilog-ext imenu." + :group 'verilog-ext) + (defconst verilog-ext-imenu-class-item-face 'verilog-ext-imenu-class-item-face) (defface verilog-ext-imenu-class-item-face '((t nil)) "Face for class items." - :group 'verilog-ext) + :group 'verilog-ext-imenu) + (defconst verilog-ext-imenu-top-re "^\\s-*\\(?1:connectmodule\\|m\\(?:odule\\|acromodule\\)\\|p\\(?:rimitive\\|rogram\\|ackage\\)\\)\\(\\s-+automatic\\)?\\s-+\\(?2:[a-zA-Z0-9_.:]+\\)") (defconst verilog-ext-imenu-localparam-re "^\\s-*localparam\\(?1:\\s-+\\(logic\\|bit\\|int\\|integer\\)\\s-*\\(\\[.*\\]\\)?\\)?\\s-+\\(?2:[a-zA-Z0-9_.:]+\\)") diff --git a/verilog-ext-tags.el b/verilog-ext-tags.el index e80748a..677f41a 100644 --- a/verilog-ext-tags.el +++ b/verilog-ext-tags.el @@ -50,7 +50,9 @@ "Verilog-ext tags." :group 'verilog-ext) -(defcustom verilog-ext-tags-backend nil +(defcustom verilog-ext-tags-backend (if (and (treesit-available-p) (treesit-language-available-p 'verilog)) + 'tree-sitter + 'builtin) "Verilog-ext tags extraction backend." :type '(choice (const :tag "Tree-sitter" tree-sitter) (const :tag "Built-in" builtin)) @@ -61,7 +63,7 @@ This setting slightly increases processing time of `verilog-ext-tags-get'." :type 'boolean - :group 'verilog-ext) + :group 'verilog-ext-tags) (defvar verilog-ext-tags-file-hashes nil) @@ -107,6 +109,10 @@ This setting slightly increases processing time of `verilog-ext-tags-get'." "verilog-ext-tags-backend") 'symbols))) +(defvar verilog-ext-tags-have-been-updated nil + "Determines whether or not tags have been updated. +Used to conditionally serialize tags cache.") + ;;;; Common (defsubst verilog-ext-tags-locs-props (type desc file line col) @@ -603,51 +609,6 @@ Optional arg VERBOSE to display extra messages for debugging." (verilog-ext-tags-add-file-locs file proj-inst-file-tables proj-inst-table) (verilog-ext-tags-add-file-locs file proj-refs-file-tables proj-refs-table)))))) -(defun verilog-ext-tags-get (&optional verbose) - "Get tags of current project. -With current-prefix or VERBOSE, dump output log." - (interactive "P") - (let* ((proj (verilog-ext-buffer-proj)) - (files (verilog-ext-proj-files proj)) - (files-removed (seq-difference (map-keys (verilog-ext-aget verilog-ext-tags-file-hashes proj)) files)) - (num-files (+ (length files-removed) (length files))) - (num-files-processed 0) - (log-file verilog-ext-tags-cache-log-file) - (tags-progress-reporter (make-progress-reporter "[Tags collection]: " 0 num-files))) - (verilog-ext-tags-proj-init proj) - (when verbose - (delete-file log-file)) - (dolist (file files-removed) - (progress-reporter-update tags-progress-reporter num-files-processed (format "[%s]" file)) - (verilog-ext-tags-get--process-file file proj :file-was-removed verbose) - (setq num-files-processed (1+ num-files-processed))) - (dolist (file files) - (when verbose - (append-to-file (format "(%0d%%) [Tags collection] Processing %s\n" (/ (* num-files-processed 100) num-files) file) nil log-file)) - (progress-reporter-update tags-progress-reporter num-files-processed (format "[%s]" file)) - (verilog-ext-tags-get--process-file file proj nil verbose) - (setq num-files-processed (1+ num-files-processed))) - (message "Finished collection of tags!"))) - -(defun verilog-ext-tags-get-async (&optional verbose) - "Create tags table asynchronously. -With current-prefix or VERBOSE, dump output log." - (interactive "P") - (let ((proj-root (verilog-ext-buffer-proj-root))) - (unless proj-root - (user-error "Not in a Verilog project buffer")) - (message "Starting tag collection for %s" proj-root) - (async-start - `(lambda () - ,(async-inject-variables verilog-ext-tags-async-inject-variables-re) - (require 'verilog-ext) - (verilog-ext-tags-unserialize) ; Read environment in child process - (verilog-ext-tags-get ,@verbose) ; Update variables in child process - (verilog-ext-tags-serialize)) ; Update cache file in childe process - (lambda (_result) - (verilog-ext-tags-unserialize) - (message "Finished collection of tags!"))))) ; Update parent process from cache file - (defun verilog-ext-tags-serialize () "Write variables to their cache files." (message "Serializing `verilog-ext' tags cache...") @@ -663,6 +624,7 @@ With current-prefix or VERBOSE, dump output log." (defun verilog-ext-tags-unserialize () "Read cache files into their corresponding variables." + (message "Unserializing `verilog-ext' tags cache...") (dolist (var `((verilog-ext-tags-defs-file-tables . ,verilog-ext-tags-defs-file-tables-cache-file) (verilog-ext-tags-refs-file-tables . ,verilog-ext-tags-refs-file-tables-cache-file) (verilog-ext-tags-inst-file-tables . ,verilog-ext-tags-inst-file-tables-cache-file) @@ -670,19 +632,14 @@ With current-prefix or VERBOSE, dump output log." (verilog-ext-tags-inst-table . ,verilog-ext-tags-inst-table-cache-file) (verilog-ext-tags-refs-table . ,verilog-ext-tags-refs-table-cache-file) (verilog-ext-tags-file-hashes . ,verilog-ext-tags-file-hashes-cache-file))) - (set (car var) (verilog-ext-unserialize (cdr var))))) + (set (car var) (verilog-ext-unserialize (cdr var)))) + (message "Unserializing `verilog-ext' tags cache... Done")) -(defun verilog-ext-tags-setup () - "Setup tags feature: backend, cache read at startup and write before exit." - (let ((backend (or verilog-ext-tags-backend - (if (and (treesit-available-p) - (treesit-language-available-p 'verilog)) - 'tree-sitter - 'builtin)))) - (setq verilog-ext-tags-backend backend) - (when verilog-ext-cache-enable - (verilog-ext-tags-unserialize) - (add-hook 'kill-emacs-hook #'verilog-ext-tags-serialize)))) +(defun verilog-ext-tags-save-cache () + "Save tags cache only if tables have been updated. +Removes serializing and compression processing overhead if no change was made." + (when verilog-ext-tags-have-been-updated + (verilog-ext-tags-serialize))) (defun verilog-ext-tags-clear-cache (&optional all) "Clear tags cache files for current project. @@ -712,6 +669,59 @@ With prefix arg, clear cache for ALL projects." (verilog-ext-tags-serialize) (message "Cleared all projects tags cache!"))) +(defun verilog-ext-tags-setup () + "Setup tags feature: backend, cache read at startup and write before exit." + (when verilog-ext-cache-enable + (verilog-ext-tags-unserialize) + (add-hook 'kill-emacs-hook #'verilog-ext-tags-save-cache))) + +(defun verilog-ext-tags-get (&optional verbose) + "Get tags of current project. +With current-prefix or VERBOSE, dump output log." + (interactive "P") + (let* ((proj (verilog-ext-buffer-proj)) + (files (verilog-ext-proj-files proj)) + (files-removed (seq-difference (map-keys (verilog-ext-aget verilog-ext-tags-file-hashes proj)) files)) + (num-files (+ (length files-removed) (length files))) + (num-files-processed 0) + (log-file verilog-ext-tags-cache-log-file) + (tags-progress-reporter (make-progress-reporter "[Tags collection]: " 0 num-files))) + (verilog-ext-tags-proj-init proj) + (when verbose + (delete-file log-file)) + (dolist (file files-removed) + (progress-reporter-update tags-progress-reporter num-files-processed (format "[%s]" file)) + (verilog-ext-tags-get--process-file file proj :file-was-removed verbose) + (setq num-files-processed (1+ num-files-processed))) + (dolist (file files) + (when verbose + (append-to-file (format "(%0d%%) [Tags collection] Processing %s\n" (/ (* num-files-processed 100) num-files) file) nil log-file)) + (progress-reporter-update tags-progress-reporter num-files-processed (format "[%s]" file)) + (verilog-ext-tags-get--process-file file proj nil verbose) + (setq num-files-processed (1+ num-files-processed))) + (setq verilog-ext-tags-have-been-updated t) + (message "Finished collection of tags!"))) + +(defun verilog-ext-tags-get-async (&optional verbose) + "Create tags table asynchronously. +With current-prefix or VERBOSE, dump output log." + (interactive "P") + (let ((proj-root (verilog-ext-buffer-proj-root))) + (unless proj-root + (user-error "Not in a Verilog project buffer")) + (message "Starting tag collection for %s" proj-root) + (async-start + `(lambda () + ,(async-inject-variables verilog-ext-tags-async-inject-variables-re) + (require 'verilog-ext) + (verilog-ext-tags-unserialize) ; Read environment in child process + (verilog-ext-tags-get ,@verbose) ; Update variables in child process + (verilog-ext-tags-serialize)) ; Update cache file in child process + (lambda (_result) + (verilog-ext-tags-unserialize) + (setq verilog-ext-tags-have-been-updated t) + (message "Finished collection of tags!"))))) ; Update parent process from cache file + (provide 'verilog-ext-tags) diff --git a/verilog-ext-utils.el b/verilog-ext-utils.el index 8f71b4f..9fdd088 100644 --- a/verilog-ext-utils.el +++ b/verilog-ext-utils.el @@ -38,10 +38,13 @@ Defaults to .v, .vh, .sv and .svh." :type 'boolean :group 'verilog-ext) -(defcustom verilog-ext-cache-do-compression t +(defcustom verilog-ext-cache-do-compression nil "If set to non-nil compress cache files. -Requires having \"gzip\" and \"gunzip\" in the $PATH." +Requires having \"gzip\" and \"gunzip\" in the $PATH. + +If set to non-nil increases loading time of `verilog-ext' package but cache +files take up much less disk space." :type 'boolean :group 'verilog-ext) @@ -844,7 +847,6 @@ These depend on the value of property list of `verilog-ext-project-alist'. Compress cache files if gzip is available." (let ((dir (file-name-directory filename)) - (gzip-proc-name "verilog-ext-serialize-compress") (gzip-buf "*verilog-ext-serialize-compress*")) (unless (file-exists-p dir) (make-directory dir :parents)) @@ -854,8 +856,9 @@ Compress cache files if gzip is available." (insert (let (print-length) (prin1-to-string data)))) (when (and verilog-ext-cache-do-compression (executable-find "gzip")) - ;; Async compressing - (start-process-shell-command gzip-proc-name gzip-buf (format "gzip -9f %s" filename)))))) + ;; Synchronous processing, as it might be run just before exiting Emacs + (unless (eq 0 (call-process-shell-command (format "gzip -9f %s" filename) nil gzip-buf t)) + (error "Error compressing %s" filename)))))) (defun verilog-ext-unserialize (filename) "Read data serialized by `verilog-ext-serialize' from FILENAME." @@ -873,16 +876,19 @@ Compress cache files if gzip is available." (if (and verilog-ext-cache-do-compression (executable-find "gunzip") (file-exists-p compressed-filename)) - ;; External gunzip program: This doesn't need to be asynchronous as it will only be done during initial setup - (unless (eq 0 (call-process-shell-command decompress-cmd nil gzip-buf t)) - (error "Error uncompressing %s" compressed-filename)) - (setq temp-filename filename)) - (when (file-exists-p temp-filename) - (with-temp-buffer - (insert-file-contents temp-filename) - (delete-file temp-filename) - ;; this will blow up if the contents of the file aren't lisp data structures - (read (buffer-string))))))) + (progn + ;; External gunzip program: This doesn't need to be asynchronous as it will only be done during initial setup + (unless (eq 0 (call-process-shell-command decompress-cmd nil gzip-buf t)) + (error "Error decompressing %s" compressed-filename)) + (with-temp-buffer + (insert-file-contents temp-filename) + (delete-file temp-filename) + (read (buffer-string)))) + ;; Do not decompress + (when (file-exists-p filename) + (with-temp-buffer + (insert-file-contents filename) + (read (buffer-string)))))))) (provide 'verilog-ext-utils)