diff --git a/server/src/zen_lang/lsp_server/impl/autocomplete.clj b/server/src/zen_lang/lsp_server/impl/autocomplete.clj new file mode 100644 index 0000000..1804ac7 --- /dev/null +++ b/server/src/zen_lang/lsp_server/impl/autocomplete.clj @@ -0,0 +1,28 @@ +(ns zen-lang.lsp-server.impl.autocomplete) + + +(defn find-completions [ztx {:keys [uri struct-path]}] + (cond + ;; :type symbol suggestion + (= :type (last struct-path)) + (let [cur-ns-edn (get-in @ztx [:file uri :last-valid-edn]) + zen-symbols (keys (:symbols @ztx)) + cur-ns-symbols (-> cur-ns-edn (dissoc 'import 'ns) keys) + imported-symbols (reduce (fn [acc ns'] + (into acc (keys (get-in @ztx [:ns ns'])))) + [] + (get cur-ns-edn 'import))] + (->> (concat zen-symbols cur-ns-symbols imported-symbols) + sort + (mapv str))) + + ;; schema :keys keyword suggestion + :else + (let [pos-ctx-struct (get-in @ztx (into [:file uri :last-valid-edn] struct-path)) + type-symbol (:type pos-ctx-struct)] + (when type-symbol + (->> (get-in @ztx [:symbols type-symbol :keys]) keys sort (mapv str)))))) + + +(comment + ) diff --git a/server/src/zen_lang/lsp_server/impl/server.clj b/server/src/zen_lang/lsp_server/impl/server.clj index a4787c8..a435a56 100644 --- a/server/src/zen_lang/lsp_server/impl/server.clj +++ b/server/src/zen_lang/lsp_server/impl/server.clj @@ -11,6 +11,7 @@ :refer [get-location location->zloc zloc->path]] + [zen-lang.lsp-server.impl.autocomplete :as autocomplete] [zen.core :as zen] [zen.store :as store]) (:import @@ -244,8 +245,10 @@ _ (debug :path path) namespaces (keys (:ns @zen-ctx)) symbols (keys (:symbols @zen-ctx)) + zen-completions' (autocomplete/find-completions zen-ctx {:uri uri :struct-path path}) completions (map #(org.eclipse.lsp4j.CompletionItem. %) - (map str (concat namespaces symbols)))] + (or zen-completions' + (map str (concat namespaces symbols))))] (CompletableFuture/completedFuture (vec completions)))) diff --git a/server/test-resources/test-project/zrc/bar.edn b/server/test-resources/test-project/zrc/bar.edn index d091ad4..d521ddb 100644 --- a/server/test-resources/test-project/zrc/bar.edn +++ b/server/test-resources/test-project/zrc/bar.edn @@ -5,4 +5,6 @@ {:zen/tags #{zen/schema} :type zen/map :keys {:foo {:confirms #{foo/schema}} ;; No errors expected - }}} + }} + + } diff --git a/server/test-resources/test-project/zrc/baz.edn b/server/test-resources/test-project/zrc/baz.edn new file mode 100644 index 0000000..78c5782 --- /dev/null +++ b/server/test-resources/test-project/zrc/baz.edn @@ -0,0 +1,22 @@ +{ns baz + import #{foo} + + schema + {:zen/tags #{zen/schema} + :type zen/map + :keys {:foo {:confirms #{foo/schema}} ;; No errors expected + }} + + schema2 + {:zen/tags #{zen/schema} + :type zen/map + :keys {:foo {:type zen/coll + , + } + :baz {:type zen/string + , + + } + :qux {:type zen/string + , + }}}} diff --git a/server/test/zen_lsp/autocomplete_test.clj b/server/test/zen_lsp/autocomplete_test.clj new file mode 100644 index 0000000..9514456 --- /dev/null +++ b/server/test/zen_lsp/autocomplete_test.clj @@ -0,0 +1,35 @@ +(ns zen-lsp.autocomplete-test + (:require [clojure.test :as test :refer [deftest is testing]] + [zen-lang.lsp-server.impl.server :as server] + [zen-lang.lsp-server.impl.autocomplete :as zl])) + +(defn file->message [f] + {:text (slurp f) :uri f}) + +(def ztx + (do (alter-var-root #'server/zen-ctx (constantly (server/new-context))) + (server/initialize-paths {:root "test-resources/test-project"}) + (server/load-document (file->message "test-resources/test-project/zrc/baz.edn")) + server/zen-ctx)) + +(deftest find-completions-test + (testing "`find-completion` should" + + (testing "find keys of schema under cursor (keywords)" + + (is (= [":every" ":maxItems" ":minItems" ":schema-index"] + (let [f "test-resources/test-project/zrc/baz.edn" + path ['schema2 :keys :foo]] + (zl/find-completions ztx {:uri f :struct-path path})))) + + (is (= [":maxLength" ":minLength" ":regex" ":tags"] + (let [f "test-resources/test-project/zrc/baz.edn" + path ['schema2 :keys :baz]] + (zl/find-completions ztx {:uri f :struct-path path}))))) + + (testing "find `symbols` applied by given context" + (is (= (conj (->> @ztx :symbols keys (mapv str) set) "schema" "schema2") + (let [f "test-resources/test-project/zrc/baz.edn" + path ['schema2 :qux :type]] + (set (zl/find-completions ztx {:uri f :struct-path path}))))) ) + ))