mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 10:49:54 +00:00
feat(els): parallelize Server
This commit is contained in:
parent
5aa73ef19b
commit
d49e6fa70c
7 changed files with 298 additions and 56 deletions
140
crates/els/channels.rs
Normal file
140
crates/els/channels.rs
Normal file
|
@ -0,0 +1,140 @@
|
|||
use std::sync::mpsc;
|
||||
|
||||
use erg_compiler::artifact::BuildRunnable;
|
||||
use erg_compiler::erg_parser::parse::Parsable;
|
||||
|
||||
use lsp_types::request::{
|
||||
CodeActionRequest, CodeActionResolveRequest, CodeLensRequest, Completion, ExecuteCommand,
|
||||
GotoDefinition, HoverRequest, InlayHintRequest, References, ResolveCompletionItem,
|
||||
SemanticTokensFullRequest, SignatureHelpRequest, WillRenameFiles,
|
||||
};
|
||||
use lsp_types::{
|
||||
CodeAction, CodeActionParams, CodeLensParams, CompletionItem, CompletionParams,
|
||||
ExecuteCommandParams, GotoDefinitionParams, HoverParams, InlayHintParams, ReferenceParams,
|
||||
RenameFilesParams, SemanticTokensParams, SignatureHelpParams,
|
||||
};
|
||||
|
||||
use crate::server::Server;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SendChannels {
|
||||
completion: mpsc::Sender<(i64, CompletionParams)>,
|
||||
resolve_completion: mpsc::Sender<(i64, CompletionItem)>,
|
||||
goto_definition: mpsc::Sender<(i64, GotoDefinitionParams)>,
|
||||
semantic_tokens_full: mpsc::Sender<(i64, SemanticTokensParams)>,
|
||||
inlay_hint: mpsc::Sender<(i64, InlayHintParams)>,
|
||||
hover: mpsc::Sender<(i64, HoverParams)>,
|
||||
references: mpsc::Sender<(i64, ReferenceParams)>,
|
||||
code_lens: mpsc::Sender<(i64, CodeLensParams)>,
|
||||
code_action: mpsc::Sender<(i64, CodeActionParams)>,
|
||||
code_action_resolve: mpsc::Sender<(i64, CodeAction)>,
|
||||
signature_help: mpsc::Sender<(i64, SignatureHelpParams)>,
|
||||
will_rename_files: mpsc::Sender<(i64, RenameFilesParams)>,
|
||||
execute_command: mpsc::Sender<(i64, ExecuteCommandParams)>,
|
||||
}
|
||||
|
||||
impl SendChannels {
|
||||
pub fn new() -> (Self, ReceiveChannels) {
|
||||
let (tx_completion, rx_completion) = mpsc::channel();
|
||||
let (tx_resolve_completion, rx_resolve_completion) = mpsc::channel();
|
||||
let (tx_goto_definition, rx_goto_definition) = mpsc::channel();
|
||||
let (tx_semantic_tokens_full, rx_semantic_tokens_full) = mpsc::channel();
|
||||
let (tx_inlay_hint, rx_inlay_hint) = mpsc::channel();
|
||||
let (tx_hover, rx_hover) = mpsc::channel();
|
||||
let (tx_references, rx_references) = mpsc::channel();
|
||||
let (tx_code_lens, rx_code_lens) = mpsc::channel();
|
||||
let (tx_code_action, rx_code_action) = mpsc::channel();
|
||||
let (tx_code_action_resolve, rx_code_action_resolve) = mpsc::channel();
|
||||
let (tx_sig_help, rx_sig_help) = mpsc::channel();
|
||||
let (tx_will_rename_files, rx_will_rename_files) = mpsc::channel();
|
||||
let (tx_execute_command, rx_execute_command) = mpsc::channel();
|
||||
(
|
||||
Self {
|
||||
completion: tx_completion,
|
||||
resolve_completion: tx_resolve_completion,
|
||||
goto_definition: tx_goto_definition,
|
||||
semantic_tokens_full: tx_semantic_tokens_full,
|
||||
inlay_hint: tx_inlay_hint,
|
||||
hover: tx_hover,
|
||||
references: tx_references,
|
||||
code_lens: tx_code_lens,
|
||||
code_action: tx_code_action,
|
||||
code_action_resolve: tx_code_action_resolve,
|
||||
signature_help: tx_sig_help,
|
||||
will_rename_files: tx_will_rename_files,
|
||||
execute_command: tx_execute_command,
|
||||
},
|
||||
ReceiveChannels {
|
||||
completion: rx_completion,
|
||||
resolve_completion: rx_resolve_completion,
|
||||
goto_definition: rx_goto_definition,
|
||||
semantic_tokens_full: rx_semantic_tokens_full,
|
||||
inlay_hint: rx_inlay_hint,
|
||||
hover: rx_hover,
|
||||
references: rx_references,
|
||||
code_lens: rx_code_lens,
|
||||
code_action: rx_code_action,
|
||||
code_action_resolve: rx_code_action_resolve,
|
||||
signature_help: rx_sig_help,
|
||||
will_rename_files: rx_will_rename_files,
|
||||
execute_command: rx_execute_command,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ReceiveChannels {
|
||||
pub(crate) completion: mpsc::Receiver<(i64, CompletionParams)>,
|
||||
pub(crate) resolve_completion: mpsc::Receiver<(i64, CompletionItem)>,
|
||||
pub(crate) goto_definition: mpsc::Receiver<(i64, GotoDefinitionParams)>,
|
||||
pub(crate) semantic_tokens_full: mpsc::Receiver<(i64, SemanticTokensParams)>,
|
||||
pub(crate) inlay_hint: mpsc::Receiver<(i64, InlayHintParams)>,
|
||||
pub(crate) hover: mpsc::Receiver<(i64, HoverParams)>,
|
||||
pub(crate) references: mpsc::Receiver<(i64, ReferenceParams)>,
|
||||
pub(crate) code_lens: mpsc::Receiver<(i64, CodeLensParams)>,
|
||||
pub(crate) code_action: mpsc::Receiver<(i64, CodeActionParams)>,
|
||||
pub(crate) code_action_resolve: mpsc::Receiver<(i64, CodeAction)>,
|
||||
pub(crate) signature_help: mpsc::Receiver<(i64, SignatureHelpParams)>,
|
||||
pub(crate) will_rename_files: mpsc::Receiver<(i64, RenameFilesParams)>,
|
||||
pub(crate) execute_command: mpsc::Receiver<(i64, ExecuteCommandParams)>,
|
||||
}
|
||||
|
||||
pub trait Sendable<R: lsp_types::request::Request + 'static> {
|
||||
fn send(&self, id: i64, params: R::Params);
|
||||
}
|
||||
|
||||
macro_rules! impl_sendable {
|
||||
($Request: ident, $Params: ident, $receiver: ident) => {
|
||||
impl<Checker: BuildRunnable, Parser: Parsable> Sendable<$Request>
|
||||
for Server<Checker, Parser>
|
||||
{
|
||||
fn send(&self, id: i64, params: $Params) {
|
||||
self.channels
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.$receiver
|
||||
.send((id, params))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_sendable!(Completion, CompletionParams, completion);
|
||||
impl_sendable!(ResolveCompletionItem, CompletionItem, resolve_completion);
|
||||
impl_sendable!(GotoDefinition, GotoDefinitionParams, goto_definition);
|
||||
impl_sendable!(
|
||||
SemanticTokensFullRequest,
|
||||
SemanticTokensParams,
|
||||
semantic_tokens_full
|
||||
);
|
||||
impl_sendable!(InlayHintRequest, InlayHintParams, inlay_hint);
|
||||
impl_sendable!(HoverRequest, HoverParams, hover);
|
||||
impl_sendable!(References, ReferenceParams, references);
|
||||
impl_sendable!(CodeLensRequest, CodeLensParams, code_lens);
|
||||
impl_sendable!(CodeActionRequest, CodeActionParams, code_action);
|
||||
impl_sendable!(CodeActionResolveRequest, CodeAction, code_action_resolve);
|
||||
impl_sendable!(SignatureHelpRequest, SignatureHelpParams, signature_help);
|
||||
impl_sendable!(WillRenameFiles, RenameFilesParams, will_rename_files);
|
||||
impl_sendable!(ExecuteCommand, ExecuteCommandParams, execute_command);
|
|
@ -179,7 +179,7 @@ impl<'b> CompletionOrderSetter<'b> {
|
|||
|
||||
type Cache = Shared<Dict<String, Vec<CompletionItem>>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CompletionCache {
|
||||
cache: Cache,
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
mod channels;
|
||||
mod code_action;
|
||||
mod code_lens;
|
||||
mod command;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
mod channels;
|
||||
mod code_action;
|
||||
mod code_lens;
|
||||
mod command;
|
||||
|
|
|
@ -3,27 +3,25 @@ use std::io::{stdin, stdout, BufRead, Read, Write};
|
|||
use std::ops::Not;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
use std::sync::mpsc;
|
||||
|
||||
use erg_common::config::ErgConfig;
|
||||
use erg_common::consts::PYTHON_MODE;
|
||||
use erg_common::dict::Dict;
|
||||
use erg_common::env::erg_path;
|
||||
use erg_common::shared::{
|
||||
MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLockReadGuard, RwLockWriteGuard, Shared,
|
||||
};
|
||||
use erg_compiler::erg_parser::ast::Module;
|
||||
use erg_compiler::erg_parser::parse::{Parsable, SimpleParser};
|
||||
use erg_compiler::lower::ASTLowerer;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use serde_json::Value;
|
||||
|
||||
use erg_common::config::ErgConfig;
|
||||
use erg_common::dict::Dict;
|
||||
use erg_common::env::erg_path;
|
||||
use erg_common::normalize_path;
|
||||
use erg_common::spawn::spawn_new_thread;
|
||||
use erg_common::{fn_name, normalize_path};
|
||||
|
||||
use erg_compiler::artifact::{BuildRunnable, IncompleteArtifact};
|
||||
use erg_compiler::build_hir::HIRBuilder;
|
||||
use erg_compiler::context::{Context, ModuleContext};
|
||||
use erg_compiler::erg_parser::ast::Module;
|
||||
use erg_compiler::erg_parser::parse::{Parsable, SimpleParser};
|
||||
use erg_compiler::hir::{Expr, HIR};
|
||||
use erg_compiler::lower::ASTLowerer;
|
||||
use erg_compiler::module::{SharedCompilerResource, SharedModuleIndex};
|
||||
use erg_compiler::ty::HasType;
|
||||
|
||||
|
@ -41,6 +39,11 @@ use lsp_types::{
|
|||
WorkDoneProgressOptions,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::channels::{SendChannels, Sendable};
|
||||
use crate::completion::CompletionCache;
|
||||
use crate::file_cache::FileCache;
|
||||
use crate::hir_visitor::HIRVisitor;
|
||||
|
@ -191,7 +194,7 @@ impl AnalysisResult {
|
|||
|
||||
pub(crate) const TRIGGER_CHARS: [&str; 4] = [".", ":", "(", " "];
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct AnalysisResultCache(Shared<Dict<NormalizedUrl, AnalysisResult>>);
|
||||
|
||||
impl AnalysisResultCache {
|
||||
|
@ -265,6 +268,41 @@ impl AnalysisResultCache {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ModuleCache(Shared<Dict<NormalizedUrl, ModuleContext>>);
|
||||
|
||||
impl ModuleCache {
|
||||
pub fn new() -> Self {
|
||||
Self(Shared::new(Dict::new()))
|
||||
}
|
||||
|
||||
pub fn get(&self, uri: &NormalizedUrl) -> Option<&ModuleContext> {
|
||||
let _ref = self.0.borrow();
|
||||
let ref_ = unsafe { self.0.as_ptr().as_ref() };
|
||||
ref_.unwrap().get(uri)
|
||||
}
|
||||
|
||||
pub fn get_mut(&self, uri: &NormalizedUrl) -> Option<&mut ModuleContext> {
|
||||
let _ref = self.0.borrow_mut();
|
||||
let ref_ = unsafe { self.0.as_ptr().as_mut() };
|
||||
ref_.unwrap().get_mut(uri)
|
||||
}
|
||||
|
||||
pub fn insert(&self, uri: NormalizedUrl, module: ModuleContext) {
|
||||
self.0.borrow_mut().insert(uri, module);
|
||||
}
|
||||
|
||||
pub fn remove(&self, uri: &NormalizedUrl) -> Option<ModuleContext> {
|
||||
self.0.borrow_mut().remove(uri)
|
||||
}
|
||||
|
||||
pub fn values(&self) -> std::collections::hash_map::Values<NormalizedUrl, ModuleContext> {
|
||||
let _ref = self.0.borrow();
|
||||
let ref_ = unsafe { self.0.as_ptr().as_ref() };
|
||||
ref_.unwrap().values()
|
||||
}
|
||||
}
|
||||
|
||||
/// A Language Server, which can be used any object implementing `BuildRunnable` internally by passing it as a generic parameter.
|
||||
#[derive(Debug)]
|
||||
pub struct Server<Checker: BuildRunnable = HIRBuilder, Parser: Parsable = SimpleParser> {
|
||||
|
@ -276,12 +314,33 @@ pub struct Server<Checker: BuildRunnable = HIRBuilder, Parser: Parsable = Simple
|
|||
pub(crate) opt_features: Vec<OptionalFeatures>,
|
||||
pub(crate) file_cache: FileCache,
|
||||
pub(crate) comp_cache: CompletionCache,
|
||||
// TODO: ModuleContextCache
|
||||
pub(crate) modules: Dict<NormalizedUrl, ModuleContext>,
|
||||
pub(crate) modules: ModuleCache,
|
||||
pub(crate) analysis_result: AnalysisResultCache,
|
||||
pub(crate) current_sig: Option<Expr>,
|
||||
pub(crate) _parser: std::marker::PhantomData<Parser>,
|
||||
pub(crate) _checker: std::marker::PhantomData<Checker>,
|
||||
pub(crate) channels: Option<SendChannels>,
|
||||
pub(crate) _parser: std::marker::PhantomData<fn() -> Parser>,
|
||||
pub(crate) _checker: std::marker::PhantomData<fn() -> Checker>,
|
||||
}
|
||||
|
||||
impl<C: BuildRunnable, P: Parsable> Clone for Server<C, P> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
cfg: self.cfg.clone(),
|
||||
home: self.home.clone(),
|
||||
erg_path: self.erg_path.clone(),
|
||||
client_capas: self.client_capas.clone(),
|
||||
disabled_features: self.disabled_features.clone(),
|
||||
opt_features: self.opt_features.clone(),
|
||||
file_cache: self.file_cache.clone(),
|
||||
comp_cache: self.comp_cache.clone(),
|
||||
modules: self.modules.clone(),
|
||||
analysis_result: self.analysis_result.clone(),
|
||||
current_sig: self.current_sig.clone(),
|
||||
channels: self.channels.clone(),
|
||||
_parser: std::marker::PhantomData,
|
||||
_checker: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
||||
|
@ -295,9 +354,10 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
disabled_features: vec![],
|
||||
opt_features: vec![],
|
||||
file_cache: FileCache::new(),
|
||||
modules: Dict::new(),
|
||||
modules: ModuleCache::new(),
|
||||
analysis_result: AnalysisResultCache::new(),
|
||||
current_sig: None,
|
||||
channels: None,
|
||||
_parser: std::marker::PhantomData,
|
||||
_checker: std::marker::PhantomData,
|
||||
}
|
||||
|
@ -420,6 +480,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
result.capabilities.code_lens_provider = Some(CodeLensOptions {
|
||||
resolve_provider: Some(false),
|
||||
});
|
||||
self.init_services();
|
||||
send(&json!({
|
||||
"jsonrpc": "2.0",
|
||||
"id": id,
|
||||
|
@ -427,6 +488,45 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
}))
|
||||
}
|
||||
|
||||
fn init_services(&mut self) {
|
||||
let (senders, receivers) = SendChannels::new();
|
||||
self.channels = Some(senders);
|
||||
self.start_service::<Completion>(receivers.completion, Self::handle_completion);
|
||||
self.start_service::<ResolveCompletionItem>(
|
||||
receivers.resolve_completion,
|
||||
Self::handle_resolve_completion,
|
||||
);
|
||||
self.start_service::<GotoDefinition>(
|
||||
receivers.goto_definition,
|
||||
Self::handle_goto_definition,
|
||||
);
|
||||
self.start_service::<SemanticTokensFullRequest>(
|
||||
receivers.semantic_tokens_full,
|
||||
Self::handle_semantic_tokens_full,
|
||||
);
|
||||
self.start_service::<InlayHintRequest>(receivers.inlay_hint, Self::handle_inlay_hint);
|
||||
self.start_service::<HoverRequest>(receivers.hover, Self::handle_hover);
|
||||
self.start_service::<References>(receivers.references, Self::handle_references);
|
||||
self.start_service::<CodeLensRequest>(receivers.code_lens, Self::handle_code_lens);
|
||||
self.start_service::<CodeActionRequest>(receivers.code_action, Self::handle_code_action);
|
||||
self.start_service::<CodeActionResolveRequest>(
|
||||
receivers.code_action_resolve,
|
||||
Self::handle_code_action_resolve,
|
||||
);
|
||||
self.start_service::<SignatureHelpRequest>(
|
||||
receivers.signature_help,
|
||||
Self::handle_signature_help,
|
||||
);
|
||||
self.start_service::<WillRenameFiles>(
|
||||
receivers.will_rename_files,
|
||||
Self::handle_will_rename_files,
|
||||
);
|
||||
self.start_service::<ExecuteCommand>(
|
||||
receivers.execute_command,
|
||||
Self::handle_execute_command,
|
||||
);
|
||||
}
|
||||
|
||||
fn exit(&self) -> ELSResult<()> {
|
||||
send_log("exiting ELS")?;
|
||||
std::process::exit(0);
|
||||
|
@ -523,18 +623,34 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
}
|
||||
}
|
||||
|
||||
fn wrap<R>(
|
||||
&mut self,
|
||||
id: i64,
|
||||
msg: &Value,
|
||||
handler: Handler<Server<Checker, Parser>, R::Params, R::Result>,
|
||||
) -> ELSResult<()>
|
||||
fn parse_send<R>(&self, id: i64, msg: &Value) -> ELSResult<()>
|
||||
where
|
||||
R: lsp_types::request::Request + 'static,
|
||||
R::Result: Serialize,
|
||||
Server<Checker, Parser>: Sendable<R>,
|
||||
{
|
||||
let params = R::Params::deserialize(&msg["params"])?;
|
||||
send(&LSPResult::new(id, handler(self, params)?))
|
||||
self.send(id, params);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn start_service<R>(
|
||||
&self,
|
||||
receiver: mpsc::Receiver<(i64, R::Params)>,
|
||||
handler: Handler<Server<Checker, Parser>, R::Params, R::Result>,
|
||||
) where
|
||||
R: lsp_types::request::Request + 'static,
|
||||
R::Params: Send,
|
||||
R::Result: Serialize,
|
||||
{
|
||||
let mut _self = self.clone();
|
||||
spawn_new_thread(
|
||||
move || loop {
|
||||
let (id, params) = receiver.recv().unwrap();
|
||||
let _ = send(&LSPResult::new(id, handler(&mut _self, params).unwrap()));
|
||||
},
|
||||
fn_name!(),
|
||||
);
|
||||
}
|
||||
|
||||
fn handle_request(&mut self, msg: &Value, id: i64, method: &str) -> ELSResult<()> {
|
||||
|
@ -542,39 +658,23 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
"initialize" => self.init(msg, id),
|
||||
"shutdown" => self.shutdown(id),
|
||||
Rename::METHOD => self.rename(msg),
|
||||
Completion::METHOD => self.wrap::<Completion>(id, msg, Self::handle_completion),
|
||||
ResolveCompletionItem::METHOD => {
|
||||
self.wrap::<ResolveCompletionItem>(id, msg, Self::handle_resolve_completion)
|
||||
}
|
||||
GotoDefinition::METHOD => {
|
||||
self.wrap::<GotoDefinition>(id, msg, Self::handle_goto_definition)
|
||||
}
|
||||
HoverRequest::METHOD => self.wrap::<HoverRequest>(id, msg, Self::handle_hover),
|
||||
References::METHOD => self.wrap::<References>(id, msg, Self::handle_references),
|
||||
Completion::METHOD => self.parse_send::<Completion>(id, msg),
|
||||
ResolveCompletionItem::METHOD => self.parse_send::<ResolveCompletionItem>(id, msg),
|
||||
GotoDefinition::METHOD => self.parse_send::<GotoDefinition>(id, msg),
|
||||
HoverRequest::METHOD => self.parse_send::<HoverRequest>(id, msg),
|
||||
References::METHOD => self.parse_send::<References>(id, msg),
|
||||
SemanticTokensFullRequest::METHOD => {
|
||||
self.wrap::<SemanticTokensFullRequest>(id, msg, Self::handle_semantic_tokens_full)
|
||||
}
|
||||
InlayHintRequest::METHOD => {
|
||||
self.wrap::<InlayHintRequest>(id, msg, Self::handle_inlay_hint)
|
||||
}
|
||||
CodeActionRequest::METHOD => {
|
||||
self.wrap::<CodeActionRequest>(id, msg, Self::handle_code_action)
|
||||
self.parse_send::<SemanticTokensFullRequest>(id, msg)
|
||||
}
|
||||
InlayHintRequest::METHOD => self.parse_send::<InlayHintRequest>(id, msg),
|
||||
CodeActionRequest::METHOD => self.parse_send::<CodeActionRequest>(id, msg),
|
||||
CodeActionResolveRequest::METHOD => {
|
||||
self.wrap::<CodeActionResolveRequest>(id, msg, Self::handle_code_action_resolve)
|
||||
}
|
||||
SignatureHelpRequest::METHOD => {
|
||||
self.wrap::<SignatureHelpRequest>(id, msg, Self::handle_signature_help)
|
||||
}
|
||||
CodeLensRequest::METHOD => {
|
||||
self.wrap::<CodeLensRequest>(id, msg, Self::handle_code_lens)
|
||||
}
|
||||
WillRenameFiles::METHOD => {
|
||||
self.wrap::<WillRenameFiles>(id, msg, Self::handle_will_rename_files)
|
||||
}
|
||||
ExecuteCommand::METHOD => {
|
||||
self.wrap::<ExecuteCommand>(id, msg, Self::handle_execute_command)
|
||||
self.parse_send::<CodeActionResolveRequest>(id, msg)
|
||||
}
|
||||
SignatureHelpRequest::METHOD => self.parse_send::<SignatureHelpRequest>(id, msg),
|
||||
CodeLensRequest::METHOD => self.parse_send::<CodeLensRequest>(id, msg),
|
||||
WillRenameFiles::METHOD => self.parse_send::<WillRenameFiles>(id, msg),
|
||||
ExecuteCommand::METHOD => self.parse_send::<ExecuteCommand>(id, msg),
|
||||
other => send_error(Some(id), -32600, format!("{other} is not supported")),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,4 +103,4 @@ pub trait Buildable<T = HIR> {
|
|||
fn get_context(&self) -> Option<&ModuleContext>;
|
||||
}
|
||||
|
||||
pub trait BuildRunnable<T = HIR>: Buildable<T> + Runnable {}
|
||||
pub trait BuildRunnable<T = HIR>: Buildable<T> + Runnable + 'static {}
|
||||
|
|
|
@ -98,7 +98,7 @@ macro_rules! expect_pop {
|
|||
};
|
||||
}
|
||||
|
||||
pub trait Parsable {
|
||||
pub trait Parsable: 'static {
|
||||
fn parse(code: String) -> Result<CompleteArtifact, IncompleteArtifact<Module, ParseErrors>>;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue