The Crystal Programming Language Forum

Crystalline - LSP server for Crystal

I’m wondering if it would not be a bit too soon, I would rather wait to see if other people find it useful. It also lacks a lot of polish (incoplete features, no binaries or brew install, undocumented code, no specs).

These are crystal compiler dependencies, which Crystalline uses under the hood.

Regarding LLVM, can you check these instructions?

For libxml, there is a llvm 10 bug on macos when checking system dependencies.

❯ llvm-config --system-libs                                                                                                                                                                                           14:05:22
-lm -lz -lcurses -llibxml2.tbd

(-llibxml2.tbd is wrong)

A workaround is to add a symbolic link:

ln -s /usr/lib/libxml2.2.dylib /usr/local/lib/liblibxml2.tbd.dylib

It is not ideal, but until llvm produces a fix I’m afraid this is required.
More info here.

Well sorry I cannot give more insight on that issue, but as Crystalline embarks the crystal compiler it does require a large amount of RAM to compile, and it takes a while.

Killed] [0/1] Codegen (bc+obj)

Did you kill it yourself? Because if so, it looks like it was still compiling.

In all cases, I’m planning to provide compiled binaries in the future.

Hmm sorry no, I’m not a Window user (except for playing games :video_game:).

Well it is quite simple actually. I’m mostly relying on what you guys did already, the Crystal parser & semantic analysis to produce a typed AST and I extract meaningful information using visitors to display that in the editor.

Of course, I try to cache the result as most as possible - when possible, and be a bit clever on how to process requests in parallel, in threads isolated from the language server I/O loop and use some locks to not overload the server.

For instance it will not trigger a full scale analysis when you just hover or go to a definition every time. It will just reuse the last analysis result.

It will also not run 15 compiler tasks at the same time if you ask for autocompletion 15 times after typing a character, it will wait for the pending analysis to complete and run another one afterwards to process the latest updates. And it will not block in the meantime if the user just wants to use the formatter.

There really is a lot of room for improvements, but for small to medium scale projects with a decent computer it seems to be working fine for me.

I don’t have a lot of spare time unfortunately these days, so I won’t be able to write down more than that. The first step would be to document the code and refine the features.

3 Likes

Worked for me. Thanks.

1 Like

Hi,
Have you interest in using https://github.com/crystal-lang-tools/lsp ? if so, me too, as this repository seems dead, I keep a fork on https://github.com/hugopl/lsp with my patches… and I’m using it to write a LSP client for an editor, Tijolo.

Hey @hugopl,

I tried using it at first but I had issues because:

  • it was relying on an old version of the standard
  • some json structures conflict when deserializing
  • there is only type definitions in the shard - I needed an up-to-date server

So for Crystalline I wrote the LSP part from scratch alongside a generic server loop implementation. I was planning to extract this part as a shard but as I implemented only the messages I needed and skipped specs so we’ll see in the future!

Oh thank you! It’s great!
It is better to uninstall Scry or Crystalline comes as a complement?

1 Like

Awesome! :+1: Just write in the README that LLVM 8 is needed (it is not possible to compile with LLVM 10).

1 Like

Thanks! :smile:

It’s either one or the other.

Thanks! :+1:

I don’t really know about other OSes, but on macos it is technically possible to compile with LLVM10 even though there is a bug in the current minor version.

I posted the workaround earlier:

It is not obvious though, and you’re right to highlight the fact that I should definitely write something in the readme :wink:.

OK thanks

Yep, I’m aware of the first two issues you said, the third one isn’t really an issue because the shard idea is to have only the type definitions decoupled from any client/server implementation… to avoid the boring task of replicating them from the spec… I’m using it because it saved some of my time and as I use only a tiny part of LSP, the structures conflicts aren’t a problem (yet) for me.

I saw you use partial text-sync on Crystaline, this is very good… scry uses full text sync, i.e. ask the client to send the whole file on every change, something really slow and non-sense.

1 Like

Yes I understand the idea, and I was actually not talking about a full server implementation.

That was a bit obscure, but when I was talking about “server” I was referring to a class orchestrating the whole protocol (requests / notifications / responses / replies / errors), dispatching the messages to an external entity in a non blocking way when needed and replying to clients. So basically the I/O loop, but without any concrete action taken when a message is processed.

The actual implementation could then be delegated to a controller class separate from the shard.

This is what I tried to do in the /lsp part of Crystalline.

Install on Ubuntu 18.04 (WIP).

It’s safer to use the same (or closest) LLVM version that Crystal compiler. When writing this message:

crystal version
Crystal 0.35.1 [5999ae29b] (2020-06-19)

LLVM: 8.0.0
Default target: x86_64-unknown-linux-gnu

So LLVM 8 (but the ./llvm.sh official script support v9 and +, I have a compil error)

git clone https://github.com/elbywan/crystalline
cd ./crystalline

# Install llvm
sudo apt-get update
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 9
# whereis llvm-config-9 (v9 for me), when located add the path to env
export LLVM_CONFIG=/usr/bin/llvm-config-9

# build Crystalline
mkdir ./bin
crystal build ./src/crystalline.cr  -o ./bin/crystalline --release --no-debug --progress  -Dpreview_mt

Then make it executable chmod +x crystalline, then add crystalline to a bin path (executable), like mv ./crystalline $HOME/bin/crystalline or /usr/local/bin or /usr/bin

But I have an error during the Crystalline build. I will test again on the next Crystal version.

Hello!

This project is a very good news!

As a contributor on scry (for various reasons I stopped doing crystal for now though…) you’re doing it right!
I’m happy that someone is taking over this subject that way!!

1 Like

I wonder if crystalline could be renamed to something else… just because of the fact that now that I have it in my path, autocompleting crys stops at crystal without a space, where previously it was the only binary I had matching that.

Is it needed to put crystalline in the path at all if it’s needed to be configured in vscode?

No, it’s not needed to have it in a location covered by the path env :wink:. Providing the absolute location in the vscode configuration option should be good enough.

Actually I just remembered that I put something about moving the binary to a folder covered by the PATH env in the readme. I’ll update to remove that part.

Small update: pre-built binaries are now available, it should greatly simplify the installation step.

3 Likes

:+1:

IMHO not installing it on system path should just make things harder (or at least less straight forward) to all other editors… i.e. require an extra step from user… because for sure every Linux distro will put this binary in a different location when crystalline start to get packaged and shipped by Linux distros.

It is not the Linux distribution that chooses the path but the maintainer of the package. So no problem on this side.