Skip to content

Fix ns detection for complex metadata #555

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions clojure-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -1888,6 +1888,11 @@ content) are considered part of the preceding sexp."
(zero-or-one (any ":'")) ;; (in-ns 'foo) or (ns+ :user)
(group (one-or-more (not (any "()\"" whitespace))) symbol-end)))

(make-obsolete-variable 'clojure-namespace-name-regex 'clojure-namespace-regexp "5.12.0")

(defconst clojure-namespace-regexp
(rx line-start "(" (? "clojure.core/") (or "in-ns" "ns" "ns+")))

(defcustom clojure-cache-ns nil
"Whether to cache the results of `clojure-find-ns'.

Expand All @@ -1911,9 +1916,16 @@ DIRECTION is `forward' or `backward'."
#'search-forward-regexp
#'search-backward-regexp)))
(while (and (not candidate)
(funcall fn clojure-namespace-name-regex nil t))
(unless (or (clojure--in-string-p) (clojure--in-comment-p))
(setq candidate (match-string-no-properties 4))))
(funcall fn clojure-namespace-regexp nil t))
(let ((end (match-end 0)))
(save-excursion
(save-match-data
(goto-char end)
(clojure-forward-logical-sexp)
(when (and (looking-back clojure--sym-regexp end 'greedy)
(not (clojure--in-string-p))
(not (clojure--in-comment-p)))
(setq candidate (match-string-no-properties 0)))))))
candidate))

(defun clojure-find-ns ()
Expand Down Expand Up @@ -1982,7 +1994,7 @@ Returns a list pair, e.g. (\"defn\" \"abc\") or (\"deftest\" \"some-test\")."
\"Non-logical\" sexp are ^metadata and #reader.macros."
(comment-normalize-vars)
(comment-forward (point-max))
(looking-at-p "\\^\\|#:?:?[[:alpha:]]"))
(looking-at-p "\\(?:#?\\^\\)\\|#:?:?[[:alpha:]]"))

(defun clojure-forward-logical-sexp (&optional n)
"Move forward N logical sexps.
Expand Down
92 changes: 51 additions & 41 deletions test/clojure-mode-util-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -57,47 +57,57 @@
(clojure-expected-ns))
clj-file-ns))))))

(describe "clojure-namespace-name-regex"
(it "should match common namespace declarations"
(let ((ns "(ns foo)"))
(expect (string-match clojure-namespace-name-regex ns))
(match-string 4 ns))
(let ((ns "(ns
foo)"))
(expect (string-match clojure-namespace-name-regex ns))
(expect (match-string 4 ns) :to-equal "foo"))
(let ((ns "(ns foo.baz)"))
(expect (string-match clojure-namespace-name-regex ns))
(expect (match-string 4 ns) :to-equal "foo.baz"))
(let ((ns "(ns ^:bar foo)"))
(expect (string-match clojure-namespace-name-regex ns))
(expect (match-string 4 ns) :to-equal "foo"))
(let ((ns "(ns ^:bar ^:baz foo)"))
(expect (string-match clojure-namespace-name-regex ns))
(expect (match-string 4 ns) :to-equal "foo"))
(let ((ns "(ns ^{:bar true} foo)"))
(expect (string-match clojure-namespace-name-regex ns))
(expect (match-string 4 ns) :to-equal "foo"))
(let ((ns "(ns #^{:bar true} foo)"))
(expect (string-match clojure-namespace-name-regex ns))
(expect (match-string 4 ns) :to-equal "foo"))
;; TODO
;; (let ((ns "(ns #^{:fail {}} foo)"))
;; (should (string-match clojure-namespace-name-regex ns))
;; (match-string 4 ns))
;; (let ((ns "(ns ^{:fail2 {}} foo.baz)"))
;; (should (string-match clojure-namespace-name-regex ns))
;; (should (equal "foo.baz" (match-string 4 ns))))
(let ((ns "(ns ^{} foo)"))
(expect (string-match clojure-namespace-name-regex ns))
(expect (match-string 4 ns) :to-equal "foo"))
(let ((ns "(ns ^{:skip-wiki true}
aleph.netty"))
(expect (string-match clojure-namespace-name-regex ns))
(expect (match-string 4 ns) :to-equal "aleph.netty"))
(let ((ns "(ns foo+)"))
(expect (string-match clojure-namespace-name-regex ns))
(expect (match-string 4 ns) :to-equal "foo+"))))
(describe "clojure-find-ns"
(it "should find common namespace declarations"
(with-clojure-buffer "(ns foo)"
(expect (clojure-find-ns) :to-equal "foo"))
(with-clojure-buffer "(ns
foo)"
(expect (clojure-find-ns) :to-equal "foo"))
(with-clojure-buffer "(ns foo.baz)"
(expect (clojure-find-ns) :to-equal "foo.baz"))
(with-clojure-buffer "(ns ^:bar foo)"
(expect (clojure-find-ns) :to-equal "foo"))
(with-clojure-buffer "(ns ^:bar ^:baz foo)"
(expect (clojure-find-ns) :to-equal "foo")))
(it "should find namespace declarations with nested metadata and docstrings"
(with-clojure-buffer "(ns ^{:bar true} foo)"
(expect (clojure-find-ns) :to-equal "foo"))
(with-clojure-buffer "(ns #^{:bar true} foo)"
(expect (clojure-find-ns) :to-equal "foo"))
(with-clojure-buffer "(ns #^{:fail {}} foo)"
(expect (clojure-find-ns) :to-equal "foo"))
(with-clojure-buffer "(ns ^{:fail2 {}} foo.baz)"
(expect (clojure-find-ns) :to-equal "foo.baz"))
(with-clojure-buffer "(ns ^{} foo)"
(expect (clojure-find-ns) :to-equal "foo"))
(with-clojure-buffer "(ns ^{:skip-wiki true}
aleph.netty"
(expect (clojure-find-ns) :to-equal "aleph.netty"))
(with-clojure-buffer "(ns ^{:foo {:bar :baz} :fake (ns in.meta)} foo
\"docstring
(ns misleading)\")"
(expect (clojure-find-ns) :to-equal "foo")))
(it "should support non-alphanumeric characters"
(with-clojure-buffer "(ns foo+)"
(expect (clojure-find-ns) :to-equal "foo+"))
(with-clojure-buffer "(ns bar**baz$-_quux)"
(expect (clojure-find-ns) :to-equal "bar**baz$-_quux")))
(it "should support in-ns forms"
(with-clojure-buffer "(in-ns 'bar.baz)"
(expect (clojure-find-ns) :to-equal "bar.baz")))
(it "should take the closest ns before point"
(with-clojure-buffer " (ns foo1)

(ns foo2)"
(expect (clojure-find-ns) :to-equal "foo2"))
(with-clojure-buffer " (in-ns foo1)
(ns 'foo2)
(in-ns 'foo3)
|
(ns foo4)"
(re-search-backward "|")
(expect (clojure-find-ns) :to-equal "foo3"))))

(describe "clojure-sort-ns"
(it "should sort requires in a basic ns"
Expand Down