branch: externals/javaimp commit 766cc2e30096bf9b1d423a2266a1a26fc2e2b098 Author: Filipp Gunbin <fgun...@fastmail.fm> Commit: Filipp Gunbin <fgun...@fastmail.fm>
Don't save excursion or restriction in parse entry points --- javaimp-parse.el | 85 ++++++++++++++++++++++++++------------------------------ javaimp-tests.el | 14 +++++----- javaimp.el | 39 ++++++++++++++------------ 3 files changed, 68 insertions(+), 70 deletions(-) diff --git a/javaimp-parse.el b/javaimp-parse.el index e00fedb..91002a0 100644 --- a/javaimp-parse.el +++ b/javaimp-parse.el @@ -367,12 +367,9 @@ then goes all the way up. Examines and sets property buffer which are after `javaimp--parse-dirty-pos', if it is non-nil. Resets this variable after parsing is done." (when javaimp--parse-dirty-pos - (when (eq javaimp--parse-dirty-pos 'init) - ;; TODO better way to do this - (setq javaimp--parse-dirty-pos (point-min)) - (setq syntax-ppss-table javaimp-syntax-table) - (add-hook 'after-change-functions #'javaimp--parse-update-dirty-pos)) - ;; FIXME this inhibits costly cc-mode hooks on prop updates + (javaimp--parse-ensure-buffer-setup) + ;; cc-mode sets some costly modification hooks, we can inhibit + ;; them because we update only our private props here (let ((inhibit-modification-hooks t)) (remove-text-properties javaimp--parse-dirty-pos (point-max) '(javaimp-parse-scope nil)) @@ -387,6 +384,13 @@ non-nil. Resets this variable after parsing is done." (javaimp--parse-scopes nil))))) (setq javaimp--parse-dirty-pos nil)))) +(defun javaimp--parse-ensure-buffer-setup () + ;; FIXME This may be done in major/minor mode setup + (when (eq javaimp--parse-dirty-pos 'init) + (setq javaimp--parse-dirty-pos (point-min)) + (setq syntax-ppss-table javaimp-syntax-table) + (add-hook 'after-change-functions #'javaimp--parse-update-dirty-pos))) + (defun javaimp--parse-class-abstract-methods () (goto-char (point-max)) (let (res) @@ -435,57 +439,46 @@ non-nil. Resets this variable after parsing is done." (setq javaimp--parse-dirty-pos beg))) -;; Functions intended to be called from other parts of javaimp. +;; Functions intended to be called from other parts of javaimp. They +;; do not preserve excursion / restriction - it's the caller's +;; responsibility. (defun javaimp--parse-get-package () "Return the package declared in the current file." - (save-excursion - (save-restriction - (widen) - (javaimp--parse-all-scopes) - (goto-char (point-max)) - (when (javaimp--parse-rsb-keyword - "^[ \t]*package[ \t]+\\([^ \t;\n]+\\)[ \t]*;" nil t 1) - (match-string 1))))) + (javaimp--parse-all-scopes) + (goto-char (point-max)) + (when (javaimp--parse-rsb-keyword + "^[ \t]*package[ \t]+\\([^ \t;\n]+\\)[ \t]*;" nil t 1) + (match-string 1))) (defun javaimp--parse-get-all-scopes (&optional pred parent-pred) "Return all scopes in the current buffer, optionally filtering them with PRED, and their parents with PARENT-PRED. Neither of them should move point." - (save-excursion - (save-restriction - (widen) - (javaimp--parse-all-scopes) - (let ((pos (point-max)) - scope res) - (while (setq pos (previous-single-property-change pos 'javaimp-parse-scope)) - (setq scope (get-text-property pos 'javaimp-parse-scope)) - (when (and scope - (or (null pred) - (funcall pred scope))) - (setq scope (javaimp--copy-scope scope)) - (when parent-pred - (javaimp--filter-scope-parents scope parent-pred)) - (push scope res))) - res)))) + (javaimp--parse-all-scopes) + (let ((pos (point-max)) + scope res) + (while (setq pos (previous-single-property-change pos 'javaimp-parse-scope)) + (setq scope (get-text-property pos 'javaimp-parse-scope)) + (when (and scope + (or (null pred) + (funcall pred scope))) + (setq scope (javaimp--copy-scope scope)) + (when parent-pred + (javaimp--filter-scope-parents scope parent-pred)) + (push scope res))) + res)) (defun javaimp--parse-get-class-abstract-methods () - (save-excursion - (save-restriction - (widen) - (javaimp--parse-all-scopes) - (javaimp--parse-class-abstract-methods)))) + (javaimp--parse-all-scopes) + (javaimp--parse-class-abstract-methods)) (defun javaimp--parse-get-interface-abstract-methods () - (save-excursion - (save-restriction - (widen) - (let ((interfaces - (javaimp--parse-get-all-scopes - (lambda (scope) - (javaimp-test-scope-type scope - '(interface) javaimp--classlike-scope-types))))) - (seq-mapcat #'javaimp--parse-interface-abstract-methods - interfaces))))) + (let ((interfaces (javaimp--parse-get-all-scopes + (lambda (scope) + (javaimp-test-scope-type scope + '(interface) javaimp--classlike-scope-types))))) + (seq-mapcat #'javaimp--parse-interface-abstract-methods + interfaces))) (provide 'javaimp-parse) diff --git a/javaimp-tests.el b/javaimp-tests.el index f90c148..d102527 100644 --- a/javaimp-tests.el +++ b/javaimp-tests.el @@ -199,10 +199,10 @@ package commented.block; (defun javaimp-test--check-named-scopes () (let* ((scopes (javaimp--parse-get-all-scopes - (lambda (scope) - (memq (javaimp-scope-type scope) '(class interface enum method))) - (lambda (scope) - (memq (javaimp-scope-type scope) '(class interface enum method))))) + (lambda (s) + (memq (javaimp-scope-type s) '(class interface enum method))) + (lambda (s) + (memq (javaimp-scope-type s) '(class interface enum method))))) (actual (mapcar (lambda (s) (let (res) @@ -284,13 +284,13 @@ package commented.block; -;; Tests for javaimp--get-file-classes-1 +;; Tests for javaimp--get-classes -(ert-deftest javaimp-test--get-file-classes () +(ert-deftest javaimp-test--get-classes () (with-temp-buffer (insert-file-contents (concat javaimp--basedir "testdata/test1-misc-classes.java")) - (should (equal (javaimp--get-file-classes-1) + (should (equal (javaimp--get-classes) '("org.foo.Top" "org.foo.Top.CInner1" "org.foo.Top.CInner1.CInner1_CInner1" diff --git a/javaimp.el b/javaimp.el index 3397d8c..0cc7ade 100644 --- a/javaimp.el +++ b/javaimp.el @@ -453,12 +453,13 @@ prefix arg is given, don't do this filtering." javaimp-additional-source-dirs))) (defun javaimp--dir-above-current-package () - (let ((package (javaimp--parse-get-package))) - (when package - (string-remove-suffix - (mapconcat #'file-name-as-directory - (split-string package "\\." t) nil) - default-directory)))) + (when-let ((package (save-excursion + (save-restriction + (widen) + (javaimp--parse-get-package))))) + (string-remove-suffix + (mapconcat #'file-name-as-directory (split-string package "\\." t) nil) + default-directory))) (defun javaimp--get-directory-classes (dir) (when (file-accessible-directory-p dir) @@ -468,16 +469,17 @@ prefix arg is given, don't do this filtering." (directory-files-recursively dir "\\.java\\'"))))) (defun javaimp--get-file-classes (file) - (let ((buf (seq-find (lambda (b) (equal (buffer-file-name b) file)) - (buffer-list)))) - (if buf - (with-current-buffer buf - (javaimp--get-file-classes-1)) - (with-temp-buffer - (insert-file-contents file) - (javaimp--get-file-classes-1))))) - -(defun javaimp--get-file-classes-1 () + (if-let ((buf (get-file-buffer file))) + (with-current-buffer buf + (save-excursion + (save-restriction + (widen) + (javaimp--get-classes)))) + (with-temp-buffer + (insert-file-contents file) + (javaimp--get-classes)))) + +(defun javaimp--get-classes () "Return fully-qualified names of all class-like scopes." (let ((package (javaimp--parse-get-package)) (scopes (javaimp--parse-get-all-scopes @@ -748,7 +750,10 @@ start (`javaimp-scope-start') instead." (defun javaimp-help-show-scopes () "Show scopes in a *javaimp-scopes* buffer." (interactive) - (let ((scopes (javaimp--parse-get-all-scopes)) + (let ((scopes (save-excursion + (save-restriction + (widen) + (javaimp--parse-get-all-scopes)))) (file buffer-file-name) (buf (get-buffer-create "*javaimp-scopes*"))) (with-current-buffer buf