A language server for Bjolang

Runs the compiler in-process against the Bjolang checkout beside it, and
answers diagnostics, an outline, go to definition, hover and completion,
plus a request of its own for macro expansion.

Diagnostics come from the compiler's own check of the editor's text,
saved or not: on open, on save, and 400 ms after typing pauses. The
outline, definitions, hovers and completions read only as far as the
reader, with no type checking, so they answer on every request: the
top-level names of the file, its imports and the prelude, local names
from the binding forms the parser knows, the declarations and docs as
written, and the builtins with their types. emacs/bjolang-lsp.el shows a
macro call's expansion, one step or all of it, in a buffer.

test/smoke.py drives the server as an editor would.

🤖 Generated with [ECA](https://eca.dev)

Co-Authored-By: eca-agent <git@eca.dev>
This commit is contained in:
Linus Björnstam 2026-10-15 22:38:22 +02:00
commit c6f357c6f8
13 changed files with 2776 additions and 0 deletions

37
BjolangLsp.fsproj Normal file
View file

@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<NuGetAudit>false</NuGetAudit>
<!-- The compiler's tokenizer recurses once per token and needs tail
calls, which F# turns off in Debug by default. -->
<Tailcalls>true</Tailcalls>
<!-- Where the Bjolang checkout is, beside this one. The server runs the
compiler in-process, and the compiler finds the standard library
and the runtime assemblies by walking up from its own binary, which
here is in this project's bin. So the checkout's path is baked in,
and BJOLANG_HOME overrides it. -->
<BjolangHome>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../Bjolang'))</BjolangHome>
</PropertyGroup>
<ItemGroup>
<AssemblyMetadata Include="BjolangHome" Value="$(BjolangHome)" />
</ItemGroup>
<ItemGroup>
<Compile Include="Rpc.fs" />
<Compile Include="Expansion.fs" />
<Compile Include="Check.fs" />
<Compile Include="Symbols.fs" />
<Compile Include="Scope.fs" />
<Compile Include="Hover.fs" />
<Compile Include="Completion.fs" />
<Compile Include="Program.fs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(BjolangHome)/Bjolang.fsproj" />
</ItemGroup>
</Project>