Repository: clojure-lsp/clojure-lsp (clojure)

Issue:
textDocument/references not returning declaration in results when includeDeclaration is true
I'm not sure if this is a problem or I'm misunderstanding the protocol. It seems that with the `textDocument/references` request, if `includeDeclaration` is set to true it should return the declaration as a reference.

With the following code:

```clojure
(ns windows
  (:require [hiccup.core :as h]))

(def hello "world")

(comment
  hello)
```

If I find references on the bottom reference of `hello`, the following request and response occur:

```
[Trace - 5:39:36 PM] Sending request 'textDocument/references - (67)'.
Params: {
    "textDocument": {
        "uri": "file:///home/brandon/development/clojure-test/src/windows.clj"
    },
    "position": {
        "line": 6,
        "character": 4
    },
    "context": {
        "includeDeclaration": true
    }
}


[Trace - 5:39:36 PM] Received response 'textDocument/references - (67)' in 3ms.
Result: [
    {
        "uri": "file:///home/brandon/development/clojure-test/src/windows.clj",
        "range": {
            "start": {
                "line": 6,
                "character": 2
            },
            "end": {
                "line": 6,
                "character": 7
            }
        }
    }
]
```

It seems the results should include the declaration as well as the bottom reference, but only the bottom reference is returned. This is true if I call find references on the declaration `hello` as well.

Pull request:
#fixes #257 

- Add support for includeDeclaration on references
- Refactor references to use j/from-java
- add tests for references

Patch:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 12c39b723..5f1044dd7 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,12 +1,13 @@
 name: Release
 
 on:
-  create:
+  push:
     tags:
       - 2*
 
 jobs:
   release:
+    if: github.event.base_ref == 'refs/heads/master'
     name: Create Release
     runs-on: ubuntu-latest
     steps:
diff --git a/src/clojure_lsp/feature/call_hierarchy.clj b/src/clojure_lsp/feature/call_hierarchy.clj
index b64cc736a..19319ee1b 100644
--- a/src/clojure_lsp/feature/call_hierarchy.clj
+++ b/src/clojure_lsp/feature/call_hierarchy.clj
@@ -45,7 +45,7 @@
          :usage (f.references/find-under-cursor parent-row parent-col local-env file-type)}))))
 
 (defn incoming [uri row col project-root]
-  (->> (f.references/reference-usages uri row col)
+  (->> (f.references/reference-usages uri row col false)
        (map usage-by-uri->incoming-usage-by-uri)
        (remove nil?)
        (mapv (fn [usage-by-uri]
diff --git a/src/clojure_lsp/feature/refactor.clj b/src/clojure_lsp/feature/refactor.clj
index d7a82b4b3..e210f8fc5 100644
--- a/src/clojure_lsp/feature/refactor.clj
+++ b/src/clojure_lsp/feature/refactor.clj
@@ -43,7 +43,7 @@
 
 (defmethod refactor :inline-symbol [{:keys [uri row col]}]
   (let [usage (f.definition/definition-usage uri row col)
-        references (f.references/reference-usages uri row col)]
+        references (f.references/reference-usages uri row col false)]
     (r.transform/inline-symbol usage references)))
 
 (defmethod refactor :introduce-let [{:keys [loc args]}]
diff --git a/src/clojure_lsp/feature/references.clj b/src/clojure_lsp/feature/references.clj
index 16a27ca71..35c7ba382 100644
--- a/src/clojure_lsp/feature/references.clj
+++ b/src/clojure_lsp/feature/references.clj
@@ -29,17 +29,23 @@
              (sort-by (comp keyword? :sym)))
         (nth 0 nil))))
 
-(defn reference-usages [doc-id line column]
+(defn reference-usages [doc-id row col include-declaration?]
   (let [file-envs (:file-envs @db/db)
         local-env (get file-envs doc-id)
-        {cursor-sym :sym} (find-under-cursor line column local-env (shared/uri->file-type doc-id))]
-    (into []
-          (for [[uri usages] (:file-envs @db/db)
-                {:keys [sym tags] :as usage} usages
-                :when (and (= sym cursor-sym)
-                           (not (contains? tags :declare)))]
-            {:uri uri
-             :usage usage}))))
+        cursor (find-under-cursor row col local-env (shared/uri->file-type doc-id))]
+    (cond-> []
+
+      include-declaration?
+      (conj {:uri doc-id
+             :usage cursor})
+
+      :always
+      (into (for [[uri usages] (:file-envs @db/db)
+                  {:keys [sym tags] :as usage} usages
+                  :when (and (= sym (:sym cursor))
+                             (not (contains? tags :declare)))]
+              {:uri uri
+               :usage usage})))))
 
 (defn safe-find-references
   ([uri text]
diff --git a/src/clojure_lsp/handlers.clj b/src/clojure_lsp/handlers.clj
index 72010909d..b99d24c1d 100644
--- a/src/clojure_lsp/handlers.clj
+++ b/src/clojure_lsp/handlers.clj
@@ -120,10 +120,13 @@
   (let [file-envs (:file-envs @db/db)]
     (f.completion/resolve-item label sym-wanted file-envs)))
 
-(defn references [doc-id line column]
-  (mapv (fn [{:keys [uri usage]}]
-          {:uri uri :range (shared/->range usage)})
-        (f.references/reference-usages doc-id line column)))
+(defn references [{:keys [textDocument position context]}]
+  (->> (f.references/reference-usages textDocument
+                                      (-> position :line inc)
+                                      (-> position :character inc)
+                                      (:includeDeclaration context))
+       (mapv (fn [{:keys [uri usage]}]
+               {:uri uri :range (shared/->range usage)}))))
 
 (defn did-close [uri]
   (swap! db/db #(-> %
@@ -378,7 +381,7 @@
   [range [doc-id row col]]
   {:range   range
    :command {:title   (-> doc-id
-                          (f.references/reference-usages row col)
+                          (f.references/reference-usages row col false)
                           count
                           (str " references"))
              :command "code-lens-references"
diff --git a/src/clojure_lsp/main.clj b/src/clojure_lsp/main.clj
index f3245a81c..5f64a317b 100644
--- a/src/clojure_lsp/main.clj
+++ b/src/clojure_lsp/main.clj
@@ -140,14 +140,10 @@
           (reify Supplier
             (get [this]
               (end
-                (try
-                  (let [doc-id (interop/document->decoded-uri (.getTextDocument params))
-                        pos (.getPosition params)
-                        line (inc (.getLine pos))
-                        column (inc (.getCharacter pos))]
-                    (interop/conform-or-log ::interop/references (#'handlers/references doc-id line column)))
-                  (catch Exception e
-                    (log/error e)))))))))
+                (->> params
+                     j/from-java
+                     handlers/references
+                     (interop/conform-or-log ::interop/references))))))))
 
   (^CompletableFuture completion [this ^CompletionParams params]
     (go :completion


Test patch:
diff --git a/test/clojure_lsp/features/references.clj b/test/clojure_lsp/features/references.clj
new file mode 100644
index 000000000..85736729c
--- /dev/null
+++ b/test/clojure_lsp/features/references.clj
@@ -0,0 +1,24 @@
+(ns clojure-lsp.features.references
+  (:require
+    [clojure-lsp.db :as db]
+    [clojure-lsp.feature.references :as f.references]
+    [clojure-lsp.parser :as parser]
+    [clojure.test :refer [deftest testing is]]))
+
+(deftest reference-usages-test
+  (testing "not including declaration"
+    (let [code "(let [something 1] something something)"
+          usages (parser/find-usages code :clj {})]
+      (reset! db/db {:documents {"file://a.clj" {:text code}}
+                     :file-envs {"file://a.clj" usages}})
+      (let [references (f.references/reference-usages "file://a.clj" 1 7 false)]
+        (is (= 2 (count references))))))
+  (testing "including declaration"
+    (let [code "(let [something 1] something something)"
+          usages (parser/find-usages code :clj {})]
+      (reset! db/db {:documents {"file://a.clj" {:text code}}
+                     :file-envs {"file://a.clj" usages}})
+      (let [references (f.references/reference-usages "file://a.clj" 1 7 true)]
+        (is (= 3 (count references)))
+        (is (= "something"
+               (first (map (comp :str :usage) references))))))))
diff --git a/test/clojure_lsp/handlers_test.clj b/test/clojure_lsp/handlers_test.clj
index c4ed8fa9f..0be76fc1b 100644
--- a/test/clojure_lsp/handlers_test.clj
+++ b/test/clojure_lsp/handlers_test.clj
@@ -5,13 +5,7 @@
    [clojure-lsp.handlers :as handlers]
    [clojure-lsp.parser :as parser]
    [clojure.string :as string]
-   [clojure.test :refer [deftest is testing]])
-  (:import
-   (org.eclipse.lsp4j
-     Diagnostic
-     DiagnosticSeverity
-     Range
-     Position)))
+   [clojure.test :refer [deftest is testing]]))
 
 (deftest did-close
   (reset! db/db {:documents {"file://a.clj" {:text "(ns a)"}
diff --git a/test/clojure_lsp/refactor/transform_test.clj b/test/clojure_lsp/refactor/transform_test.clj
index c3f80dde2..327b8a395 100644
--- a/test/clojure_lsp/refactor/transform_test.clj
+++ b/test/clojure_lsp/refactor/transform_test.clj
@@ -598,7 +598,7 @@
       (let [zloc (z/find-value (z/of-string code) z/next 'something)
             pos (meta (z/node zloc))
             definition (f.definition/definition-usage "file://a.clj" (:row pos) (:col pos))
-            references (f.references/reference-usages "file://a.clj" (:row pos) (:col pos))
+            references (f.references/reference-usages "file://a.clj" (:row pos) (:col pos) false)
             results (transform/inline-symbol definition references)
             a-results (get results "file://a.clj")]
         (is (map? results))
@@ -617,7 +617,7 @@
       (let [zloc (z/find-value (z/of-string b-code) z/next 'a/something)
             pos (meta (z/node zloc))
             definition (f.definition/definition-usage "file://b.clj" (:row pos) (:col pos))
-            references (f.references/reference-usages "file://b.clj" (:row pos) (:col pos))
+            references (f.references/reference-usages "file://b.clj" (:row pos) (:col pos) false)
             results (transform/inline-symbol definition references)
             a-results (get results "file://a.clj")
             b-results (get results "file://b.clj")]