Skip to content

Commit

Permalink
Merge pull request #17 from CFiggers/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
CFiggers authored Jan 10, 2024
2 parents 56c580f + aa61ef4 commit cd2afe9
Show file tree
Hide file tree
Showing 8 changed files with 206 additions and 162 deletions.
38 changes: 33 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,36 @@
# Changelog
All notable changes to this project will be documented in this file.
Format for entires is <version-string> - release date.

# Changelog
All notable changes to this project will be documented in this file.
Format for entires is <version-string> - release date.
## 0.0.3 - 2024-01-09

## 0.0.1 - 2023-09-26
- Hard forked this project from [JohnDoneth/janet-language-server](https://github.com/JohnDoneth/janet-language-server).
- Completion
- Add basic CompletionItemKind by @fnurk in https://github.com/CFiggers/janet-lsp/pull/9
- Formatting
- New feature: Document formatting by @CFiggers in https://github.com/CFiggers/janet-lsp/pull/13
- Signature Helps
- New Feature: Signature Helps by @CFiggers in https://github.com/CFiggers/janet-lsp/pull/14
- Debug Console
- New Feature: Debug Console by @CFiggers in https://github.com/CFiggers/janet-lsp/pull/15
- Diagnostics
- Improvement: Multiple Diagnostic Errors by @CFiggers in https://github.com/CFiggers/janet-lsp/pull/16
- Cross-cutting
- Separate environment for flychecking user code (better separation between running server env and diagnostic eval env)
- Replace `spork/argparse` with `ianthehenry/cmd` for command line argument parsing
- Bug fixes

## 0.0.2 - 2023-10-24

- Hover
- Improved hover documentation (more detailed info, syntax highlighting for function signatures)
- Completion
- Added `project.janet` symbols for jpm (`declare-project`, `declare-native`, `declare-executable`, etc.)
- General
- Improved module loading logic for eval/completion environment
- Replaced `spork/json` dependency with `CFiggers/jayson` for .jimage compatibility
- Handle `shutdown` and `exit` lifecycle requests properly

## 0.0.1 - 2023-09-26

- Hard forked this project from [JohnDoneth/janet-language-server](https://github.com/JohnDoneth/janet-language-server).

47 changes: 24 additions & 23 deletions src/eval.janet
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@
((compile newtup env where)))
(thunk))))))

(defn eval-buffer [str filename]
(defn eval-buffer [str &opt filename]
(default filename "eval.janet")
(var state (string str))
(defn chunks [buf parser]
(def ret state)
Expand Down Expand Up @@ -85,57 +86,57 @@

(deftest "test eval-buffer: (+ 2 2)"
(setdyn :eval-env (make-env root-env))
(test (eval-buffer "(+ 2 2)") :ok))
(test (eval-buffer "(+ 2 2)") @[]))

(deftest "test eval-buffer: (2)"
(setdyn :eval-env (make-env root-env))
(test (eval-buffer "(2)")
[:error
{:location [1 1]
:message "2 expects 1 argument, got 0"}]))
@[{:location [1 1]
:message "2 expects 1 argument, got 0"}]))

(deftest "test eval-buffer: (+ 2 2"
(setdyn :eval-env (make-env root-env))
(test (eval-buffer "(+ 2 2")
[:error
{:location [2 0]
:message "unexpected end of source, ( opened at line 1, column 1"}]))
@[{:location [2 0]
:message "unexpected end of source, ( opened at line 1, column 1"}]))

# check for side effects
(deftest "test eval-buffer: (pp 42)"
(setdyn :eval-env (make-env root-env))
(test (eval-buffer "(pp 42)") :ok))
(test (eval-buffer "(pp 42)") @[]))

(deftest "test eval-buffer: ()"
(setdyn :eval-env (make-env root-env))
(test (eval-buffer "()")
[:error
{:location [0 0]
:message "expected integer key for tuple in range [0, 0), got 0"}]))
@[{:location [0 0]
:message "expected integer key for tuple in range [0, 0), got 0"}]))

(deftest "import with no argument should give a parse error"
(setdyn :eval-env (make-env root-env))
(test (eval-buffer "(import )")
[:error
{:location [1 1]
:message "macro arity mismatch, expected at least 1, got 0"}]))
@[{:location [1 1]
:message "macro arity mismatch, expected at least 1, got 0"}]))

(deftest "import with no matching module should give a parse error"
(setdyn :eval-env (make-env root-env))
(test (eval-buffer "(import randommodulethatdoesntexist)")
[:error
{:location [0 0]
:message "could not find module randommodulethatdoesntexist:\n /usr/local/lib/janet/randommodulethatdoesntexist.jimage\n /usr/local/lib/janet/randommodulethatdoesntexist.janet\n /usr/local/lib/janet/randommodulethatdoesntexist/init.janet\n /usr/local/lib/janet/randommodulethatdoesntexist.so"}]))
@[{:location [0 0]
:message "could not find module randommodulethatdoesntexist:\n /usr/local/lib/janet/randommodulethatdoesntexist.jimage\n /usr/local/lib/janet/randommodulethatdoesntexist.janet\n /usr/local/lib/janet/randommodulethatdoesntexist/init.janet\n /usr/local/lib/janet/randommodulethatdoesntexist.so"}]))

(deftest "does not error because string/trim is a cfunction"
(setdyn :eval-env (make-env root-env))
(test (eval-buffer "(string/trim )") :ok))
(test (eval-buffer "(string/trim )") @[]))

(deftest "should give a parser error 2"
(setdyn :eval-env (make-env root-env))
(test (eval-buffer "(freeze )")
[:error
{:location [1 1]
:message "<function freeze> expects at least 1 argument, got 0"}]))

@[{:location [1 1]
:message "<function freeze> expects at least 1 argument, got 0"}]))

(deftest "multiple compiler errors"
(setdyn :eval-env (make-env root-env))
(test (eval-buffer "(freeze ) (import )")
@[{:location [1 1]
:message "<function freeze> expects at least 1 argument, got 0"}
{:location [1 11]
:message "macro arity mismatch, expected at least 1, got 0"}]))
7 changes: 0 additions & 7 deletions src/logging.janet
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
(import spork/rpc)

(defn init-logger []
(setdyn :out stderr)
(spit "janetlsp.log.txt" ""))

(defn shutdown-logger []
(file/close (dyn :logfile)))

(defn log [output]

(comment pp (dyn :console))
Expand Down
18 changes: 17 additions & 1 deletion src/lookup.janet
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,33 @@
(break)))
ret)))

(test (peg/match word-peg "(defn main [& args] (+ 1 1))")
@[[0 "" 0]
[1 "defn" 5]
[6 "main" 10]
[11 "[&" 13]
[14 "args]" 19]
[20 "" 20]
[21 "+" 22]
[23 "1" 24]
[25 "1" 26]
[27 "" 27]])

(test (peg/match word-peg "") nil)

(defn word-at [location source]
# (logging/log (string/format "word-at received location: %m" location))
# (logging/log (string/format "word-at received source: %m" source))
(let [{:character character-pos :line line-pos} location
line ((string/split "\n" source) line-pos)
parsed (sort-by last (peg/match word-peg line))
parsed (or (sort-by last (or (peg/match word-peg line) @[[0 "" 0]])))
word (or (first-where |(>= ($ 2) character-pos) parsed) (last parsed))]
{:range [(word 0) (word 2)] :word (word 1)}))

(test (word-at {:line 0 :character 16} "(def- parse-peg\n") {:range [6 14] :word "parse-peg"})

(test (word-at {:line 1 :character 0} "(import )\n") {:range [0 0] :word ""})

(def sexp-peg
(peg/compile
~{:s-exp (group (* (position) (* "(" (any (+ (drop :s-exp) (to (set "()")))) ")") (position)))
Expand Down
159 changes: 39 additions & 120 deletions src/main.janet
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@
(defn parse-content-length [input]
(scan-number (string/trim ((string/split ":" input) 1))))

(deftest "parse-content-length"
(test (parse-content-length "000:123:456:789") 123)
(test (parse-content-length "123:456:789") 456)
(test (parse-content-length "0123:456::::789") 456))

(defn on-document-change
``
Handler for the ["textDocument/didChange"](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_didChange) event.
Expand Down Expand Up @@ -102,41 +97,6 @@
[name]
{:label name :kind (binding-type name)})

(deftest "test binding-to-lsp-item"
(setdyn :eval-env (table/proto-flatten (make-env root-env)))

(def bind-fiber (fiber/new |(do (defglobal "anil" nil)
(defglobal "hello" 'world)
(defglobal "atuple" [:a 1])
true) :e (dyn :eval-env)))
(def bf-return (resume bind-fiber))

(def test-cases @[['hello :symbol] [true :boolean] [% :function]
[abstract? :cfunction] ["Hello world" :string]
[@"Hello world":buffer] [123 :number]
[:keyword :keyword] [stderr :core/file]
[(peg/compile 1) :core/peg] [{:a 1} :struct]
[@{:a 1} :table] ['atuple :tuple]
[@[:a 1]:array] # [(coro) :fiber]
['anil :nil]])

(test (map (juxt 1 |(binding-to-lsp-item (first $))) test-cases)
@[[:symbol {:kind 12 :label hello}]
[:boolean {:kind 6 :label true}]
[:function {:kind 3 :label @%}]
[:cfunction {:kind 3 :label @abstract?}]
[:string {:kind 6 :label "Hello world"}]
[:buffer {:kind 6 :label @"Hello world"}]
[:number {:kind 6 :label 123}]
[:keyword {:kind 6 :label :keyword}]
[:core/file {:kind 17 :label "<core/file 0x1>"}]
[:core/peg {:kind 6 :label "<core/peg 0x2>"}]
[:struct {:kind 6 :label {:a 1}}]
[:table {:kind 6 :label @{:a 1}}]
[:tuple {:kind 6 :label atuple}]
[:array {:kind 6 :label @[:a 1]}]
[:nil {:kind 12 :label anil}]]))

(defn on-completion [state params]
[:ok state {:isIncomplete true
:items (seq [bind :in (all-bindings (dyn :eval-env))] (binding-to-lsp-item bind))}])
Expand Down Expand Up @@ -297,38 +257,6 @@
(array/push results path))))
results)

(deftest "test find-all-module-files"
(test (find-all-module-files (os/cwd))
@["/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/src/main.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/src/rpc.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/src/logging.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/src/misc.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/src/lookup.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/src/doc.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/src/eval.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/libs/jpm-defs.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/libs/jayson.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/test/basic.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/build/janet-lsp.jimage"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/dist/janet-lsp.jimage"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/test/syntax-highlighting.janet"]))

(deftest "test find-all-module-files"
(test (find-all-module-files (os/cwd) true)
@["/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/src/main.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/src/rpc.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/src/logging.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/src/misc.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/src/lookup.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/src/doc.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/src/eval.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/libs/jpm-defs.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/libs/jayson.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/test/basic.janet"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/janet-lsp/build/janet-lsp.jimage"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/dist/janet-lsp.jimage"
"/home/caleb/projects/vscode/vscode-janet-plus-plus/test/syntax-highlighting.janet"]))

(defn find-unique-paths [paths]
(->> (seq [found-path :in paths]
(if (= (path/basename found-path) "init.janet")
Expand All @@ -342,25 +270,7 @@
(map |(path/relpath (os/cwd) $))
(map |(string "./" $))))

(deftest "test find-unique-paths"
(test (find-unique-paths (find-all-module-files (os/cwd)))
@["./janet-lsp/src/:all:.janet"
"./janet-lsp/libs/:all:.janet"
"./janet-lsp/test/:all:.janet"
"./janet-lsp/build/:all:.jimage"
"./dist/:all:.jimage"
"./test/:all:.janet"]))

(deftest "test find-unique-paths"
(test (find-unique-paths (find-all-module-files (os/cwd) true))
@["./janet-lsp/src/:all:.janet"
"./janet-lsp/libs/:all:.janet"
"./janet-lsp/test/:all:.janet"
"./janet-lsp/build/:all:.jimage"
"./dist/:all:.jimage"
"./test/:all:.janet"]))

(defn start-language-server [opts]
(defn start-language-server []
# (setdyn :debug true)
(print "Starting LSP")
(logging/log "Starting LSP")
Expand All @@ -371,7 +281,7 @@
# (merge-module (dyn :eval-env) (((curenv) 'module/paths) :value))
(merge-module (dyn :eval-env) jpm-defs)

(each path (find-unique-paths (find-all-module-files (os/cwd) (not (opts :dont-search-jpm-tree))))
(each path (find-unique-paths (find-all-module-files (os/cwd) (not ((dyn :opts) :dont-search-jpm-tree))))
(cond
(string/has-suffix? ".janet" path) (array/push (((dyn :eval-env) 'module/paths) :value) [path :source])
(string/has-suffix? ".so" path) (array/push (((dyn :eval-env) 'module/paths) :value) [path :native])
Expand All @@ -382,11 +292,9 @@

(message-loop :state @{:documents @{}}))

(defn start-debug-console [opts]
(setdyn :debug true)

(defn start-debug-console []
(def host "127.0.0.1")
(def port (if (opts :port) (string (opts :port)) "8037"))
(def port (if ((dyn :opts) :port) (string ((dyn :opts) :port)) "8037"))

(print (string/format "Janet LSP Debug Console Active on %s:%s" host port))
(print "Awaiting reports from running LSP...")
Expand All @@ -400,27 +308,38 @@
(+= linecount 1))}
host port))

(cmd/main
(cmd/fn
"A Language Server (LSP) for the Janet Programming Language."
[[--dont-search-jpm-tree -j] (flag) "Whether to search `jpm_tree` for modules."
--stdio (flag) "Whether to respond to stdio. Defaults to `true`."
[--console -c] (flag) "Start a debug console instead of starting the Language Server."
[--debug-port -p] (optional :int++) "What port to start the debug console on. Defaults to 8037."]
(when debug-port
(assert console "`--debug-port` requires `--console` as well"))
(default stdio true)
(default debug-port 8037)

(def opts
{:dont-search-jpm-tree dont-search-jpm-tree
:stdio stdio
:console console
:debug-port debug-port})

(setdyn :opts opts)
# (setdyn :out stderr)

(if console
(start-debug-console opts)
(start-language-server opts))))
(defn main [& args]

(def parsed-args (cmd/args))

(when (or (has-value? parsed-args "--version")
(has-value? parsed-args "-v"))
(print "Janet LSP v" version)
(os/exit 0))

(cmd/run
(cmd/fn
"A Language Server (LSP) for the Janet Programming Language."
[[--dont-search-jpm-tree -j] (flag) "Whether to search `jpm_tree` for modules."
--stdio (flag) "Use STDIO."
[--debug -d] (flag) "Print debug messages."
[--console -c] (flag) "Start a debug console instead of starting the Language Server."
[--debug-port -p] (optional :int++) "What port to start the debug console on. Defaults to 8037."]

(default stdio true)
(default debug-port 8037)

(def opts
{:dont-search-jpm-tree dont-search-jpm-tree
:stdio stdio
:console console
:debug-port debug-port})

(setdyn :opts opts)
(setdyn :debug debug)
(setdyn :out stderr)

(if console
(start-debug-console)
(start-language-server)))
parsed-args))
2 changes: 2 additions & 0 deletions src/misc.janet
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
(use judge)

(defmacro letv [bindings & body]
~(do ,;(seq [[k v] :in (partition 2 bindings)] ['var k v]) ,;body))

Expand Down
6 changes: 0 additions & 6 deletions test/basic.janet

This file was deleted.

Loading

0 comments on commit cd2afe9

Please sign in to comment.