Skip to content

Commit

Permalink
Merge pull request #435 from erg-lang/para-els
Browse files Browse the repository at this point in the history
Parallelize ELS
  • Loading branch information
mtshiba committed Jun 21, 2023
2 parents 7063056 + e27cf8f commit 4ece884
Show file tree
Hide file tree
Showing 19 changed files with 486 additions and 162 deletions.
140 changes: 140 additions & 0 deletions crates/els/channels.rs
Original file line number Diff line number Diff line change
@@ -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);
2 changes: 1 addition & 1 deletion crates/els/code_lens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {

fn send_trait_impls_lens(&mut self, uri: &NormalizedUrl) -> ELSResult<Vec<CodeLens>> {
let mut result = vec![];
if let Some(hir) = self.get_artifact(uri).and_then(|a| a.object.as_ref()) {
if let Some(hir) = self.analysis_result.get_hir(uri) {
for chunk in hir.module.iter() {
match chunk {
Expr::Def(def) if def.def_kind().is_trait() => {
Expand Down
2 changes: 1 addition & 1 deletion crates/els/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down
11 changes: 4 additions & 7 deletions crates/els/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
}

pub(crate) fn quick_check_file(&mut self, uri: NormalizedUrl) -> ELSResult<()> {
let Some(old) = self.analysis_result.get(&uri).map(|r| &r.ast) else {
let Some(old) = self.analysis_result.get_ast(&uri) else {
crate::_log!("not found");
return Ok(());
};
Expand All @@ -97,16 +97,13 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
};
let ast_diff = ASTDiff::diff(old, &new);
crate::_log!("diff: {ast_diff}");
if let Some(mut lowerer) = self.get_lowerer(&uri) {
let hir = self
.analysis_result
.get_mut(&uri)
.and_then(|r| r.artifact.object.as_mut());
if let Some(mut lowerer) = self.steal_lowerer(&uri) {
let hir = self.analysis_result.get_mut_hir(&uri);
if let Some((hir_diff, hir)) = HIRDiff::new(ast_diff, &mut lowerer).zip(hir) {
crate::_log!("hir_diff: {hir_diff}");
hir_diff.update(hir);
}
self.restore_mod_ctx(uri, lowerer.pop_mod_ctx().unwrap());
self.restore_lowerer(uri, lowerer);
}
// skip checking for dependents
Ok(())
Expand Down
8 changes: 6 additions & 2 deletions crates/els/diff.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::cmp::Ordering::*;
use std::fmt;
use std::ops::{Deref, DerefMut};

use erg_common::traits::Stream;
use erg_compiler::erg_parser::ast;
Expand Down Expand Up @@ -35,7 +36,10 @@ impl fmt::Display for ASTDiff {
/// diff(old: {x, y, z}, new: {x, a, z}) => ASTDiff::Modification(1)
/// diff(old: {x, y, z}, new: {x, y, z}) => ASTDiff::Nop
impl ASTDiff {
pub fn diff(old: &Module, new: &Module) -> ASTDiff {
pub fn diff<M1: Deref<Target = Module>, M2: Deref<Target = Module>>(
old: M1,
new: M2,
) -> ASTDiff {
match old.len().cmp(&new.len()) {
Less => {
let idx = new
Expand Down Expand Up @@ -96,7 +100,7 @@ impl HIRDiff {
}
}

pub fn update(self, old: &mut HIR) {
pub fn update<H: DerefMut<Target = HIR>>(self, mut old: H) {
match self {
Self::Addition(idx, expr) => {
old.module.insert(idx, expr);
Expand Down
2 changes: 1 addition & 1 deletion crates/els/file_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ impl FileCache {
);
}

pub(crate) fn ranged_update(&self, uri: &NormalizedUrl, old: Range, new_code: &str) {
pub(crate) fn _ranged_update(&self, uri: &NormalizedUrl, old: Range, new_code: &str) {
let mut ent = self.files.borrow_mut();
let Some(entry) = ent.get_mut(uri) else {
return;
Expand Down
9 changes: 7 additions & 2 deletions crates/els/hir_visitor.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use erg_common::consts::ERG_MODE;
use erg_common::shared::MappedRwLockReadGuard;
use erg_common::traits::Locational;
use erg_common::Str;
use erg_compiler::erg_parser::token::Token;
Expand All @@ -14,14 +15,18 @@ use crate::util::{self, NormalizedUrl};
/// * cursor(`Token`) -> `Expr` mapping (`get_min_expr`)
/// * cursor(`Token`) -> `VarInfo` mapping (`get_info`)
pub struct HIRVisitor<'a> {
hir: &'a HIR,
hir: MappedRwLockReadGuard<'a, HIR>,
file_cache: &'a FileCache,
uri: NormalizedUrl,
strict_cmp: bool,
}

impl<'a> HIRVisitor<'a> {
pub fn new(hir: &'a HIR, file_cache: &'a FileCache, uri: NormalizedUrl) -> Self {
pub fn new(
hir: MappedRwLockReadGuard<'a, HIR>,
file_cache: &'a FileCache,
uri: NormalizedUrl,
) -> Self {
Self {
hir,
file_cache,
Expand Down
3 changes: 2 additions & 1 deletion crates/els/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
match self.get_definition(&uri, &token)? {
Some(vi) => {
if let Some(line) = vi.def_loc.loc.ln_begin() {
let line0 = line.saturating_sub(1);
let Some(file_path) = vi.def_loc.module.as_ref() else {
return Ok(None);
};
Expand Down Expand Up @@ -137,7 +138,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
let uri = NormalizedUrl::try_from(file_path.as_path())?;
code_block += self
.file_cache
.get_line(&uri, line)
.get_line(&uri, line0)
.unwrap_or_default()
.trim_start();
match code_block.chars().last() {
Expand Down
2 changes: 1 addition & 1 deletion crates/els/inlay_hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
let mut result = vec![];
if let Some(IncompleteArtifact {
object: Some(hir), ..
}) = self.get_artifact(&uri)
}) = self.analysis_result.get_artifact(&uri).as_deref()
{
for chunk in hir.module.iter() {
result.extend(self.get_expr_hint(chunk));
Expand Down
1 change: 1 addition & 0 deletions crates/els/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod channels;
mod code_action;
mod code_lens;
mod command;
Expand Down
1 change: 1 addition & 0 deletions crates/els/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod channels;
mod code_action;
mod code_lens;
mod command;
Expand Down
Loading

0 comments on commit 4ece884

Please sign in to comment.