Skip to content
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

Also consider cljc files for namespaces-on-classpath #91

Merged
merged 1 commit into from
Jun 17, 2023
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
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 deprecated) takes cljc files into account.
Add replacement `compliment.utils/namespaces&files-on-classpath` that yields a collection of maps containing the filename.

### 0.3.14 (2022-07-11)

Expand Down
11 changes: 6 additions & 5 deletions src/compliment/sources/namespaces_and_classes.clj
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,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)
:when (if has-dot
(nscl-matches? prefix ns-str)
(.startsWith ns-str prefix))]
{:candidate ns-str, :type :namespace})
(for [{:keys [^String ns-str, ^String file]} (utils/namespaces&files-on-classpath)
:when (and (re-find #"\.cljc?$" file)
(if has-dot
(nscl-matches? prefix ns-str)
(.startsWith ns-str prefix)))]
{:candidate ns-str, :type :namespace, :file file})
;; 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
34 changes: 20 additions & 14 deletions src/compliment/utils.clj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
Note that should always have the same value, regardless of OS."
"/")

(defn- ensure-no-leading-slash [file]
(if (.startsWith file File/separator)
(.substring file 1) file))

(defn fuzzy-matches?
"Tests if symbol matches the prefix when symbol is split into parts on
separator."
Expand Down Expand Up @@ -181,25 +185,28 @@ Note that should always have the same value, regardless of OS."
(->> (for [^String file (all-files-on-classpath classpath)
:when (and (.endsWith file ".class") (not (.contains file "__"))
(not (.contains file "$")))]
(.. (if (.startsWith file File/separator)
(.substring file 1) file)
(.. (ensure-no-leading-slash file)
(replace ".class" "")
;; Address the issue #79 , on Windows, for prefix such
;; as "java.util.", the list of candidates was empty.
(replace resource-separator ".")))
(group-by #(subs % 0 (max (.indexOf ^String % ".") 0)))))))

(defn namespaces-on-classpath
"Returns the list of all Clojure namespaces obtained by classpath scanning."
(defn namespaces&files-on-classpath
"Returns a collection of maps (e.g. `{:ns-str \"some.ns\", :file \"some/ns.cljs\"}`) of all clj/cljc/cljs 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 "_" "-")))))))
;; TODO deduplicate these results by ns-str
(for [file (all-files-on-classpath classpath)
:let [file (ensure-no-leading-slash file)
[_ ^String nsname] (re-matches #"[^\w]?(.+)\.clj[sc]?$" file)]
:when nsname]
(let [ns-str (.. nsname (replace resource-separator ".") (replace "_" "-"))]
{:ns-str ns-str, :file file})))))

(defn ^:deprecated namespaces-on-classpath []
(transduce (map :ns-str) conj #{} (namespaces&files-on-classpath)))

(defn project-resources
"Returns a list of all non-code files in the current project."
Expand All @@ -208,9 +215,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")
(.endsWith file ".jar") (.endsWith file ".class")))]
:when (not (or (empty? file)
(re-find #"\.(clj[cs]?|jar|class)$" file)))]
;; resource pathes always use "/" regardless of platform
(.. (if (.startsWith file File/separator)
(.substring file 1) file)
(.. (ensure-no-leading-slash file)
(replace File/separator resource-separator))))))
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, :file "clojure/java/browse.clj"}
{:candidate "clojure.java.shell", :type :namespace, :file "clojure/java/shell.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" :file "clojure/test/tap.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&files-on-classpath-test
(is (contains? (set (namespaces&files-on-classpath))
{:ns-str "compliment.t-utils" :file "compliment/t_utils.clj"}))
(is (contains? (set (namespaces&files-on-classpath))
{:ns-str "dummy" :file "dummy.cljs"})))
2 changes: 2 additions & 0 deletions test/dummy.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
;; To test compliment.utils/namespaces&files-on-classpath
(ns dummy)