feat: register server capability correctly (#397)

## Summary
- register workspace and text document capabilities through the
structured LSP capability types
- advertise completion, signature help, declaration, definition,
implementation, type definition, and reference support more explicitly
- add placeholder handlers for declaration, type definition, and
implementation requests so the advertised capabilities have matching
routes

## Testing
- Not run (not requested)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Added workspace folder support for improved project tracking.
* Registered navigation handlers for type-definition, implementation,
and declaration (currently return a “not supported yet” placeholder).
* **Improvements**
* Enhanced completion and signature help with explicit trigger
characters and clearer capability declarations.
* **Tests**
* Relaxed capability assertions to recognize more nuanced
enabled/disabled states.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Myriad-Dreamin
2026-04-06 10:23:38 +08:00
committed by GitHub
parent 8d4ad26834
commit d04bc6f774
2 changed files with 74 additions and 23 deletions

View File

@@ -11,6 +11,7 @@
#include "eventide/ipc/json_codec.h"
#include "eventide/ipc/lsp/position.h"
#include "eventide/ipc/lsp/protocol.h"
#include "eventide/ipc/lsp/uri.h"
#include "eventide/reflection/enum.h"
#include "eventide/serde/json/json.h"
@@ -1475,6 +1476,8 @@ et::task<std::optional<SymbolInfo>>
}
void MasterServer::register_handlers() {
using StringVec = std::vector<std::string>;
// === initialize ===
peer.on_request([this](RequestContext& ctx, const protocol::InitializeParams& params)
-> RequestResult<protocol::InitializeParams> {
@@ -1494,28 +1497,53 @@ void MasterServer::register_handlers() {
// Build capabilities
protocol::InitializeResult result;
auto& caps = result.capabilities;
// Text document sync: incremental
protocol::TextDocumentSyncOptions sync_opts;
sync_opts.open_close = true;
sync_opts.change = protocol::TextDocumentSyncKind::Incremental;
sync_opts.save = protocol::variant<protocol::boolean, protocol::SaveOptions>{true};
result.capabilities.text_document_sync = std::move(sync_opts);
caps.text_document_sync = protocol::TextDocumentSyncOptions{
.open_close = true,
.change = protocol::TextDocumentSyncKind::Incremental,
.save = protocol::variant<protocol::boolean, protocol::SaveOptions>{true},
};
// watch workspace folder changes.
caps.workspace = protocol::WorkspaceOptions{};
caps.workspace->workspace_folders = protocol::WorkspaceFoldersServerCapabilities{
.supported = true,
.change_notifications = true,
};
// Feature capabilities
result.capabilities.hover_provider = true;
result.capabilities.completion_provider = protocol::CompletionOptions{};
result.capabilities.signature_help_provider = protocol::SignatureHelpOptions{};
result.capabilities.definition_provider = true;
result.capabilities.references_provider = true;
result.capabilities.document_symbol_provider = true;
result.capabilities.document_link_provider = protocol::DocumentLinkOptions{};
result.capabilities.code_action_provider = true;
result.capabilities.folding_range_provider = true;
result.capabilities.inlay_hint_provider = true;
result.capabilities.call_hierarchy_provider = true;
result.capabilities.type_hierarchy_provider = true;
result.capabilities.workspace_symbol_provider = true;
caps.hover_provider = true;
caps.completion_provider = protocol::CompletionOptions{
.trigger_characters = StringVec{".", "<", ">", ":", "\"", "/", "*"},
};
caps.signature_help_provider = protocol::SignatureHelpOptions{
.trigger_characters = StringVec{"(", ")", "{", "}", "<", ">", ","},
};
/// FIXME: In the future, we would support work done progress.
caps.declaration_provider = protocol::DeclarationOptions{
.work_done_progress = false,
};
caps.definition_provider = protocol::DefinitionOptions{
.work_done_progress = false,
};
caps.implementation_provider = protocol::ImplementationOptions{
.work_done_progress = false,
};
caps.type_definition_provider = protocol::TypeDefinitionOptions{
.work_done_progress = false,
};
caps.references_provider = protocol::ReferenceOptions{
.work_done_progress = false,
};
caps.document_symbol_provider = true;
caps.document_link_provider = protocol::DocumentLinkOptions{};
caps.code_action_provider = true;
caps.folding_range_provider = true;
caps.inlay_hint_provider = true;
caps.call_hierarchy_provider = true;
caps.type_hierarchy_provider = true;
caps.workspace_symbol_provider = true;
// Semantic tokens
protocol::SemanticTokensOptions sem_opts;
@@ -1826,6 +1854,24 @@ void MasterServer::register_handlers() {
co_return refs;
});
// --- textDocument/typeDefinition ---
peer.on_request(
[this](RequestContext& ctx, const protocol::TypeDefinitionParams& params) -> RawResult {
co_return serde_raw{"null"}; // not supported yet
});
// --- textDocument/implementation ---
peer.on_request(
[this](RequestContext& ctx, const protocol::ImplementationParams& params) -> RawResult {
co_return serde_raw{"null"}; // not supported yet
});
// --- textDocument/declaration ---
peer.on_request(
[this](RequestContext& ctx, const protocol::DeclarationParams& params) -> RawResult {
co_return serde_raw{"null"}; // not supported yet
});
// =========================================================================
// Feature requests routed to stateless workers
// =========================================================================