Giter VIP home page Giter VIP logo

scheme-langserver's Introduction

Scheme-langserver

NOTE: There're many many bugs in scheme-langserver. I'm just fixing and appealing help from the community. Please be patient.

NOTE: you can find the auto generated type information here. It's now mainly used for next-stage-development (maybe include AKKU) and debugging.

Implementing support like autocomplete, goto definition, or documentation on hover is a significant effort for programming. However, comparing to other language like java, python, javascript and c, language server protocol implementation for lisp language are just made in a vacuum. Geiser, racket langserver and swish-lint etc., their works are all based on repl(Read-Eval-Print Loop) or keyword tokenizer instead of programming. For example, if a programmer was coding on an unaccomplished project, in which the codes were not fully executable, Geiser or any others would only complete top-level binding identifiers listed by environment-symbols procedure (for Chez). Which means for local bindings and unaccomplished codes, though making effort for programming is supposed of the importance mostly, Geiser and its counterparts help nothing. Familiar cases occur with goto definition and many other functionalities.

A primary cause is, for scheme and other lisp dialects, their abundant data sets and flexible control structures raise program analysis a big challenge. Especially the dynamic type system and macro, it seems like that scheme is mainly used for genius and meta/macro programming. But I say no. Scheme can make many interesting things if a better programming environment is provided. And now I'll work on this.

This package is a language server protocol implementation helping scheme programming. It provides completion, definition and type inference. These functionalities are established on static code analysis with r6rs standard and some obvious rules for unaccomplished codes. This package itself and related libraries are published or going to be published with Akku, which is a package manager for Scheme.

This package also has been tested with Chez Scheme versions 9.4 and 9.5. A detailed test on version 10.0.0 will be done after upgrading my laptop OS to a newer version.

I do this open source work just in my spare time and I can contribute many splendid ideas to the community like embedding data flow analysis into scheme-langserver or many other things. And I'm continuously asking for much more donation or funding. You can click this patreon page or 爱发电 to donate monthly, or just donate 10 USD just once time with the following paypal link.

paypal

Recent Status

I'll keep fixing bugs, profiling the code, and collecting information for my giant book on homemade type inference system. This will take me about 1 or 2 years. Further developments including a VScode plugin and data flow analysis. But actually, I'm now setting this open source work a part-time job, and I can not guarantee a schedule.

Release

1.2.0 It has never occurred to me the next medium version comes so fast. But it is still essential to claim that I just re-construct the identifier catching mechanism with abstract interpreter, which will allow processing identifier claims in self-defined macros. A detailed outline should be referred in documentation.

Previous releases please refer to this file.

Setup

Building

Pre-require

  1. Chez Scheme;

NOTE Scheme-langserver's muti-threaded feature requires Chez Scheme to have been compiled with the --threads option. For Chez Scheme version after 10.0.0, there're some differents now.

  1. Akku
  2. chez-exe

NOTE chez-exe requires boot files and kernel files of Chez Scheme. So, the compile command maybe like follows:scheme --script gen-config.ss --bootpath /path-to-ChezScheme/{machine-type}/boot/{machine-type}

For Linux

git clone https://github.com/ufo5260987423/scheme-langserver
cd scheme-langserver
akku install
bash .akku/env
compile-chez-program run.ss
./run path-to-logfile

TODO: for Windows

The run file is also executable in Windows WSL environment.

As for native on Windows, scheme-langserver requires AKKU to be native on Windows first now. An essential barrier is the srfi, whose library path can't be handled in Windows7. Further discussion is on tihs page.

Installation for LunarVim(1.3)

I have pull request to mason.nvim and mason-lspconfig.nvim. In that case, you can get this implementation automatically with LunarVim.

But now, above configuration haven't been tested. So, manual installation is still needed: for installed plugin nvim-lspconfig, after manually building from above step Building, an executable file run would be available at {path-to-run}. Then, create file ~/.local/share/lunarvim/site/pack/lazy/opt/nvim-lspconfig/lua/lspconfig/server_configurations/scheme_langserver.lua as follows:

local util = require 'lspconfig.util'
local bin_name = '{path-to-run}'
local cmd = { bin_name }

return {
  default_config = {
    cmd = cmd,
    filetypes = { 'scheme' },
    root_dir = util.find_git_ancestor,
    single_file_support = true,
  },
  docs = {
    description = [[
https://github.com/ufo5260987423/scheme-langserver
`scheme-langserver`, a language server protocol implementation for scheme
]]   ,
  },
}

Then configure your ~/.config/lvim/config.lua and add following codes like:

vim.cmd [[ au BufRead,BufNewFile *.sld set filetype=scheme ]]
vim.cmd [[ au BufRead,BufNewFile *.sls set filetype=scheme ]]

vim.api.nvim_create_autocmd('LspAttach', {
  group = vim.api.nvim_create_augroup('UserLspConfig', {}),
  callback = function(ev)
    -- Enable completion triggered by <c-x><c-o>
    vim.bo[ev.buf].omnifunc = 'v:lua.vim.lsp.omnifunc'

    -- Buffer local mappings.
    -- See `:help vim.lsp.*` for documentation on any of the below functions
    local opts = { buffer = ev.buf }
    vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, opts)
    vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts)
    vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts)
    vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts)
  end,
})

-- local capabilities = vim.lsp.protocol.make_client_capabilities()
-- capabilities = require("cmp_nvim_lsp").default_capabilities(capabilities)
local lspconfig = require('lspconfig')
lspconfig.scheme_langserver.setup {}
lvim.builtin.cmp.enabled()
lvim.builtin.cmp.sources = {
  { name = 'nvim_lsp' },
  { name = 'luasnip' },
  { name = 'buffer' },
}

NOTE: detailed configuration for lvim.builtin.cmp.sources and LspAttach can refer this page and this page.

Enable multi-thread or type-inference

NOTE: for previous versions, they have a configuration for SCM/SS identifier catching. But in recent versions I implement abstract interpreter, so that we do not need that configuration.

Scheme-langserver has facilitated many higher level functions, but they shouldn't be fully convinced and tested. If you want to have a try, just step above instructions and rewrite file ~/.local/share/lunarvim/site/pack/lazy/opt/nvim-lspconfig/lua/lspconfig/server_configurations/scheme_langserver.lua as follows:

local util = require 'lspconfig.util'
local bin_name = '{path-to-run}'

--the first 'enable' is for multi-thread mechanism. 
local cmd = { bin_name ,'{path-to-log}','enable'}
-- the second 'enable' is for type inference.
-- local cmd = { bin_name ,'{path-to-log}','disable', 'enable'}

return {
  default_config = {
    cmd = cmd,
    filetypes = { 'scheme' },
    root_dir = util.find_git_ancestor,
    single_file_support = true,
  },
  docs = {
    description = [[
https://github.com/ufo5260987423/scheme-langserver
`scheme-langserver`, a language server protocol implementation for scheme
]]   ,
  },
}

NOTE: the type inference is in its very early stage. Even for small code file it may take much more time than your expectation.

TODO: Installation for VScode

Features

  1. Top-level and local identifiers binding completion. Top-level and local identifiers binding
  2. Goto definition. Goto definition with telescope.nvim
  3. Compatible with package manager: Akku.
  4. File changes synchronizing and corresponding index changing.
  5. Hover.
  6. References and document highlight (document-scoped references). Find references with telescope.nvim
  7. Document symbol. Find document symbols with telescope.nvim
  8. Catching *-syntax(define-syntax, let-syntax, etc.) based local identifier binding.
  9. Cross-platform parallel indexing.
  10. Self-made source code annotator to be compatible with .sps files.
  11. Peephole optimization for API requests.
  12. Type inference with a homemade DSL interpreter(I'm very proud of it!). And now it has been embedded into the auto-completion. As the following figure indicated, the "length-b" and "length-a" having "integer?" type are in the front of those recommended options because they can match the parameter type requiring from "<=". Autocompletion with type inference A test in can prove this result, just run scheme --script tests/protocol/apis/test-completion.sps and the log file scheme-langserver.log would contain results like this:
send-message
2023 11 21 11 26 41 967266866
{"jsonrpc":"2.0","id":"3","result":[{"label":"length-a"},{"label":"length-b"},{"label":"lambda"},{"label":"latin-1-codec"},{"label":"lcm"},{"label":"least-fixnum"},{"label":"length"},{"label":"let"},{"label":"let*"},{"label":"let*-values"},{"label":"let-syntax"},{"label":"let-values"},{"label":"letrec"},{"label":"letrec*"},{"label":"letrec-syntax"},{"label":"lexical-violation?"},{"label":"list"},{"label":"list->string"},{"label":"list->vector"},{"label":"list-ref"},{"label":"list-sort"},{"label":"list-tail"},{"label":"list?"},{"label":"log"},{"label":"lookahead-char"},{"label":"lookahead-u8"}]}
  1. Abstract interpreter for identifier catching among different file extensions like scm, ss, sps, sls and sld.

TODOs

  1. Renaming.
  2. Fully compatible with r6rs standard.
  3. Macro expanding.
  4. Code eval.
  5. Code diagnostic.
  6. Add cross-language semantic supporting. Well, would java, c, python and many other languages can be supported with an AST transformer?
  7. Extract expression/statements into a procedure()

TODO:Contributing

Debug

How to Debug

https://www.scheme.com/debug/debug.html#g1

Output Log

Following tips from Building, Installation for Lunar Vim and Installation for VScode, if anyone wants to do some developing and log something, it will be convenient to add path-to-log-file and re-write file ~/.local/share/lunarvim/site/pack/packer/start/nvim-lspconfig/lua/lspconfig/server_configurations/scheme_langserver.lua as follows:

local util = require 'lspconfig.util'
local bin_name = '{path-to-run}'
local cmd = { bin_name ,"path-to-log-file"}

return {
  default_config = {
    cmd = cmd,
    filetypes = { 'scheme' },
    root_dir = util.find_git_ancestor,
    single_file_support = true,
  },
  docs = {
    description = [[
https://github.com/ufo5260987423/scheme-langserver
`scheme-langserver`, a language server protocol implementation for scheme
]]   ,
  },
}

Recurring with Log

With above output log, you may use tests/log-debug.sps recurring bugs:

  1. Rename {path-to-log}(usually ~/scheme-langserver.log) as ~/ready-for-analyse.log;
  2. run scheme --script tests/log-debug.sps. If you want to re-produce the multi-thread environment, it would also be available to run scheme --script tests/log-debug.sps.

Test

Almost all key procedures and APIs are tested. My work is just so rough but useful, maybe you would like to find what I've done in tests directory or just run following command in {scheme-langserver-root-directory}

bash test.sh

NOTE It's hard to do test with threaded environment. So, current tests focus on single thread.

Code Count

find . -name "*.sls" ! -path "./.akku/*" |xargs wc -l

Detailed Document

  1. Catching identifier bindings
  2. Synchronizing
  3. Type inference,类型推断(Deprecated, and I'm writing a Chinese book for it)
  4. API Analysis

Star History

Star History Chart

Contributors

Contributors

scheme-langserver's People

Contributors

konst-aa avatar ufo5260987423 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

scheme-langserver's Issues

/usr/local/lib/petite-chez.a: No such file or directory

I also tried on ubuntu, but failed to compile-chez-program run.ss

I got the ERROR

# compile-chez-program run.ss
compiling run.ss with output to run.so
cc: error: /usr/local/lib/petite-chez.a: No such file or directory
run

Env

# uname -a
Linux 71bdad0c8f86 5.15.49-linuxkit-pr #1 SMP Thu May 25 07:17:40 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

the chez scheme is built from source code: https://github.com/cisco/ChezScheme
the chez-exe is built from source code: https://github.com/gwatt/chez-exe
the akku is the pre-built version v1.1.0 from the official website: https://gitlab.com/akkuscm/akku/-/releases

the files provided by chez scheme is

# ls /usr/lib/csv9.5.9/a6le/
kernel.o  main.o  petite.boot  revision  scheme-script.boot  scheme.boot  scheme.h

no petite-chez.a installed

Github Workflows

cc: @ufo5260987423

As there are plans to encourage outside contributions, it would be essential to set up workflows to make that go smoothly. I would like to propose the classic workflow:

  • One that triggers on a PR and runs tests.
  • This can be implemented mostly on top of the checkout workflow; we just need a Dockerfile.

We can also add something to simplify or even automate releases:

  • A workflow that triggers on a merge into the main branch and publishes a new release. It can derive the version number from a Changelog.md written in a discussion, file, or commit message.
  • I am unsure how to approach this, but perhaps one can call the GH API to retrieve the Changelog, then call it again to publish the release. One can also use one of the existing actions, though those may change the proposed way of providing a Changelog.

I would love to hear your thoughts!

how to work with .scm files

hi,
I have built and used the scheme-langserver success on lvim when editing its own source code.

However, when I edit a single .scm file on another folder,
the scheme-langserver is not working.

  • code completion is not available.

  • goto definition seems to work

  • the log file is empty.

is another config needed?

Exception: attempt to reference unbound identifier make-mutex

Env:

  • macOS 13.4.1
  • scheme-langserver main branch

ERROR:

run compile-chez-program run.ss

Exception: attempt to reference unbound identifier make-mutex at line 17, char 26 of /Users/pikachu/code/scheme-langserver/.akku/lib/ufo-thread-pool/util/blocking-queue.chezscheme.sls

full log


compile-chez-program run.ss
compiling run.ss with output to run.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/scheme-langserver.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/scheme-langserver.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/ufo-thread-pool.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/ufo-thread-pool.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/ufo-thread-pool/util/blocking-queue.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/ufo-thread-pool/util/blocking-queue.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/slib/queue.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/slib/queue.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/scheme/base.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/scheme/base.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/akku-r7rs/base.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/akku-r7rs/base.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/:1/lists.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/:1/lists.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/:8/receive.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/:8/receive.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/:23/error/tricks.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/:23/error/tricks.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/private/vanish.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/private/vanish.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/private/check-arg.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/private/check-arg.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/private/include.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/private/include.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/private/include/compat.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/private/include/compat.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/private/include/read.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/private/include/read.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/:6/basic-string-ports.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/:6/basic-string-ports.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/:6/basic-string-ports/compat.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/:6/basic-string-ports/compat.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/:9/records.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/:9/records.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/:13/strings.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/:13/strings.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/:14/char-sets.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/:14/char-sets.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/private/let-opt.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/private/let-opt.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/:14/char-sets/inversion-list.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/:14/char-sets/inversion-list.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/:39/parameters.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/:39/parameters.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/srfi/:43/vectors.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/srfi/:43/vectors.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/akku/metadata.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/akku/metadata.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/akku-r7rs/compat.chezscheme.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/akku-r7rs/compat.chezscheme.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/akku-r7rs/include.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/akku-r7rs/include.so
compiling /Users/pikachu/code/scheme-langserver/.akku/lib/laesare/reader.sls with output to /Users/pikachu/code/scheme-langserver/.akku/libobj/laesare/reader.so
Exception: attempt to reference unbound identifier make-mutex at line 17, char 26 of /Users/pikachu/code/scheme-langserver/.akku/lib/ufo-thread-pool/util/blocking-queue.chezscheme.sls

How to use with Helix Editor?

I am new to Scheme and using Helix Editor 23.10. I successfully installed scheme-langserver 1.1.1 package from Akku.
I cannot find where Akku installed the language server executable, what the executable's name is, or how to set it up to work with Helix.

I've added the following to languages.toml
[[language]]
name = "scheme"
scope = "source.scheme"
injection-regex = "scheme"
file-types = ["ss", "scm"]
shebangs = ["scheme", "guile", "chicken"]
comment-token = ";"
indent = { tab-width = 2, unit = " " }
language-servers = [ "scheme-langserver"]

emacs的eglot使用情况

先感谢作者的开源这个非常好的项目,你真棒!
我使用emacs的eglot作为lsp客户端,得到ready-for-analyse.log

read-message
2024 3 4 17 4 53 568023936
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"processId":5845,"clientInfo":{"name":"Eglot","version":"1.17"},"rootPath":"/data/projector/CLionProjects/scheme-langserver/","rootUri":"file:///data/projector/CLionProjects/scheme-langserver","initializationOptions":{},"capabilities":{"workspace":{"applyEdit":true,"executeCommand":{"dynamicRegistration":false},"workspaceEdit":{"documentChanges":true},"didChangeWatchedFiles":{"dynamicRegistration":true},"symbol":{"dynamicRegistration":false},"configuration":true,"workspaceFolders":true},"textDocument":{"synchronization":{"dynamicRegistration":false,"willSave":true,"willSaveWaitUntil":true,"didSave":true},"completion":{"dynamicRegistration":false,"completionItem":{"snippetSupport":false,"deprecatedSupport":true,"resolveSupport":{"properties":["documentation","details","additionalTextEdits"]},"tagSupport":{"valueSet":[1]}},"contextSupport":true},"hover":{"dynamicRegistration":false,"contentFormat":["plaintext"]},"signatureHelp":{"dynamicRegistration":false,"signatureInformation":{"parameterInformation":{"labelOffsetSupport":true},"documentationFormat":["plaintext"],"activeParameterSupport":true}},"references":{"dynamicRegistration":false},"definition":{"dynamicRegistration":false,"linkSupport":true},"declaration":{"dynamicRegistration":false,"linkSupport":true},"implementation":{"dynamicRegistration":false,"linkSupport":true},"typeDefinition":{"dynamicRegistration":false,"linkSupport":true},"documentSymbol":{"dynamicRegistration":false,"hierarchicalDocumentSymbolSupport":true,"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}},"documentHighlight":{"dynamicRegistration":false},"codeAction":{"dynamicRegistration":false,"resolveSupport":{"properties":["edit","command"]},"dataSupport":true,"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}},"isPreferredSupport":true},"formatting":{"dynamicRegistration":false},"rangeFormatting":{"dynamicRegistration":false},"rename":{"dynamicRegistration":false},"inlayHint":{"dynamicRegistration":false},"publishDiagnostics":{"relatedInformation":false,"codeDescriptionSupport":false,"tagSupport":{"valueSet":[1,2]}}},"window":{"showDocument":{"support":true},"workDoneProgress":true},"general":{"positionEncodings":["utf-32","utf-8","utf-16"]},"experimental":{}},"workspaceFolders":[{"uri":"file:///data/projector/CLionProjects/scheme-langserver","name":"~/CLionProjects/scheme-langserver/"}]}}
send-message
2024 3 4 17 4 59 927210684
{"jsonrpc":"2.0","id":1,"result":{"capabilities":{"textDocumentSync":{"openClose":true,"change":2},"hoverProvider":true,"definitionProvider":true,"referencesProvider":true,"completionProvider":{"triggerCharacters":["("]},"documentSymbolProvider":true,"documentRangeFormattingProvider":false}}}
read-message
2024 3 4 17 4 59 929362320
{"jsonrpc":"2.0","method":"initialized","params":{}}
read-message
2024 3 4 17 4 59 932145590
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///data/projector/CLionProjects/scheme-langserver/scheme-langserver.sls","version":0,"languageId":"scheme","text":"(library (scheme-langserver)\n  (export\n    init-server)\n  (import\n    (chezscheme)\n    (ufo-thread-pool)\n    (ufo-match)\n\n    (scheme-langserver analysis workspace)\n\n    (scheme-langserver protocol error-code)\n    (scheme-langserver protocol request)\n    (scheme-langserver protocol response)\n    (scheme-langserver protocol server)\n    (scheme-langserver protocol analysis request-queue)\n\n    (scheme-langserver protocol apis references)\n    (scheme-langserver protocol apis document-highlight)\n    (scheme-langserver protocol apis completion)\n    (scheme-langserver protocol apis hover)\n    (scheme-langserver protocol apis definition)\n    (scheme-langserver protocol apis document-sync)\n    (scheme-langserver protocol apis document-symbol)\n    (scheme-langserver protocol apis document-diagnostic)\n\n    (scheme-langserver util try)\n    (scheme-langserver util association)\n    (scheme-langserver util path))\n(def)\n;; Processes a request. This procedure should always return a response\n(define (process-request server-instance request)\n  (let* ([method (request-method request)]\n        [id (request-id request)]\n        [params (request-params request)]\n        [workspace (server-workspace server-instance)])\n    (if\n      (and\n        (server-shutdown? server-instance)\n        (not (equal? \"initialize\" method)))\n      (send-message server-instance (fail-response id server-not-initialized \"not initialized\"))\n      (match method\n        [\"initialize\" (send-message server-instance (initialize server-instance id params))]\n        [\"initialized\" '()]\n\n        [\"textDocument/didOpen\"\n          (try\n            (did-open workspace params)\n            (except c\n              [else\n                (do-log `(format ,(condition-message c) ,@(condition-irritants c)) server-instance)\n                (do-log-timestamp server-instance)\n                (send-message server-instance (fail-response id unknown-error-code method))]))]\n        [\"textDocument/didClose\"\n          (try\n            (did-close workspace params)\n            (except c\n              [else\n                (do-log `(format ,(condition-message c) ,@(condition-irritants c)) server-instance)\n                (do-log-timestamp server-instance)\n                (send-message server-instance (fail-response id unknown-error-code method))]))]\n        [\"textDocument/didChange\"\n          (try\n            (did-change workspace params)\n            (except c\n              [else\n                (do-log `(format ,(condition-message c) ,@(condition-irritants c)) server-instance)\n                (do-log-timestamp server-instance)\n                (send-message server-instance (fail-response id unknown-error-code method))]))]\n\n        [\"textDocument/hover\"\n          (try\n            (send-message server-instance (success-response id (hover workspace params)))\n            (except c\n              [else\n                (do-log `(format ,(condition-message c) ,@(condition-irritants c)) server-instance)\n                (do-log-timestamp server-instance)\n                (send-message server-instance (fail-response id unknown-error-code method))]))]\n        [\"textDocument/completion\"\n          (try\n            (send-message server-instance (success-response id (completion workspace params)))\n            (except c\n              [else\n                (do-log `(format ,(condition-message c) ,@(condition-irritants c)) server-instance)\n                (do-log-timestamp server-instance)\n                (send-message server-instance (fail-response id unknown-error-code method))]))]\n        [\"textDocument/references\"\n          (try\n            (send-message server-instance (success-response id (find-references workspace params)))\n            (except c\n              [else\n                (do-log `(format ,(condition-message c) ,@(condition-irritants c)) server-instance)\n                (do-log-timestamp server-instance)\n                (send-message server-instance (fail-response id unknown-error-code method))]))]\n        ; [\"textDocument/documentHighlight\"\n        ;   (try\n        ;     (send-message server-instance (success-response id (find-highlight workspace params)))\n        ;     (except c\n        ;       [else\n        ;         (do-log `(format ,(condition-message c) ,@(condition-irritants c)) server-instance)\n                ; (do-log-timestamp server-instance)\n        ;         (send-message server-instance (fail-response id unknown-error-code method))]))]\n          ; [\"textDocument/signatureHelp\"\n          ;  (text-document/signatureHelp id params)]\n        [\"textDocument/definition\"\n          (try\n            (send-message server-instance (success-response id (definition workspace params)))\n            (except c\n              [else\n                (do-log `(format ,(condition-message c) ,@(condition-irritants c)) server-instance)\n                (do-log-timestamp server-instance)\n                (send-message server-instance (fail-response id unknown-error-code method))]))]\n        [\"textDocument/documentSymbol\"\n          (try\n            (send-message server-instance (success-response id (document-symbol workspace params)))\n            (except c\n              [else\n                (do-log `(format ,(condition-message c) ,@(condition-irritants c)) server-instance)\n                (do-log-timestamp server-instance)\n                (send-message server-instance (fail-response id unknown-error-code method))]))]\n        [\"textDocument/diagnostic\"\n          (try\n            (send-message server-instance (success-response id (diagnostic workspace params)))\n            (except c\n              [else\n                (do-log `(format ,(condition-message c) ,@(condition-irritants c)) server-instance)\n                (do-log-timestamp server-instance)\n                (send-message server-instance (fail-response id unknown-error-code method))]))]\n\n        [\"$/cancelRequest\"\n          (try\n            (send-message server-instance (fail-response id request-cancelled (assoc-ref params 'method)))\n            (except c\n              [else\n                (do-log `(format ,(condition-message c) ,@(condition-irritants c)) server-instance)\n                (do-log-timestamp server-instance)\n                (send-message server-instance (fail-response id unknown-error-code method))]))]\n          ; [\"textDocument/prepareRename\"\n          ;  (text-document/prepareRename id params)]\n          ; [\"textDocument/formatting\"\n          ;  (text-document/formatting! id params)]\n          ; [\"textDocument/rangeFormatting\"\n          ;  (text-document/range-formatting! id params)]\n          ; [\"textDocument/onTypeFormatting\"\n          ;  (text-document/on-type-formatting! id params)]\n          ; https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#didChangeWatchedFilesClientCapabilities\n\t;[\"workspace/didChangeConfiguration\" (+ 1 2)]\n        [else (send-message server-instance (fail-response id method-not-found (string-append \"invalid request for method \" method \" \\n\")))]\n\t;[else (+ 1 3)]\n\t))))\n\t; public static final string text_document_code_lens = \"textdocument/codelens\";\n\t; public static final string text_document_signature_help = \"textdocument/signaturehelp\";\n\t; public static final string text_document_rename = \"textdocument/rename\";\n\t; public static final string workspace_execute_command = \"workspace/executecommand\";\n\t; public static final string workspace_symbol = \"workspace/symbol\";\n\t; public static final string workspace_watched_files = \"workspace/didchangewatchedfiles\";\n\t; public static final string code_action = \"textdocument/codeaction\";\n\t; public static final string typedefinition = \"textdocument/typedefinition\";\n\t; public static final string document_highlight = \"textdocument/documenthighlight\";\n\t; public static final string foldingrange = \"textdocument/foldingrange\";\n\t; public static final string workspace_change_folders = \"workspace/didchangeworkspacefolders\";\n\t; public static final string implementation = \"textdocument/implementation\";\n\t; public static final string selection_range = \"textdocument/selectionrange\";\n\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n(define (initialize server-instance id params)\n  (let* ([root-path (uri->path (assq-ref params 'rootUri))]\n        [client-capabilities (assq-ref params 'capabilities)]\n        [window (assq-ref client-capabilities 'window)]\n        [workDoneProgress? (if window (assq-ref window 'workDoneProgress) #f)]\n        [textDocument (assq-ref params 'textDocument)]\n        ; [renameProvider\n        ;   (if (assq-ref (assq-ref (assq-ref params 'textDocumet) 'rename) 'prepareSupport)\n        ;     (make-alist 'prepareProvider #t)\n        ;     #t)]\n        [workspace-configuration-body (make-alist 'workspaceFolders (make-alist 'changeNotifications #t 'supported #t))]\n\n        [text-document-body (make-alist\n              'openClose #t\n              ;; https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentSyncKind\n              ;; Incremental=2\n              'change 2)]\n        [server-capabilities (make-alist\n              'textDocumentSync text-document-body\n              'hoverProvider #t\n              'definitionProvider #t\n              'referencesProvider #t\n              ; 'diagnosticProvider (make-alist 'interFileDependencies #t 'workspaceDiagnostics #f)\n              ; 'workspaceSymbol #t\n              ; 'typeDefinitionProvider #t\n              ; 'selectionRangeProvider #t\n              ; 'callHierarchyProvider #t\n              'completionProvider (make-alist 'triggerCharacters (vector \"(\"))\n              ; 'signatureHelpProvider (make-alist 'triggerCharacters (vector \" \" \")\" \"]\"))\n              ; 'implementationProvider #t\n              ; 'renameProvider renameProvider\n              ; 'codeActionProvider #t\n              ; 'documentHighlightProvider #t\n              'documentSymbolProvider #t\n              ; 'documentLinkProvider #t\n              ; 'documentFormattingProvider #t\n              'documentRangeFormattingProvider #f\n              ; 'documentOnTypeFormattingProvider (make-alist 'firstTriggerCharacter \")\" 'moreTriggerCharacter (vector \"\\n\" \"]\"))\n              ; 'codeLensProvider #t\n              ; 'foldingRangeProvider #t\n              ; 'colorProvider #t\n              ; 'workspace workspace-configuration\n              )])\n\n    (if (null? (server-mutex server-instance))\n      (begin\n        (server-workspace-set! server-instance (init-workspace root-path #f (server-ss/scm-import-rnrs? server-instance) (server-type-inference? server-instance)))\n        (server-work-done-progress?-set! server-instance workDoneProgress?)\n        (success-response id (make-alist 'capabilities server-capabilities)))\n      (with-mutex (server-mutex server-instance)\n        (if (null? (server-workspace server-instance))\n          (begin\n            (server-workspace-set! server-instance (init-workspace root-path #t (server-ss/scm-import-rnrs? server-instance) (server-type-inference? server-instance)))\n            (server-work-done-progress?-set! server-instance workDoneProgress?)\n            (success-response id (make-alist 'capabilities server-capabilities)))\n          (fail-response id server-error-start \"server has been initialized\"))))))\n\n(define init-server\n    (case-lambda\n        [()\n          (init-server\n            (standard-input-port)\n            (standard-output-port)\n            '()\n            #f\n            #f\n            #f)]\n        [(log-path)\n          (init-server\n            (standard-input-port)\n            (standard-output-port)\n            (open-file-output-port\n              log-path\n              (file-options replace)\n              'block\n              (make-transcoder (utf-8-codec)))\n            #f\n            #f\n            #f)]\n        [(log-path enable-multi-thread?)\n          (init-server log-path enable-multi-thread? #f #f)]\n        [(log-path enable-multi-thread? ss/scm-import-rnrs?)\n          (init-server log-path enable-multi-thread? ss/scm-import-rnrs? #f)]\n        [(log-path enable-multi-thread? ss/scm-import-rnrs? type-inference?)\n          (init-server\n            (standard-input-port)\n            (standard-output-port)\n            (open-file-output-port\n              log-path\n              (file-options replace)\n              'block\n              (make-transcoder (utf-8-codec)))\n            (equal? enable-multi-thread? \"enable\")\n            (equal? ss/scm-import-rnrs? \"enable\")\n            (equal? type-inference? \"enable\"))]\n        [(input-port output-port log-port enable-multi-thread?)\n          (init-server input-port output-port log-port enable-multi-thread? #f #f)]\n        [(input-port output-port log-port enable-multi-thread? ss/scm-import-rnrs? type-inference?)\n          ;The thread-pool size just limits how many threads to process requests;\n          (let* ([thread-pool (if (and enable-multi-thread? threaded?) (init-thread-pool 1 #t) '())]\n              [request-queue (if (and enable-multi-thread? threaded?) (init-request-queue) '())]\n              [server-instance (make-server input-port output-port log-port thread-pool request-queue '() ss/scm-import-rnrs? type-inference?)])\n            (try\n              (if (not (null? thread-pool))\n                (thread-pool-add-job thread-pool\n                  (lambda ()\n                    (let loop ()\n                      (process-request server-instance (request-queue-pop request-queue))\n                      (loop)))))\n              (let loop ([request-message (read-message server-instance)])\n                (if (not (null? request-message))\n                  (if (not (or (equal? \"shutdown\" (request-method request-message)) (equal? \"exit\" (request-method request-message))))\n                    (begin\n                      (if (null? thread-pool)\n                        (process-request server-instance request-message)\n                        (request-queue-push request-queue request-message))\n                      (loop (read-message server-instance))))))\n              (except c\n                [else\n                  (pretty-print `(format ,(condition-message c) ,@(condition-irritants c)))\n                  (do-log (string-append \"error: \" (eval `(format ,(condition-message c) ,@(condition-irritants c)))) server-instance)\n                  (do-log-timestamp server-instance)])))]))\n)\n"}}}
read-message
2024 3 4 17 4 59 932843820
{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{}}}
send-message
2024 3 4 17 4 59 932905205
{"jsonrpc":"2.0","id":false,"error":{"code":-32601,"message":"invalid request for method workspace\/didChangeConfiguration \n"}}
read-message
2024 3 4 17 5 2 220342980
{"jsonrpc":"2.0","id":2,"method":"textDocument/hover","params":{"textDocument":{"uri":"file:///data/projector/CLionProjects/scheme-langserver/scheme-langserver.sls"},"position":{"line":28,"character":3}}}

1, 使用(load "tests/log-debug.sps")复现时,发现tests/log-debug.sps处理以send-message为界,导致result不对,以及init-server参数匹配不到预期的case,我修改了tests/log-debug.sps

(test-begin "log-debug")
(let loop ([lines (read-lines "~/ready-for-analyse.log")]
        [result '()]
        [batch '()]
        [read? #f])
    (if (not (null? lines))
        (let ([current-line (car lines)])
            (cond
                [read?
                    (let ([s current-line])
                      (loop
                        lines
                        `(,@result ,(string-append
        "Content-Length: "
        (number->string (bytevector-length (string->utf8 s)))
        "\r\n\r\n" s))
                        '()
                        #f))]
                [(and (not read?) (equal? current-line "read-message")) (loop (cddr lines) result '() #t)]
                [else (loop (cdr lines) result '() #f)]))
        (let* ([input-port (open-bytevector-input-port (string->utf8 (apply string-append result)))]
                [log-port (open-file-output-port "~/scheme-langserver.log" (file-options replace) 'block (make-transcoder (utf-8-codec)))]
                [output-port (open-file-output-port "~/scheme-langserver.out" (file-options replace) 'none)]
                ; special for ss/scm enabled
                ; [server-instance (init-server input-port output-port log-port #f #t)]
		;[a (break)]
                [server-instance (init-server input-port output-port log-port #f #f #f)])
            (test-equal #f (server-shutdown? server-instance)))
        ))
(test-end)

2,运行

>scheme
Chez Scheme Version 9.5.9
Copyright 1984-2022 Cisco Systems, Inc.

> (load "tests/log-debug.sps")
%%%% Starting test log-debug
(format
  "~s is not a condition of type &message"
  position-out-of-range)
Exception: variable position-out-of-range is not bound
Type (debug) to enter the debugger.
> 

发现报错了,我编辑的动作是输入(def),光标在def后面。我对比了eglot和LunarVim(1.3)的差异,发现LunarVim(1.3)是发送textDocument/didChange和textDocument/completion,我猜是因为eglot没有发送textDocument/didChange就发送hover,但是我不知道如何修改。后来我修改scheme-langserver的initialize中'hoverProvider #f即不支持hover,eglot表现就和LunarVim一样发送textDocument/didChange和textDocument/completion,现在正常工作了!我目前对于lsp和scheme了解不多,不知道position-out-of-range和hover报错的具体原因,希望作者排查处理,谢谢你

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.