A modern, high-performance .NET framework for building Language Server Protocol (LSP) servers with full LSP 3.18 specification support.
- π― Full LSP 3.18 Support - Complete implementation of the latest LSP specification
- β‘ High Performance - Built with System.Text.Json source generation for optimal performance
- π AOT Ready - Full support for Ahead-of-Time (AOT) compilation
- π¦ Zero Dependencies - No dependency on Newtonsoft.Json or other third-party libraries
- πͺ Window & Progress - Complete support for window messages, logging, and progress reporting
- π§ Easy to Use - Simple, intuitive API for building language servers
- π Performance Metrics - Built-in performance monitoring and telemetry support
- π¨ Type Safe - Strongly typed protocol messages with full IntelliSense support
Install via NuGet Package Manager:
dotnet add package EmmyLua.LanguageServer.FrameworkOr via Package Manager Console:
Install-Package EmmyLua.LanguageServer.Frameworkusing EmmyLua.LanguageServer.Framework.Server;
using EmmyLua.LanguageServer.Framework.Protocol.Message.Initialize;
// Create a language server
var server = LanguageServer.From(Console.OpenStandardInput(), Console.OpenStandardOutput());
// Handle initialization
server.OnInitialize((request, serverInfo) =>
{
serverInfo.Name = "My Language Server";
serverInfo.Version = "1.0.0";
return Task.CompletedTask;
});
// Handle initialized notification
server.OnInitialized(async (request) =>
{
await server.Client.LogInfo("Server initialized!");
});
// Run the server
await server.Run();using EmmyLua.LanguageServer.Framework.Server.Handler;
// Create a hover handler
public class MyHoverHandler : HoverHandlerBase
{
protected override Task<Hover?> Handle(HoverParams request, CancellationToken token)
{
var hover = new Hover
{
Contents = new MarkupContent
{
Kind = MarkupKind.Markdown,
Value = "**Hello from LSP!**"
}
};
return Task.FromResult<Hover?>(hover);
}
public override void RegisterCapability(ServerCapabilities serverCapabilities,
ClientCapabilities clientCapabilities)
{
serverCapabilities.HoverProvider = true;
}
}
// Add handler to server
server.AddHandler(new MyHoverHandler());Display messages and collect user input:
// Show a message
await server.Client.ShowMessage(new ShowMessageParams
{
Type = MessageType.Info,
Message = "Operation completed successfully!"
});
// Request user action
var result = await server.Client.ShowMessageRequest(new ShowMessageRequestParams
{
Type = MessageType.Warning,
Message = "Do you want to continue?",
Actions = new List<MessageActionItem>
{
new() { Title = "Yes" },
new() { Title = "No" }
}
}, cancellationToken);
// Log messages
await server.Client.LogError("An error occurred");
await server.Client.LogInfo("Processing file...");Report progress for long-running operations:
// Using the helper class (recommended)
using var progress = await WorkDoneProgressReporter.Create(
server.Client,
title: "Analyzing workspace",
cancellable: true
);
for (int i = 0; i < 100; i++)
{
await progress.Report($"Processing file {i + 1}/100", (uint)i);
}
await progress.End("Analysis complete!");For detailed examples, see LSP_WINDOW_PROGRESS_USAGE.md
Enable performance metrics to monitor your server:
var options = new LanguageServerOptions
{
EnablePerformanceTracing = true,
PerformanceMetricsPrintInterval = TimeSpan.FromMinutes(5)
};
var server = LanguageServer.From(input, output, options);
// Get metrics at any time
var metrics = server.GetMetrics();
Console.WriteLine($"Total requests: {metrics.TotalRequestsHandled}");
Console.WriteLine($"Average duration: {metrics.AverageRequestDurationMs}ms");- β DidOpen / DidChange / DidClose / DidSave
- β WillSave / WillSaveWaitUntil
- β Completion (with resolve support)
- β Hover
- β Signature Help
- β Definition / Declaration / Type Definition / Implementation
- β References
- β Document Highlight
- β Document Symbol
- β Code Action
- β Code Lens
- β Document Link
- β Document Color / Color Presentation
- β Document Formatting / Range Formatting / On Type Formatting
- β Rename / Prepare Rename
- β Folding Range
- β Selection Range
- β Call Hierarchy
- β Semantic Tokens
- β Inlay Hint
- β Inline Value
- β Type Hierarchy
- β Inline Completion
- β Linked Editing Range
- β Workspace Symbols
- β Configuration
- β Workspace Folders
- β File Operations (Create/Rename/Delete)
- β File Watching
- β Diagnostics
- β Execute Command
- β Apply Edit
- β ShowMessage / ShowMessageRequest
- β LogMessage
- β Work Done Progress
- β Telemetry
The framework is designed with extensibility and performance in mind:
βββββββββββββββββββββββββββββββββββββββββββ
β Language Server Application β
βββββββββββββββββββββββββββββββββββββββββββ€
β Handler Layer β
β (HoverHandler, CompletionHandler...) β
βββββββββββββββββββββββββββββββββββββββββββ€
β LanguageServer Core β
β (Protocol, Routing, Lifecycle) β
βββββββββββββββββββββββββββββββββββββββββββ€
β JSON-RPC Protocol Layer β
β (JsonProtocolReader/Writer) β
βββββββββββββββββββββββββββββββββββββββββββ€
β Transport Layer (stdio) β
βββββββββββββββββββββββββββββββββββββββββββ
Check out the LanguageServer.Test project for a complete working example that demonstrates:
- Server initialization
- Multiple handlers implementation
- Configuration management
- Progress reporting
- Error handling
- EmmyLuaAnalyzer - A feature-rich Lua language server
Contributions are welcome! Please read our Contributing Guide for details on how to submit pull requests, report issues, and contribute to the project.
This project is licensed under the MIT License - see the LICENSE file for details.
- π« Report bugs via GitHub Issues
- π‘ Request features via GitHub Discussions
Made with β€οΈ by the EmmyLua community