Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
5.8 KiB

пре 4 година
  1. ;;; cider-resolve.el --- Resolve clojure symbols according to current nREPL connection
  2. ;; Copyright © 2015-2019 Bozhidar Batsov, Artur Malabarba and CIDER contributors
  3. ;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
  4. ;; This program is free software; you can redistribute it and/or modify
  5. ;; it under the terms of the GNU General Public License as published by
  6. ;; the Free Software Foundation, either version 3 of the License, or
  7. ;; (at your option) any later version.
  8. ;; This program is distributed in the hope that it will be useful,
  9. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. ;; GNU General Public License for more details.
  12. ;; You should have received a copy of the GNU General Public License
  13. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. ;;; Commentary:
  15. ;; The ns cache is a dict of namespaces stored in the connection buffer. This
  16. ;; file offers functions to easily get information about variables from this
  17. ;; cache, given the variable's name and the file's namespace. This
  18. ;; functionality is similar to that offered by the `cider-var-info' function
  19. ;; (and others). The difference is that all functions in this file operate
  20. ;; without contacting the server (they still rely on an active connection
  21. ;; buffer, but no messages are actually exchanged).
  22. ;; For this reason, the functions here are well suited for very
  23. ;; performance-sentitive operations, such as font-locking or
  24. ;; indentation. Meanwhile, operations like code-jumping are better off
  25. ;; communicating with the middleware, just in the off chance that the cache is
  26. ;; outdated.
  27. ;; Below is a typical entry on this cache dict. Note that clojure.core symbols
  28. ;; are excluded from the refers to save space.
  29. ;; "cider.nrepl.middleware.track-state"
  30. ;; (dict "aliases"
  31. ;; (dict "cljs" "cider.nrepl.middleware.util.cljs"
  32. ;; "misc" "cider.nrepl.middleware.util.misc"
  33. ;; "set" "clojure.set")
  34. ;; "interns" (dict a
  35. ;; "assoc-state" (dict "arglists"
  36. ;; (("response"
  37. ;; (dict "as" "msg" "keys"
  38. ;; ("session")))))
  39. ;; "filter-core" (dict "arglists"
  40. ;; (("refers")))
  41. ;; "make-transport" (dict "arglists"
  42. ;; (((dict "as" "msg" "keys"
  43. ;; ("transport")))))
  44. ;; "ns-as-map" (dict "arglists"
  45. ;; (("ns")))
  46. ;; "ns-cache" (dict)
  47. ;; "relevant-meta" (dict "arglists"
  48. ;; (("var")))
  49. ;; "update-vals" (dict "arglists"
  50. ;; (("m" "f")))
  51. ;; "wrap-tracker" (dict "arglists"
  52. ;; (("handler"))))
  53. ;; "refers" (dict "set-descriptor!" "#'nrepl.middleware/set-descriptor!"))
  54. ;;; Code:
  55. (require 'cider-client)
  56. (require 'nrepl-dict)
  57. (require 'cider-util)
  58. (defvar cider-repl-ns-cache)
  59. (defun cider-resolve--get-in (&rest keys)
  60. "Return (nrepl-dict-get-in cider-repl-ns-cache KEYS)."
  61. (when-let* ((conn (cider-current-repl)))
  62. (with-current-buffer conn
  63. (nrepl-dict-get-in cider-repl-ns-cache keys))))
  64. (defun cider-resolve-alias (ns alias)
  65. "Return the namespace that ALIAS refers to in namespace NS.
  66. If it doesn't point anywhere, returns ALIAS."
  67. (or (cider-resolve--get-in ns "aliases" alias)
  68. alias))
  69. (defconst cider-resolve--prefix-regexp "\\`\\(?:#'\\)?\\([^/]+\\)/")
  70. (defun cider-resolve-var (ns var)
  71. "Return a dict of the metadata of a clojure var VAR in namespace NS.
  72. VAR is a string.
  73. Return nil only if VAR cannot be resolved."
  74. (let* ((var-ns (when (string-match cider-resolve--prefix-regexp var)
  75. (cider-resolve-alias ns (match-string 1 var))))
  76. (name (replace-regexp-in-string cider-resolve--prefix-regexp "" var)))
  77. (or
  78. (cider-resolve--get-in (or var-ns ns) "interns" name)
  79. (unless var-ns
  80. ;; If the var had no prefix, it might be referred.
  81. (if-let* ((referral (cider-resolve--get-in ns "refers" name)))
  82. (cider-resolve-var ns referral)
  83. ;; Or it might be from core.
  84. (unless (equal ns "clojure.core")
  85. (cider-resolve-var "clojure.core" name)))))))
  86. (defun cider-resolve-core-ns ()
  87. "Return a dict of the core namespace for current connection.
  88. This will be clojure.core or cljs.core depending on the return value of the
  89. function `cider-repl-type'."
  90. (when-let* ((repl (cider-current-repl)))
  91. (with-current-buffer repl
  92. (cider-resolve--get-in (if (eq cider-repl-type 'cljs)
  93. "cljs.core"
  94. "clojure.core")))))
  95. (defun cider-resolve-ns-symbols (ns)
  96. "Return a plist of all valid symbols in NS.
  97. Each entry's value is the metadata of the var that the symbol refers to.
  98. NS can be the namespace name, or a dict of the namespace itself."
  99. (when-let* ((dict (if (stringp ns)
  100. (cider-resolve--get-in ns)
  101. ns)))
  102. (nrepl-dbind-response dict (interns refers aliases)
  103. (append (cdr interns)
  104. (nrepl-dict-flat-map (lambda (alias namespace)
  105. (nrepl-dict-flat-map (lambda (sym meta)
  106. (list (concat alias "/" sym) meta))
  107. (cider-resolve--get-in namespace "interns")))
  108. aliases)))))
  109. (provide 'cider-resolve)
  110. ;;; cider-resolve.el ends here