Skip to content

Commit

Permalink
namespaces-on-classpath yields also cljc candidates
Browse files Browse the repository at this point in the history
...and allows for cljs candidates.
  • Loading branch information
eval committed Jun 15, 2023
1 parent 42c4c1d commit 74c4f1e
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 16 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
- Complete fully-qualified classnames by their shortname prefix anywhere in the
file (previously worked only in the `:import` section of the `ns` form).
- Fix ' and #' being swallowed when completing vars prefixed by them.
- [#91](https://github.com/alexander-yakushev/compliment/pull/91): `compliment.utils/namespaces-on-classpath`
now includes namespaces from cljc. `extensions`-option allows for cljs namespaces.

### 0.3.14 (2022-07-11)

Expand Down
5 changes: 3 additions & 2 deletions src/compliment/sources/namespaces_and_classes.clj
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,12 @@
(get-all-full-names prefix))
;; If prefix doesn't contain a period, using fuziness produces too many
;; irrelevant candidates.
(for [^String ns-str (utils/namespaces-on-classpath)
(for [{^String ns-str :ns, ^String ext :extension}
(utils/namespaces-on-classpath {:name-only false, :extensions #{"clj" "cljc"}})
:when (if has-dot
(nscl-matches? prefix ns-str)
(.startsWith ns-str prefix))]
{:candidate ns-str, :type :namespace})
{:candidate ns-str, :type :namespace, :extension ext})
;; Fuzziness is too slow for all classes, so only startsWith. Also, if no
;; period in prefix, only complete root package names to maintain good
;; performance and not produce too many candidates.
Expand Down
33 changes: 22 additions & 11 deletions src/compliment/utils.clj
Original file line number Diff line number Diff line change
Expand Up @@ -190,16 +190,26 @@ Note that should always have the same value, regardless of OS."
(group-by #(subs % 0 (max (.indexOf ^String % ".") 0)))))))

(defn namespaces-on-classpath
"Returns the list of all Clojure namespaces obtained by classpath scanning."
[]
(let [classpath (classpath)]
(cache-last-result ::namespaces-on-classpath classpath
(set (for [^String file (all-files-on-classpath classpath)
:when (and (.endsWith file ".clj")
(not (.startsWith file "META-INF")))
:let [[_ ^String nsname] (re-matches #"[^\w]?(.+)\.clj" file)]
:when nsname]
(.. nsname (replace resource-separator ".") (replace "_" "-")))))))
"Returns the list of all clj(c) namespaces obtained by classpath scanning.
Options:
- `extensions` (default `#{\"clj\", \"cljc\"}`) - collection of extensions to filter namespaces on. Should be subset of `#{\"clj\", \"cljc\", \"cljs\"}`.
- `name-only` (default `true`) - set to `false` to receive map with `:ns` and `:extension`."
([] (namespaces-on-classpath nil))
([{:keys [extensions name-only] :or {name-only true, extensions #{"clj" "cljc"}}}]
(let [classpath (classpath)
extensions (set extensions)]
(cond->> (cache-last-result ::namespaces-on-classpath classpath
(for [^String file (all-files-on-classpath classpath)
:when (and (or (.endsWith file ".clj") (.endsWith file ".cljc") (.endsWith file ".cljs"))
(not (.startsWith file "META-INF")))
:let [[_ ^String nsname ^String extension] (re-matches #"[^\w]?(.+)\.(clj[sc]?)" file)]
:when nsname]
(let [ns-str (.. nsname (replace resource-separator ".") (replace "_" "-"))]
{:ns ns-str, :extension extension})))
extensions (filter (comp extensions :extension))
name-only (map :ns)
:always set))))

(defn project-resources
"Returns a list of all non-code files in the current project."
Expand All @@ -208,7 +218,8 @@ Note that should always have the same value, regardless of OS."
(cache-last-result ::project-resources classpath
(for [path classpath
^String file (list-files path false)
:when (not (or (empty? file) (.endsWith file ".clj")
:when (not (or (empty? file)
(.endsWith file ".clj") (.endsWith file ".cljc") (.endsWith file ".cljs")
(.endsWith file ".jar") (.endsWith file ".class")))]
;; resource pathes always use "/" regardless of platform
(.. (if (.startsWith file File/separator)
Expand Down
4 changes: 2 additions & 2 deletions test/compliment/sources/t_namespaces_and_classes.clj
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
=> (just ["src"])

(src/candidates "clojure.java." (-ns) nil)
=> (contains #{{:candidate "clojure.java.browse", :type :namespace}
{:candidate "clojure.java.shell", :type :namespace}} :gaps-ok)
=> (contains #{{:candidate "clojure.java.browse", :type :namespace :extension "clj"}
{:candidate "clojure.java.shell", :type :namespace :extension "clj"}} :gaps-ok)

(src/candidates "java.io.Stri" (-ns) nil)
=> (contains #{{:candidate "java.io.StringReader", :type :class}
Expand Down
2 changes: 1 addition & 1 deletion test/compliment/t_core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@

;; Test for not required namespaces
(core/completions "cl.test.ta" {}) =>
(just [{:type :namespace, :candidate "clojure.test.tap"}])
(just [{:type :namespace, :candidate "clojure.test.tap" :extension "clj"}])

;; Test for aliases
(core/completions "cor" {:ns 'compliment.t-core})
Expand Down
6 changes: 6 additions & 0 deletions test/compliment/t_utils.clj
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,9 @@
(is (contains? all-classes "java.lang.Thread"))
(is (contains? all-classes "java.io.File"))
(is (contains? all-classes "java.nio.channels.FileChannel"))))

(deftest namespaces-on-classpath-test
(is (contains? (namespaces-on-classpath {:extensions #{"clj"}}) "compliment.t-utils"))
(is (= #{"dummy"} (namespaces-on-classpath {:extensions #{"cljs"}})))
(is (= #{{:ns "dummy" :extension "cljs"}}
(namespaces-on-classpath {:extensions #{"cljs"} :name-only false}))))
2 changes: 2 additions & 0 deletions test/dummy.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
;; For testing (compliment.t-utils) purpose
(ns dummy)

0 comments on commit 74c4f1e

Please sign in to comment.