Repository: clojure-lsp/clojure-lsp
Pull request #307 (2021-02-09 12:47:12)

Add full alias completion to fix it on vscode client
Some clients like Calva, only accepts full string completion items (alias + function/name)


Patch:
diff --git a/docs/settings.md b/docs/settings.md
index 40a9ec2c..5fde8278 100644
--- a/docs/settings.md
+++ b/docs/settings.md
@@ -1,74 +1,19 @@
 # Settings 
 
-Custom `clojure-lsp` settings can be configured via 3 ways: **Global configuration**, **project configuration** or **LSP InitializationOptions**.
+`clojure-lsp` settings are picked up on server start and can be configured via 3 ways: 
 
-## Supported settings
+- **Global configuration** 
+- **project configuration**
+- **LSP InitializationOptions**
 
-`source-paths` value is a set of project-local directories to look for clj/cljc/cljs files. Default is `#{"src", "test"}`.
-
-`ignore-classpath-directories` if true, will not consider clojure files within the directories specified by your classpath. This is needed, for instance, if your build puts artifacts into `resources` or `target` that you want lsp to ignore.
-
-`use-metadata-for-privacy?` if true, will use `^:private` metadata for refactorings instead of `defn-`
-
-`keep-require-at-start?` if true, will keep first require/import at the first line instead of inserting a new line before it when using `clean-ns` refactoring.
-
-`semantic-tokens?` if true or not present, will enable LSP semantic tokens server support for syntax highlighting. 
-
-`show-docs-arity-on-same-line?` if true, will keep the arity on the same line of the function on hover, useful for Emacs users.
-
-`auto-add-ns-to-new-files?` if true or not present, will automatically add the `ns` form in new files. 
-
-`document-formatting?` if true or not present, document formatting is provided.
-
-`document-range-formatting?` if true or not present, document range formatting is provided.
-
-`dependency-scheme` by default, dependencies are linked with vim's `zipfile://<zipfile>::<innerfile>` scheme, however you can use a scheme of `jar` to get urls compatible with java's JarURLConnection. You can have the client make an lsp extension request of `clojure/dependencyContents` with the jar uri and the server will return the jar entry's contents. [Similar to java clients](https://github.com/redhat-developer/vscode-java/blob/a24945453092e1c39267eac9367c759a6c7b0497/src/extension.ts#L290-L298)
-
-`cljfmt` json encoded configuration for https://github.com/weavejester/cljfmt
-
-```clojure
-:cljfmt 
-  {:indents 
-    {"#.*" [["block", 0]]
-     "ns" [["inner", 0], ["inner", 1]]
-     "and" [["inner", 0]]
-     "or" [["inner", 0]]
-     "are" [["inner", 0]]}}
-```
-
-`project-specs` - value is a vector containing a map of key/value pairs, for example:
-```clojure
-"initializationOptions": {
-    "project-specs": [{
-        "project-path": "deps.edn",
-        "classpath-cmd": ["clj", "-Spath"]}]
-    }
-```
-Note: You may also consider configuring project specs via the (optional) `.lsp/config.edn` file, i.e.,
-```clojure
-{:project-specs [{:project-path "deps.edn"
-                  :classpath-cmd ["clj" "-Spath"]}]}
-```
-Each project-spec will add to the list of dependencies for lsp to crawl:
-  - `:project-path` is the required filename used by your build tool (project.clj, build.boot, deps.edn, package.json, etc)
-  - `:classpath-cmd` is the required vector of commands to get your project's classpath string (e.g. `["clj", "-Spath"]`)
-  - `:env` optionally add environment variables to the classpath-cmd (e.g. `{"BOOT_FILE" "x.boot"}`)
-  
-### Lint
-
-`clojure-lsp` uses [clj-kondo](https://github.com/clj-kondo/clj-kondo) to lint the code and retrieve the analysis to
-make most of features work, make sure you have it properly configured in your `.clj-kondo/config.edn` file, for more information about available configurations, 
-check the [clj-kondo configuration section](https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md)
-
----
 ## Project
 
-`clojure-lsp` will also look for project specific settings in a file called `.lsp/config.edn`. It will search from your root folder up the directory structure so you can have multiple projects share the same settings.
+`clojure-lsp` will look for project specific settings in a file called `.lsp/config.edn`. It will search from your project root folder up the directory structure so you can have multiple projects share the same settings.
 
+Example:
 ```clojure
-{:macro-defs {korma.core/defentity [:declaration :elements]}
- :cljfmt {:indents {#re ".*" ns [[:inner 0] [:inner 1]]}}
- :clj-kondo {:linters {:missing-docstring {:level :warning}}}}
+{:cljfmt {:indents {#re ".*" ns [[:inner 0] [:inner 1]]}}
+ :auto-add-ns-to-new-files? false}
 ```
 
 ---
@@ -76,7 +21,7 @@ check the [clj-kondo configuration section](https://github.com/clj-kondo/clj-kon
 
 For global settings which should work for all the projects using `clojure-lsp`, you just need to add the same configs to `~/.lsp/config.edn`.
 
-For an example of `config.edn`, check [here](https://github.com/ericdallo/dotfiles/blob/master/.lsp/config.edn).
+For an example of a global `config.edn`, check [here](https://github.com/ericdallo/dotfiles/blob/master/.lsp/config.edn).
 
 ---
 ## InitializationOptions
@@ -84,3 +29,26 @@ For an example of `config.edn`, check [here](https://github.com/ericdallo/dotfil
 This is specific for an client, where it sends on startup, check [LSP spec for more information](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#initialize).
 
 This is an [example how Emacs `lsp-mode`](https://github.com/emacs-lsp/lsp-mode/blob/master/clients/lsp-clojure.el#L205) pass custom information.
+
+## All settings
+
+| name                            | description                                                                                                                                                                                                                                                                                                                                                                                                          | default           |
+|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------|
+| `source-paths`                  | project-local directories to look for clj/cljc/cljs files                                                                                                                                                                                                                                                                                                                                                            | `#{"src" "test"}` |
+| `ignore-classpath-directories`  | will not consider clojure files within the directories specified by your classpath. This is needed, for instance, if your build puts artifacts into `resources` or `target` that you want lsp to ignore.                                                                                                                                                                                                             | `false`           |
+| `use-metadata-for-privacy?`     | Whether to use `^:private` metadata for refactorings instead of `defn-`                                                                                                                                                                                                                                                                                                                                              | `false`           |
+| `keep-require-at-start?`        | Whether to keep first require/import at the first line instead of inserting a new line before it when using `clean-ns` refactoring.                                                                                                                                                                                                                                                                                  | `false`           |
+| `semantic-tokens?`              | Whether to enable LSP semantic tokens server support for syntax highlighting.  (Experimental)                                                                                                                                                                                                                                                                                                                        | `false`           |
+| `show-docs-arity-on-same-line?` | Whether to keep the arity on the same line of the function on hover, useful for Emacs users.                                                                                                                                                                                                                                                                                                                         | `false`           |
+| `auto-add-ns-to-new-files?`     | Whether to automatically add the `ns` form in new blank files.                                                                                                                                                                                                                                                                                                                                                       | `true`            |
+| `document-formatting?`          | if true or not present, document formatting is provided.                                                                                                                                                                                                                                                                                                                                                             | `true`            |
+| `document-range-formatting?`    | if true or not present, document range formatting is provided.                                                                                                                                                                                                                                                                                                                                                       | `true`            |
+| `dependency-scheme`             | How the dependencies should be linked, `jar` will make urls compatible with java's JarURLConnection. You can have the client make an lsp extension request of `clojure/dependencyContents` with the jar uri and the server will return the jar entry's contents. [Similar to java clients](https://github.com/redhat-developer/vscode-java/blob/a24945453092e1c39267eac9367c759a6c7b0497/src/extension.ts#L290-L298) | `zip`             |
+| `cljfmt`                        | Used for formatting, json encoded configuration for [cljfmt](https://github.com/weavejester/cljfmt)                                                                                                                                                                                                                                                                                                                  | `{}`              |
+| `project-specs`                 | A vector containing a map of key/value pairs, defining how `clojure-lsp` should find your project classpath                                                                                                                                                                                                                                                                                                          | Check the default [here](https://github.com/clojure-lsp/clojure-lsp/blob/master/src/clojure_lsp/crawler.clj#L53-L60)                  |
+
+### Lint
+
+`clojure-lsp` uses [clj-kondo](https://github.com/clj-kondo/clj-kondo) to lint the code and retrieve the analysis to
+make most of features work, make sure you have it properly configured in your `.clj-kondo/config.edn` file, for more information about available configurations, 
+check the [clj-kondo configuration section](https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md)
diff --git a/src/clojure_lsp/feature/completion.clj b/src/clojure_lsp/feature/completion.clj
index 8eea4a3d..afe0cf49 100644
--- a/src/clojure_lsp/feature/completion.clj
+++ b/src/clojure_lsp/feature/completion.clj
@@ -13,7 +13,7 @@
 (defn ^:private remove-keys [pred m]
   (apply dissoc m (filter pred (keys m))))
 
-(defn ^:private keyword-element->keyword-str [{:keys [name alias ns]}]
+(defn ^:private keyword-element->str [{:keys [name alias ns]}]
   (let [kw (cond
              alias
              (keyword (str alias) name)
@@ -63,15 +63,29 @@
     :else
     :text))
 
-(defn element->completion-item [{:keys [deprecated alias ns bucket arglist-strs] :as element}]
+(defn ^:private element->label [{:keys [alias bucket] :as element} cursor-alias]
+  (cond
+
+    (= :keywords bucket)
+    (keyword-element->str element)
+
+    (#{:namespace-alias :namespace-usages} bucket)
+    (some-> alias name)
+
+    cursor-alias
+    (str cursor-alias "/" (-> element :name name))
+
+    :else
+    (-> element :name name)))
+
+(defn ^:private element->completion-item
+  [{:keys [deprecated ns bucket arglist-strs] :as element}
+   alias]
   (let [kind (element->completion-item-kind element)
         detail (or (when arglist-strs (string/join " " arglist-strs))
                    (some-> ns name))
         definition? (#{:namespace-definitions :var-definitions} bucket)]
-    (-> {:label  (if (= bucket :keywords)
-                   (keyword-element->keyword-str element)
-                   (or (some-> alias name)
-                       (-> element :name name)))}
+    (-> {:label (element->label element alias)}
         (cond-> detail (assoc :detail detail)
                 deprecated (assoc :tags [1])
                 kind (assoc :kind kind)
@@ -109,7 +123,7 @@
       false
 
       (and (= bucket :keywords)
-           (or (matches-fn (keyword-element->keyword-str element))
+           (or (matches-fn (keyword-element->str element))
                (and ns
                     (matches-fn (str ns)))
                (and alias
@@ -123,7 +137,7 @@
 (defn with-element-items [elements matches-fn cursor-uri cursor-element]
   (->> elements
        (filter (partial valid-element-completion-item? matches-fn cursor-uri cursor-element))
-       (map element->completion-item)
+       (map #(element->completion-item % nil))
        (sort-by :label)))
 
 (defn with-elements-from-alias [alias matches-fn ns-elements other-elements]
@@ -135,7 +149,7 @@
          (filter #(and (= (:bucket %) :var-definitions)
                        (= (:ns %) alias-ns)
                        (matches-fn (:name %))))
-         (map element->completion-item)
+         (map #(element->completion-item % alias))
          (sort-by :label))))
 
 (defn with-clojure-core-items [matches-fn]


Test patch:
diff --git a/test/clojure_lsp/features/completion_test.clj b/test/clojure_lsp/features/completion_test.clj
index 9a73d376..7f34ec65 100644
--- a/test/clojure_lsp/features/completion_test.clj
+++ b/test/clojure_lsp/features/completion_test.clj
@@ -57,13 +57,14 @@
     (h/assert-submaps
       [{:label "frequencies", :detail "clojure.core"}]
       (f.completion/completion "file:///d.clj" 1 49))
-    (h/assert-submaps
-      [{:label "bar"
-        :kind :variable
-        :documentation {:kind "markdown"
-                        :value "```clojure\nd/bar\n```\n\n----\n```clojure\nsome good docs\n```\n----\n*/d.clj*"}}
-       {:label "barbaz", :kind :function}]
-      (f.completion/completion "file:///e.clj" 4 10)))
+    (testing "complete symbols from alias"
+      (h/assert-submaps
+        [{:label "d-alias/bar"
+          :kind :variable
+          :documentation {:kind "markdown"
+                          :value "```clojure\nd/bar\n```\n\n----\n```clojure\nsome good docs\n```\n----\n*/d.clj*"}}
+         {:label "d-alias/barbaz", :kind :function}]
+        (f.completion/completion "file:///e.clj" 4 10))))
   (testing "complete-core-stuff"
     (h/assert-submaps
       [{:label "frequencies", :detail "clojure.core"}]