From 99875accc0e113d3fa5af73a79a4462c7118fa0a Mon Sep 17 00:00:00 2001 From: Arne Brasseur Date: Tue, 7 Sep 2021 16:14:20 +0200 Subject: [PATCH] Fix info lookups from namespaces that don't yet exist Currently when doing a `var-info` from a file before evaluating the `ns` form always fails. The namespace object does not yet exist, and so none of the var resolution strategies work. However fully-qualified vars, namespace names, or built-ins (clojure.core functions) could all be resolved, and it's frustrating that they aren't. This adds a check to see if `(find-ns ns)` returns anything. If not then we are initiating the lookup from a namespace that has not yet been defined, in which case none of the lookup strategies will proceed, so we continue with doing the lookup as if it had been initiated from `clojure.core`. --- CHANGELOG.md | 4 ++++ src/orchard/info.clj | 48 +++++++++++++++++++++----------------- test/orchard/info_test.clj | 16 +++++++++++++ 3 files changed, 46 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ebf1ed1..4b6db737 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ * `orchard.namespace` functionality is now parallelized when possible. +### Bugs Fixed + +* [#123](https://github.com/clojure-emacs/orchard/pull/123): Fix info lookups from namespaces that don't yet exist + ## 0.7.1 (2021-04-18) ### Bugs Fixed diff --git a/src/orchard/info.clj b/src/orchard/info.clj index 3ce6d09e..e02dec39 100644 --- a/src/orchard/info.clj +++ b/src/orchard/info.clj @@ -63,30 +63,34 @@ (defn clj-meta {:added "0.5"} - [{:keys [dialect ns sym computed-ns unqualified-sym]}] + [{:keys [dialect ns sym computed-ns unqualified-sym] :as opts}] {:pre [(= dialect :clj)]} (let [ns (or ns computed-ns)] - (or - ;; it's a special (special-symbol?) - (m/special-sym-meta sym) - ;; it's a var - (some-> ns (m/resolve-var sym) (m/var-meta)) - ;; it's a Java constructor/static member symbol - (some-> ns (java/resolve-symbol sym)) - ;; it's an unqualified sym maybe referred - (some-> ns (m/resolve-var unqualified-sym) (m/var-meta)) - ;; it's a Java class/record type symbol - (some-> ns (java/resolve-type unqualified-sym)) - ;; it's an alias for another ns - (some-> ns (m/resolve-aliases) (get sym) (m/ns-meta)) - ;; We use :unqualified-sym *exclusively* here because because our :ns is - ;; too ambiguous. - ;; - ;; Observe the incorrect behavior (should return nil, there is a test): - ;; - ;; (info '{:ns clojure.core :sym non-existing}) ;;=> {:author "Rich Hickey" :ns clojure.core ...} - ;; - (some-> (find-ns unqualified-sym) (m/ns-meta))))) + (if-not (and ns (find-ns ns)) + ;; Lookups in files whose namespaces don't exist yet should still be able + ;; to resolve built-ins and fully-qualified syms + (recur (assoc opts :ns 'clojure.core)) + (or + ;; it's a special (special-symbol?) + (m/special-sym-meta sym) + ;; it's a var + (some-> ns (m/resolve-var sym) (m/var-meta)) + ;; it's a Java constructor/static member symbol + (some-> ns (java/resolve-symbol sym)) + ;; it's an unqualified sym maybe referred + (some-> ns (m/resolve-var unqualified-sym) (m/var-meta)) + ;; it's a Java class/record type symbol + (some-> ns (java/resolve-type unqualified-sym)) + ;; it's an alias for another ns + (some-> ns (m/resolve-aliases) (get sym) (m/ns-meta)) + ;; We use :unqualified-sym *exclusively* here because because our :ns is + ;; too ambiguous. + ;; + ;; Observe the incorrect behavior (should return nil, there is a test): + ;; + ;; (info '{:ns clojure.core :sym non-existing}) ;;=> {:author "Rich Hickey" :ns clojure.core ...} + ;; + (some-> (find-ns unqualified-sym) (m/ns-meta)))))) (defn cljs-meta {:added "0.5"} diff --git a/test/orchard/info_test.clj b/test/orchard/info_test.clj index c36b92c1..25e7d3a7 100644 --- a/test/orchard/info_test.clj +++ b/test/orchard/info_test.clj @@ -467,6 +467,22 @@ :returns int})) (is (re-find #"Returns the greater of two" (:doc i)))))) +(deftest info-undefined-namespace-test + (testing "Fully qualified sym can still be resolved" + (is (= '{:added "1.2" + :ns clojure.string + :name upper-case + :file "clojure/string.clj"} + (select-keys (info/info* {:ns 'gibberish :sym 'clojure.string/upper-case}) + [:added :ns :name :file])))) + (testing "clojure.core syms can still be resolved" + (is (= '{:added "1.0" + :ns clojure.core + :name merge + :file "clojure/core.clj"} + (select-keys (info/info* {:ns 'gibberish :sym 'merge}) + [:added :ns :name :file]))))) + (deftest javadoc-info-unit-test (testing "Get an HTTP URL for a Sun/Oracle Javadoc" (testing "Javadoc 1.7 format"