Skip to content

Commit

Permalink
Add babashka pod (#674)
Browse files Browse the repository at this point in the history
* Add babashka pod

* Add tests

* Add CI

* Add more tests

* [docs]
  • Loading branch information
ericdallo committed Dec 18, 2021
1 parent 192b935 commit aef338a
Show file tree
Hide file tree
Showing 11 changed files with 229 additions and 9 deletions.
2 changes: 1 addition & 1 deletion .dir-locals.el
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
((clojure-mode
(cider-clojure-cli-aliases . "-A:test")))
(cider-clojure-cli-aliases . "test")))
11 changes: 9 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ jobs:
- name: Generate embedded binary
run: make prod-bin

- name: Run babashka pod tests
run: make pod-test

- name: Run integration tests
run: make integration-test

Expand Down Expand Up @@ -164,6 +167,10 @@ jobs:
mv clojure-lsp-native/clojure-lsp .
chmod +x clojure-lsp
- name: Run babashka pod tests
env:
CLOJURE_LSP_TEST_ENV: native
run: make pod-test

- name: Run integration tests
run: |
make integration-test
run: make integration-test
10 changes: 10 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ jobs:
with:
file: clojure-lsp

- name: Run babashka pod tests
env:
CLOJURE_LSP_TEST_ENV: native
run: make pod-test

- name: Run integration tests
run: |
make integration-test
Expand Down Expand Up @@ -231,6 +236,11 @@ jobs:
# with:
# file: clojure-lsp

- name: Run babashka pod tests
env:
CLOJURE_LSP_TEST_ENV: native
run: make pod-test

- name: Run integration tests
run: |
make integration-test
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Avoid high CPU and lockup when clj-kondo throws exceptions. #671
- Allow absolute paths in deps.edn :local/root #672
- Fix clojure-lsp not loading for some mono-repo cases, improving local/root support for polylith projects. #673
- Add babashka pod. #555

- Editor
- Change call hierarchy to return selection range of usage, not function definition.
Expand Down
13 changes: 8 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ all: debug-bin
# https://clojure.org/guides/getting_started#_clojure_installer_and_cli_tools

clean:
rm -rf classes clojure-lsp clojure-lsp.jar docs/README.md
rm -rf classes clojure-lsp clojure-lsp.jar docs/README.md docs/CHANGELOG.md

classes:
clojure -X:javac
Expand All @@ -34,6 +34,12 @@ prod-native:
test: classes
clojure -M:test

pod-test: classes
clojure -M:pod-test

integration-test:
bb integration-test ./clojure-lsp

lint-clean:
clojure -M:run clean-ns --dry --ns-exclude-regex "sample-test.*"

Expand All @@ -50,12 +56,9 @@ lint-fix:
release:
./release

integration-test:
bb integration-test ./clojure-lsp

local-webpage:
cp -rf CHANGELOG.md README.md images docs
docker login docker.pkg.github.com
docker run --rm -it -p 8000:8000 -v ${PWD}:/docs docker.pkg.github.com/clojure-lsp/docs-image/docs-image

.PHONY: all classes debug-bin prod-jar prod-jar-for-native prod-bin prod-native test integration-test local-webpage clean release
.PHONY: all classes debug-bin prod-jar prod-jar-for-native prod-bin prod-native test pod-test integration-test local-webpage clean release
9 changes: 9 additions & 0 deletions deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
:exclusions [rewrite-cljs/rewrite-cljs
com.googlecode.java-diff-utils/diffutils]}
com.googlecode.java-diff-utils/diffutils {:mvn/version "1.3.0"}
nrepl/bencode {:mvn/version "1.1.0"}
medley/medley {:mvn/version "1.3.0"}
anonimitoraf/clj-flx {:mvn/version "1.2.0"}
clj-kondo/clj-kondo {:mvn/version "2021.12.16"}
Expand All @@ -25,6 +26,14 @@
:aliases {:test {:extra-deps {lambdaisland/kaocha {:mvn/version "1.60.972"}}
:extra-paths ["test"]
:main-opts ["-m" "kaocha.runner"]}
:pod-test
{:replace-paths ["pod-test"]
:replace-deps {com.cognitect/transit-clj {:mvn/version "1.0.324"}
cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner"
:sha "cb96e80f6f3d3b307c59cbeb49bb0dcb3a2a780b"}
babashka/babashka.pods {:git/url "https://github.com/babashka/babashka.pods"
:sha "f360afa6135b8bd2d384d9ba4582c0de6fdac804"}}
:main-opts ["-m" "cognitect.test-runner" "-d" "pod-test"]}
:javac {:replace-deps {org.suskalo/americano {:mvn/version "1.2.0"}}
:exec-fn americano.cli/javac
:exec-args {:source-paths ["src-java"]}}
Expand Down
4 changes: 4 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ Remember to install your build tool, like `clojure` or `leiningen` as well in yo

To run clojure-lsp from Leiningen easily, check [lein-clojure-lsp](https://github.com/clojure-lsp/lein-clojure-lsp) plugin.

### Babashka pod

It's possible to load clojure-lsp as a babashka pod giving access to the `clojure-lsp.api` namespace, Check babashka pod registry [example](https://github.com/babashka/pod-registry/blob/master/examples/clojure-lsp.clj).

## Settings

clojure-lsp will check for `.lsp/config.edn` in the project or home dir, but it's possible to force override the settings via the `:settings` option of the API or `--settings` option of the CLI.
Expand Down
2 changes: 2 additions & 0 deletions pod-test/clojure_lsp/.dir-locals.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
((clojure-mode
(cider-clojure-cli-aliases . "pod-test")))
43 changes: 43 additions & 0 deletions pod-test/clojure_lsp/pod_test.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
(ns clojure-lsp.pod-test
(:require
[babashka.pods :as pods]
[clojure.java.io :as io]
[clojure.test :refer [deftest is testing]]))

(def pod-spec (if (= "native" (System/getenv "CLOJURE_LSP_TEST_ENV"))
["./clojure-lsp"]
["clojure" "-M:run"]))

(pods/load-pod pod-spec)
(require '[clojure-lsp.api :as clojure-lsp])

#_{:clj-kondo/ignore [:unresolved-var]}
(deftest pod-test
(testing "analyze-project!"
(let [result (clojure-lsp/analyze-project!
{:project-root (io/file "integration-test/sample-test")
:raw? true})]
(is result)))
(testing "clean-ns!"
(let [result (clojure-lsp/clean-ns!
{:project-root (io/file "integration-test/sample-test")
:namespace '[sample-test.api.format.a]
:raw? true
:dry? true})]
(is (= 1 (:result-code result)))
(is (seq (:edits result)))))
(testing "diagnostics"
(let [result (clojure-lsp/diagnostics
{:project-root (io/file "integration-test/sample-test")
:raw? true
:dry? true})]
(is (not= 0 (:result-code result)))
(is (seq (:diagnostics result)))))
(testing "format!"
(let [result (clojure-lsp/format!
{:project-root (io/file "integration-test/sample-test")
:namespace '[sample-test.api.format.a]
:raw? true
:dry? true})]
(is (= 1 (:result-code result)))
(is (seq (:edits result))))))
8 changes: 7 additions & 1 deletion src/clojure_lsp/main.clj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
[clojure.java.io :as io]
[clojure.string :as string]
[clojure.tools.cli :refer [parse-opts]]
[pod.clojure-lsp.api :as pod]
[taoensso.timbre :as log])
(:import
[clojure_lsp WarningLogDisabler])
Expand Down Expand Up @@ -93,8 +94,12 @@
(string/join \newline errors)))

(defn ^:private parse [args]
(let [{:keys [options arguments errors summary]} (parse-opts args (cli-options))]
(let [{:keys [options arguments errors summary]} (parse-opts args (cli-options))
pod? (= "true" (System/getenv "BABASHKA_POD"))]
(cond
pod?
{:action "pod" :options options}

(:help options)
{:exit-message (help summary) :ok? true}

Expand Down Expand Up @@ -134,6 +139,7 @@
{:exit-code 0})
(try
(case action
"pod" (pod/run-pod)
"clean-ns" (internal-api/clean-ns! options)
"diagnostics" (internal-api/diagnostics options)
"format" (internal-api/format! options)
Expand Down
135 changes: 135 additions & 0 deletions src/pod/clojure_lsp/api.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
(ns pod.clojure-lsp.api
{:no-doc true}
(:refer-clojure :exclude [read read-string])
(:require
[bencode.core :as bencode]
[clojure-lsp.api :as api]
[cognitect.transit :as transit])
(:import
[java.io PushbackInputStream])
(:gen-class))

(set! *warn-on-reflection* true)

(def stdin (PushbackInputStream. System/in))

(defn write [v]
(bencode/write-bencode System/out v)
(.flush System/out))

(defn read-string [^"[B" v]
(String. v))

(defn read []
(bencode/read-bencode stdin))

;; transit

;;; payload
(def jiofile-key (str ::file))

(def jiofile-read-handler
(transit/read-handler (fn [^String s] (java.io.File. s))))

(def jiofile-write-handler
(transit/write-handler jiofile-key str))

(defn reg-transit-handlers
[]
(format "
(require 'babashka.pods)
(babashka.pods/add-transit-read-handler!
\"%s\"
(fn [s] (java.io.File. s)))
(babashka.pods/add-transit-write-handler!
#{java.io.File}
\"%s\"
str)
"
jiofile-key jiofile-key))

(def transit-read-handlers
(delay
(transit/read-handler-map
{jiofile-key jiofile-read-handler})))

(def transit-write-handlers
(delay
(transit/write-handler-map
{java.io.File jiofile-write-handler})))

(defn read-transit [^String v]
(transit/read
(transit/reader
(java.io.ByteArrayInputStream. (.getBytes v "utf-8"))
:json
{:handlers @transit-read-handlers})))

(defn write-transit [v]
(let [baos (java.io.ByteArrayOutputStream.)]
(transit/write
(transit/writer
baos
:json
{:handlers @transit-write-handlers}) v)
(.toString baos "utf-8")))

(def api-vars
{'clojure-lsp.api/analyze-project! api/analyze-project!
'clojure-lsp.api/clean-ns! api/clean-ns!
'clojure-lsp.api/diagnostics api/diagnostics
'clojure-lsp.api/format! api/format!
'clojure-lsp.api/rename! api/rename!})

(defn run-pod []
(loop []
(let [message (try (read)
(catch java.io.EOFException _
::EOF))]
(when-not (identical? ::EOF message)
(let [op (-> (get message "op")
read-string
keyword)
id (some-> (get message "id")
read-string
(or "unknown"))]
(case op
:describe (do (write {"format" "transit+json"
"namespaces" [{:name "borkdude.tdn.pod"
:vars [{:name '-reg-transit-handlers
:code (reg-transit-handlers)}]}
{"name" "clojure-lsp.api"
"vars" (->> api-vars
keys
(mapv (fn [k] {"name" (name k)})))}]
"id" id})
(recur))
:invoke (do (try
(let [var (-> (get message "var")
read-string
symbol)
args (some-> (get message "args")
read-string
read-transit)]
(if-let [f (api-vars var)]
(let [value (-> (apply f args)
write-transit)
reply {"value" value
"id" id
"status" ["done"]}]
(write reply))
(throw (ex-info (str "Var not found: " var) {}))))
(catch Throwable e
(binding [*out* *err*]
(println e))
(let [reply {"ex-message" (.getMessage e)
"ex-data" (write-transit
(assoc (ex-data e)
:type (class e)))
"id" id
"status" ["done" "error"]}]
(write reply))))
(recur))
(do
(write {"err" (str "unknown op:" (name op))})
(recur))))))))

0 comments on commit aef338a

Please sign in to comment.