From 498e297146fce60b9cd0e07e16f3b6186fa6fb4b Mon Sep 17 00:00:00 2001 From: Vadim Rodionov Date: Sat, 16 Jul 2022 19:40:31 +0600 Subject: [PATCH 1/6] Fix infinite loop when typing var metadata before its name --- clojure-mode.el | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clojure-mode.el b/clojure-mode.el index 90fc6bdf..92f7f9ce 100644 --- a/clojure-mode.el +++ b/clojure-mode.el @@ -754,13 +754,13 @@ Called by `imenu--generic-function'." (when (char-equal ?\) (char-after (point))) (backward-sexp))) (cl-destructuring-bind (def-beg . def-end) (bounds-of-thing-at-point 'sexp) - (if (char-equal ?^ (char-after def-beg)) - (progn (forward-sexp) (backward-sexp)) + (when (char-equal ?^ (char-after def-beg)) + (progn (forward-sexp) (backward-sexp))) + (when (or (not (char-equal ?^ (char-after (point)))) + (and (char-equal ?^ (char-after (point))) (= def-beg (point)))) (setq found? t) (when (string= deftype "defmethod") - (setq def-end (progn (goto-char def-end) - (forward-sexp) - (point)))) + (setq def-end (progn (goto-char def-end)))) (set-match-data (list def-beg def-end))))) (goto-char start))))) From 01883b9d195303a2982ccfd7c01c38f026c1b48e Mon Sep 17 00:00:00 2001 From: Vadim Rodionov Date: Sat, 16 Jul 2022 21:41:31 +0600 Subject: [PATCH 2/6] Add tests for clojure-match-next-def --- test.clj | 4 ++++ test/clojure-mode-syntax-test.el | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/test.clj b/test.clj index 147171a1..a1d67dfa 100644 --- a/test.clj +++ b/test.clj @@ -223,6 +223,10 @@ ([x y & more] (reduce1 max (max x y) more))) + +;; definitions with metadata only don't cause freezing +(def ^String) + (defn ^String reverse "Returns s with its characters reversed." {:added "1.2"} diff --git a/test/clojure-mode-syntax-test.el b/test/clojure-mode-syntax-test.el index bc71eaab..db4d6ec8 100644 --- a/test/clojure-mode-syntax-test.el +++ b/test/clojure-mode-syntax-test.el @@ -60,6 +60,36 @@ (expect (non-func "^hint " form) :to-be nil) (expect (non-func "#macro " form) :to-be nil)))) +(describe "clojure-match-next-def" + (it "handles vars with metadata" + (with-clojure-buffer " +(def ^Integer a 1) +(list [1 2 3])" + (end-of-buffer) + (clojure-match-next-def) + (expect (looking-at "(def")))) + (it "handles vars with metadata only" + (with-clojure-buffer " +(def ^Integer) +(list [1 2 3])" + (end-of-buffer) + (clojure-match-next-def) + (expect (looking-at "(def")))) + (it "handles vars without metadata" + (with-clojure-buffer " +(def a 1) +(list [1 2 3])" + (end-of-buffer) + (clojure-match-next-def) + (expect (looking-at "(def")))) + (it "handles empty def forms" + (with-clojure-buffer " +(def) +(list [1 2 3])" + (end-of-buffer) + (clojure-match-next-def) + (expect (looking-at "(def"))))) + (describe "clojure syntax" (it "handles prefixed symbols" (dolist (form '(("#?@aaa" . "aaa") From f3574213eda5ec9ad28ae598c6496a1d35a4b084 Mon Sep 17 00:00:00 2001 From: Vadim Rodionov Date: Sat, 16 Jul 2022 22:20:32 +0600 Subject: [PATCH 3/6] Mention issues #595 and #612 in changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebcf9bdc..2d559620 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ * [#622](https://github.com/clojure-emacs/clojure-mode/issues/622): Add font locking for missing clojure.core macros * [#615](https://github.com/clojure-emacs/clojure-mode/issues/615): Support clojure-dart files. +### Bugs fixed + +* [#595](https://github.com/clojure-emacs/clojure-mode/issues/595), [#612](https://github.com/clojure-emacs/clojure-mode/issues/612): Fix buffer freezing when typing metadata for a definition + ## 5.14.0 (2022-03-07) ### New features From 4fbeef0f0d2eb00c2955026c6ed1c11e36a0a625 Mon Sep 17 00:00:00 2001 From: Vadim Rodionov Date: Sat, 16 Jul 2022 22:20:53 +0600 Subject: [PATCH 4/6] Rollback accidentally commited changes --- clojure-mode.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clojure-mode.el b/clojure-mode.el index 0126f7d3..3e484603 100644 --- a/clojure-mode.el +++ b/clojure-mode.el @@ -760,7 +760,9 @@ Called by `imenu--generic-function'." (and (char-equal ?^ (char-after (point))) (= def-beg (point)))) (setq found? t) (when (string= deftype "defmethod") - (setq def-end (progn (goto-char def-end)))) + (setq def-end (progn (goto-char def-end) + (forward-sexp) + (point)))) (set-match-data (list def-beg def-end))))) (goto-char start))))) From 62b59be8bc83c0bf640c2fe936715f372b3512d1 Mon Sep 17 00:00:00 2001 From: Vadim Rodionov Date: Sun, 17 Jul 2022 12:32:46 +0600 Subject: [PATCH 5/6] Add comment explaining code that moves point to the beginning of next sexp when encounter metadata --- clojure-mode.el | 1 + 1 file changed, 1 insertion(+) diff --git a/clojure-mode.el b/clojure-mode.el index 3e484603..595ea0a0 100644 --- a/clojure-mode.el +++ b/clojure-mode.el @@ -755,6 +755,7 @@ Called by `imenu--generic-function'." (backward-sexp))) (cl-destructuring-bind (def-beg . def-end) (bounds-of-thing-at-point 'sexp) (when (char-equal ?^ (char-after def-beg)) + ;; move to the beginning of next sexp (progn (forward-sexp) (backward-sexp))) (when (or (not (char-equal ?^ (char-after (point)))) (and (char-equal ?^ (char-after (point))) (= def-beg (point)))) From 073d18e7009d012bc47c88227239ec4a20e7042f Mon Sep 17 00:00:00 2001 From: Vadim Rodionov Date: Sun, 17 Jul 2022 15:14:15 +0600 Subject: [PATCH 6/6] Add more test cases for clojure-match-next-def --- test/clojure-mode-syntax-test.el | 57 ++++++++++++++++---------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/test/clojure-mode-syntax-test.el b/test/clojure-mode-syntax-test.el index db4d6ec8..8ac8938f 100644 --- a/test/clojure-mode-syntax-test.el +++ b/test/clojure-mode-syntax-test.el @@ -61,34 +61,35 @@ (expect (non-func "#macro " form) :to-be nil)))) (describe "clojure-match-next-def" - (it "handles vars with metadata" - (with-clojure-buffer " -(def ^Integer a 1) -(list [1 2 3])" - (end-of-buffer) - (clojure-match-next-def) - (expect (looking-at "(def")))) - (it "handles vars with metadata only" - (with-clojure-buffer " -(def ^Integer) -(list [1 2 3])" - (end-of-buffer) - (clojure-match-next-def) - (expect (looking-at "(def")))) - (it "handles vars without metadata" - (with-clojure-buffer " -(def a 1) -(list [1 2 3])" - (end-of-buffer) - (clojure-match-next-def) - (expect (looking-at "(def")))) - (it "handles empty def forms" - (with-clojure-buffer " -(def) -(list [1 2 3])" - (end-of-buffer) - (clojure-match-next-def) - (expect (looking-at "(def"))))) + (let ((some-sexp "\n(list [1 2 3])")) + (it "handles vars with metadata" + (dolist (form '("(def ^Integer a 1)" + "(def ^:a a 1)" + "(def ^::a a 1)" + "(def ^::a/b a 1)" + "(def ^{:macro true} a 1)")) + (with-clojure-buffer (concat form some-sexp) + (end-of-buffer) + (clojure-match-next-def) + (expect (looking-at "(def"))))) + + (it "handles vars without metadata" + (with-clojure-buffer (concat "(def a 1)" some-sexp) + (end-of-buffer) + (clojure-match-next-def) + (expect (looking-at "(def")))) + + (it "handles invalid def forms" + (dolist (form '("(def ^Integer)" + "(def)" + "(def ^{:macro})" + "(def ^{:macro true})" + "(def ^{:macro true} foo)" + "(def ^{:macro} foo)")) + (with-clojure-buffer (concat form some-sexp) + (end-of-buffer) + (clojure-match-next-def) + (expect (looking-at "(def"))))))) (describe "clojure syntax" (it "handles prefixed symbols"