Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--Cargo.toml61
-rw-r--r--src/act.rs20
-rw-r--r--src/bar.rs2
-rw-r--r--src/commands.rs26
-rw-r--r--src/complete.rs52
-rw-r--r--src/edi/input_handlers/click.rs19
-rw-r--r--src/edi/input_handlers/cursor.rs63
-rw-r--r--src/edi/input_handlers/keyboard.rs50
-rw-r--r--src/edi/lsp_impl.rs159
-rw-r--r--src/edi/lsp_mn.rs14
-rw-r--r--src/edi/lsp_mn/stdio.rs75
-rw-r--r--src/edi/ra.rs9
-rw-r--r--src/edi/st.rs7
-rw-r--r--src/edi/wsedit.rs312
-rw-r--r--src/gotolist.rs36
-rw-r--r--src/hov.rs11
-rw-r--r--src/lsp.rs24
-rw-r--r--src/lsp/client.rs272
-rw-r--r--src/lsp/communication.rs74
-rw-r--r--src/lsp/init_opts.rs180
-rw-r--r--src/lsp/rq.rs17
-rw-r--r--src/main.rs31
-rw-r--r--src/rnd.rs39
-rw-r--r--src/sig.rs19
-rw-r--r--src/sym.rs164
-rw-r--r--src/text.rs33
-rw-r--r--src/text/hist.rs2
-rw-r--r--src/text/inlay.rs6
28 files changed, 1178 insertions, 599 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 45bc3fd..11b7659 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,73 +10,78 @@ pattypan = { git = "https://git.bendn.org/pattypan" }
implicit-fn = "0.1.0"
ropey = "1.6.1"
softbuffer = { version = "0.4.8", default-features = false, features = ["wayland", "x11"] }
-swash = "0.2.9"
+swash = "0.2.10"
winit = { version = "0.31.0-beta.2", default-features = false, features = ["wayland", "x11"] }
-tree-sitter = "0.25.10"
-memchr = "2.8.2"
+tree-sitter = "0.26.12"
+memchr = "2.8.3"
lower = "0.2.1"
amap = "0.1.4"
run_times = "0.1.0"
array_chunks = "1.0.0"
rust-fsm = { git = "https://git.bendn.org/rust-fsm", features = ["diagram"] }
clipp = "0.1.1"
-regex = { version = "1.12.4", features = ["unstable", "use_std"] }
-tree-house = { version = "0.3.0", features = ["fixtures"] }
+regex = { version = "1.13.1", features = ["unstable", "use_std"] }
+tree-house = { version = "0.4.0", features = ["fixtures"] }
# for tree house grammar loading
helix-loader = { git = "https://git.bendn.org/helix" }
helix-core = { git = "https://git.bendn.org/helix" }
-lsp-types = { git = "https://git.bendn.org/helix", package = "helix-lsp-types", features = [
- "proposed",
-] }
+# lsp-types = { git = "https://git.bendn.org/helix", package = "helix-lsp-types", features = [
+ # "proposed",
+# ] }
-lsp-server = { git = "https://git.bendn.org/rust-analyzer" }
-rust-analyzer = { git = "https://git.bendn.org/rust-analyzer" }
+
+lsp-server = { version = "0.7.9" }
+# rust-analyzer = { git = "https://git.bendn.org/rust-analyzer" }
# lsp-server = { path = "../rust-analyzer/lib/lsp-server" }
-# rust-analyzer = { path = "../rust-analyzer/crates/rust-analyzer" }
+rust-analyzer = { path = "../rust-analyzer/crates/rust-analyzer" }
-serde_json = "1.0.150"
-serde = { version = "1.0.228", features = ["unstable"] }
-serde_derive = "1.0.228"
-log = "0.4.32"
+serde_json = "1.0.151"
+serde = { version = "1.0.229", features = ["unstable"] }
+serde_derive = "1.0.229"
+log = "0.4.33"
crossbeam = { version = "0.8.4", features = ["nightly", "crossbeam-channel"] }
test-log = "0.2.21"
-env_logger = "0.11.10"
+env_logger = "0.11.11"
url = "2.5.8"
-tokio = { version = "1.52.3", features = ["rt-multi-thread", "sync", "time"] }
+tokio = { version = "1.53.1", features = ["rt-multi-thread", "sync", "time"] }
regex-cursor = "0.1.5"
papaya = "0.2.4"
markdown = "1.0.0"
-itertools = "0.14.0"
+itertools = "0.15.0"
pin-project = "1.1.13"
replace_with = "0.1.8"
nucleo = "0.5.0"
-tokio-util = { version = "0.7.18", features = ["rt"] }
+tokio-util = { version = "0.7.19", features = ["rt"] }
scopeguard = "1.2.0"
-arc-swap = "1.9.1"
-atools = "0.1.12"
+arc-swap = "1.9.2"
+atools = "0.1.13"
swizzle = "0.1.0"
walkdir = "2.5.0"
-libc = "0.2.186"
-rustc-hash = "=2.1.1"
-git2 = "0.20.4"
+libc = "0.2.189"
+rustc-hash = "2.1.3"
+git2 = "0.21.0"
imara-diff = "0.2.0"
vecto = "0.1.1"
rangemap = { version = "1.7.1", features = ["const_fn", "nightly", "serde1"] }
itern = "0.1.1"
smol_str = "0.3.6"
-futures = "0.3.32"
-rootcause = { version = "0.12.1", features = ["compat-anyhow1"] }
+futures = "0.3.33"
+rootcause = { version = "0.13.0", features = ["compat-anyhow1"] }
ttools = { git = "https://git.bendn.org/ttools" }
# ttools = { path = "../ttools/" }
ftools = { git = "https://git.bendn.org/ftools" }
json_value_merge = "2.0.1"
annotate-snippets = "0.12.16"
-toml = "1.1.2"
+toml = "1.1.4"
bendncode = { git = "https://git.bendn.org/bendncode" }
rfd = "0.17.2"
+lsp-types = { version = "0.11.0", package = "gen-lsp-types", features = ["url"] }
+rayon = "1.12.0"
+tracing-subscriber = "0.3.23"
+crossbeam-channel = "0.5.16"
[target.'cfg(unix)'.dependencies]
kitty-rc = { version = "0.4.2", git = "https://github.com/bend-n/kitty-rc-rs" }
@@ -109,4 +114,6 @@ incremental = false
[patch.crates-io]
smol_str = { git = "https://git.bendn.org/rust-analyzer" }
ttools = { git = "https://git.bendn.org/ttools" }
+# lsp-server = { path = "../rust-analyzer/lib/lsp-server" }
# winit = { git = "https://github.com/rust-windowing/winit" }
+
diff --git a/src/act.rs b/src/act.rs
index d35cd3a..0428ddb 100644
--- a/src/act.rs
+++ b/src/act.rs
@@ -1,7 +1,8 @@
use dsb::Cell;
use dsb::cell::Style;
use itertools::Itertools;
-use lsp_types::{CodeAction, CodeActionKind};
+use lsp_types::CodeActionKind;
+use rust_analyzer::lsp::ext::CodeAction;
#[derive(Debug, Clone)]
pub enum N<T> {
@@ -165,14 +166,15 @@ fn write(x: &CodeAction, c: usize, selected: bool, to: &mut Vec<Cell>) {
vec![Cell { style: Style::new(FG, bg), ..Default::default() }; c];
let t = match &x.kind {
- Some(x) if x == &CodeActionKind::QUICKFIX => '󰁨',
- Some(x)
- if x == &CodeActionKind::REFACTOR
- || x == &CodeActionKind::REFACTOR_EXTRACT
- || x == &CodeActionKind::REFACTOR_INLINE
- || x == &CodeActionKind::REFACTOR_REWRITE =>
- '󰷥',
- Some(x) if x == &CodeActionKind::SOURCE => '󱇧',
+ Some(CodeActionKind::QuickFix) => '󰁨',
+ Some(
+ CodeActionKind::Refactor
+ | CodeActionKind::RefactorExtract
+ | CodeActionKind::RefactorInline
+ | CodeActionKind::RefactorRewrite
+ | CodeActionKind::RefactorMove,
+ ) => '󰷥',
+ Some(CodeActionKind::Source) => '󱇧',
_ => '', /* 󱢇☭ */
};
into[0].style.fg = col!("#E5C07B");
diff --git a/src/bar.rs b/src/bar.rs
index 3de6e56..bc80da0 100644
--- a/src/bar.rs
+++ b/src/bar.rs
@@ -3,9 +3,9 @@ use std::sync::Arc;
use dsb::Cell;
use dsb::cell::Style;
-use lsp_types::WorkDoneProgress;
use crate::killring::KillRM;
+use crate::lsp::communication::WorkDoneProgress;
use crate::lsp::{Client, Rq};
use crate::rnd::simplify_path;
use crate::sym::Symbols;
diff --git a/src/commands.rs b/src/commands.rs
index 014a3f8..b020c22 100644
--- a/src/commands.rs
+++ b/src/commands.rs
@@ -312,7 +312,7 @@ impl Editor {
.text
.to_l_position(*self.text.cursor.first())
.unwrap();
- let mut x = l.request_immediate::<rust_analyzer::lsp::ext::MoveItem>(&MoveItemParams {
+ let mut x = l.request_immediate::<rust_analyzer::lsp::ext::MoveItemRequest>(&MoveItemParams {
direction: if let Cmd::RAMoveIU = z { MoveItemDirection::Up } else { MoveItemDirection::Down },
text_document: o.tid(),
range: Range { start : r, end : r},
@@ -324,11 +324,11 @@ impl Editor {
}
}
Cmd::RARestart => {
- _ = l.request::<ReloadWorkspace>(&())?.0;
+ _ = l.request::<ReloadWorkspaceRequest>(&())?.0;
}
Cmd::RAParent => {
- let Some(GotoDefinitionResponse::Link([ref x])) =
- l.request_immediate::<ParentModule>(
+ let Some(DefinitionResponse::DefinitionLinkList([ref x])) =
+ l.request_immediate::<ParentModuleRequest>(
&TextDocumentPositionParams {
text_document: o.tid(),
position: self
@@ -344,8 +344,8 @@ impl Editor {
self.go(x, w, lsp_mn)?;
}
Cmd::RAJoinLines => {
- let teds =
- l.request_immediate::<JoinLines>(&JoinLinesParams {
+ let teds = l.request_immediate::<JoinLinesRequest>(
+ &JoinLinesParams {
ranges: self
.text
.cursor
@@ -357,13 +357,14 @@ impl Editor {
})
.collect(),
text_document: o.tid(),
- })?;
+ },
+ )?;
self.text
.apply_tedits(&mut { teds })
.map_err(|_| report!("couldnt apply edits"))?;
}
Cmd::RADocs => {
- let u = l.request_immediate::<ExternalDocs>(
+ let u = l.request_immediate::<ExternalDocsRequest>(
&TextDocumentPositionParams {
position: self
.text
@@ -405,12 +406,13 @@ impl Editor {
.unwrap();
}
Cmd::RARebuildProcMacros => {
- _ = l.request::<RebuildProcMacros>(&())?;
+ _ = l.request::<RebuildProcMacrosRequest>(&())?;
}
- Cmd::RACancelFlycheck => l.notify::<CancelFlycheck>(&())?,
+ Cmd::RACancelFlycheck =>
+ l.notify::<CancelFlycheckNotification>(&())?,
Cmd::RAOpenCargoToml => {
- let Some(GotoDefinitionResponse::Scalar(x)) =
- &l.request_immediate::<OpenCargoToml>(
+ let Some(DefinitionResponse::Definition(x)) =
+ &l.request_immediate::<OpenCargoTomlRequest>(
&OpenCargoTomlParams { text_document: o.tid() },
)?
else {
diff --git a/src/complete.rs b/src/complete.rs
index fc652c3..3ab13d3 100644
--- a/src/complete.rs
+++ b/src/complete.rs
@@ -63,8 +63,8 @@ fn filter_c<'a>(
) -> impl Iterator<Item = &'a CompletionItem> {
let x = &completion.r;
let y = match x {
- CompletionResponse::Array(x) => x,
- CompletionResponse::List(x) => &x.items,
+ CompletionResponse::CompletionItemList(x) => x,
+ CompletionResponse::CompletionList(x) => &x.items,
};
filter(y.iter(), f)
}
@@ -82,7 +82,9 @@ pub fn s(completion: &Complete, c: usize, f: &str) -> Vec<Cell> {
});
out
-}
+}pub const fn i<T:Copy>(x: T) -> usize {
+ (unsafe { *<*const _>::from(&x).cast::<u32>() }) as usize
+ }
#[implicit_fn::implicit_fn]
fn r(
x: &CompletionItem,
@@ -96,34 +98,36 @@ fn r(
let ds = Style::new(FG, bg);
let d: Cell = Cell { letter: None, style: ds };
let mut b = vec![d; c];
+
const MAP: [([u8; 3], [u8; 3], &str); 26] = {
(
amap::amap! {
- const { CompletionItemKind::TEXT.0 as usize } => ("#9a9b9a", " "),
- const { CompletionItemKind::METHOD.0 as usize } | const { CompletionItemKind::FUNCTION.0 as usize } => ("#FFD173", "λ "),
- const { CompletionItemKind::CONSTRUCTOR.0 as usize } => ("#FFAD66", "->"),
- const { CompletionItemKind::FIELD.0 as usize } => ("#E06C75", "x."),
- const { CompletionItemKind::VARIABLE.0 as usize } => ("#E06C75", "x "),
- const { CompletionItemKind::MODULE.0 as usize } => ("#D5FF80", "::"),
- const { CompletionItemKind::PROPERTY.0 as usize } => ("#e6e1cf", "x."),
- const { CompletionItemKind::VALUE.0 as usize } => ("#DFBFFF", "4 "),
- const { CompletionItemKind::ENUM.0 as usize } => ("#73b9ff", "󰓹u"),
- const { CompletionItemKind::ENUM_MEMBER.0 as usize } => ("#73b9ff", "󰓹:"),
- const { CompletionItemKind::SNIPPET.0 as usize } => ("#9a9b9a", "! "),
- const { CompletionItemKind::INTERFACE.0 as usize } => ("#E5C07B", "t "),
- const { CompletionItemKind::REFERENCE.0 as usize } => ("#9a9b9a", "& "),
- const { CompletionItemKind::CONSTANT.0 as usize } => ("#DFBFFF", "N "),
- const { CompletionItemKind::STRUCT.0 as usize } => ("#73D0FF", "X{"),
- const { CompletionItemKind::OPERATOR.0 as usize } => ("#F29E74", "+ "),
- const { CompletionItemKind::TYPE_PARAMETER.0 as usize } => ("#9a9b9a", "T "),
- const { CompletionItemKind::KEYWORD.0 as usize } => ("#FFAD66", "as"),
+ const { i(CompletionItemKind::Text) } => ("#9a9b9a", " "),
+ const { i(CompletionItemKind::Method) } | const { i(CompletionItemKind::Function) } => ("#FFD173", "λ "),
+ const { i(CompletionItemKind::Constructor) } => ("#FFAD66", "->"),
+ const { i(CompletionItemKind::Field) } => ("#E06C75", "x."),
+ const { i(CompletionItemKind::Variable) } => ("#E06C75", "x "),
+ const { i(CompletionItemKind::Module) } => ("#D5FF80", "::"),
+ const { i(CompletionItemKind::Property) } => ("#e6e1cf", "x."),
+ const { i(CompletionItemKind::Value) } => ("#DFBFFF", "4 "),
+ const { i(CompletionItemKind::Enum) } => ("#73b9ff", "󰓹u"),
+ const { i(CompletionItemKind::EnumMember) } => ("#73b9ff", "󰓹:"),
+ const { i(CompletionItemKind::Snippet) } => ("#9a9b9a", "! "),
+ const { i(CompletionItemKind::Interface) } => ("#E5C07B", "t "),
+ const { i(CompletionItemKind::Reference) } => ("#9a9b9a", "& "),
+ const { i(CompletionItemKind::Constant) } => ("#DFBFFF", "N "),
+ const { i(CompletionItemKind::Struct) } => ("#73D0FF", "X{"),
+ const { i(CompletionItemKind::Operator) } => ("#F29E74", "+ "),
+ const { i(CompletionItemKind::TypeParameter) } => ("#9a9b9a", "T "),
+ const { i(CompletionItemKind::Keyword) } => ("#FFAD66", "as"),
+
_ => ("#9a9b9a", " ")
}).map(const
|(x, y)| (set_a(color_(x), 0.5), color_(x), y),
)
};
let (bgt, col, ty) =
- MAP[x.kind.unwrap_or(CompletionItemKind(25)).0 as usize];
+ MAP[i(x.kind.unwrap_or(CompletionItemKind::Text))];
b.iter_mut().zip(ty.chars()).for_each(|(x, c)| {
*x = (Style::new(col, bgt) | Style::BOLD).basic(c)
});
@@ -234,7 +238,7 @@ impl Editor {
let sel = x.sel(&crate::filter(&self.text));
let sel = lsp.resolve(sel.clone()).unwrap();
let CompletionItem {
- text_edit: Some(CompletionTextEdit::Edit(ed)),
+ text_edit: Some(CompletionItemTextEdit::TextEdit(ed)),
additional_text_edits,
insert_text_format,
..
@@ -243,7 +247,7 @@ impl Editor {
return;
};
match insert_text_format {
- Some(InsertTextFormat::SNIPPET) => {
+ Some(InsertTextFormat::Snippet) => {
self.text.apply_snippet(&ed).unwrap();
}
_ => {
diff --git a/src/edi/input_handlers/click.rs b/src/edi/input_handlers/click.rs
index 2fc4db3..82ddd2b 100644
--- a/src/edi/input_handlers/click.rs
+++ b/src/edi/input_handlers/click.rs
@@ -60,21 +60,26 @@ impl Editor {
}
Do::GoToDefinition(tdpp) => {
dbg!(&tdpp);
- if let Some(x) = self.requests.def.result.clone().or_else(|| {
- tdpp.zip(lsp!(self)).and_then(|(tdpp, lsp)| {
- lsp.request_immediate::<lsp_request!("textDocument/definition")>(
- &GotoDefinitionParams {
+ if let Some(x) = self.requests.def.result.clone()
+ && let Err(e) = self.go(&x, w.clone(), lsp_mn)
+ {
+ log::error!("gtd: {e}");
+ } else if let Some(x) = {
+ tdpp.zip(lsp!(self)).and_then(|(tdpp, lsp)| {
+ lsp.request_immediate::< lsp_request!("textDocument/definition")>(
+ &DefinitionParams {
text_document_position_params: tdpp,
work_done_progress_params: default(),
partial_result_params: default(),
},
).ok()
}).flatten().and_then(|x| match &x {
- GotoDefinitionResponse::Link([x, ..]) => Some(x.clone()),
+ DefinitionResponse::Definition(Definition::Location(x)) => Some(x.clone()),
+ DefinitionResponse::Definition(Definition::LocationList([x])) => Some(x.clone()),
+ // DefinitionResponse::DefinitionLinkList([x, ..]) => Some(x.clone()),
_ => None,
})
- })
- && let Err(e) = self.go(&x, w.clone(),lsp_mn)
+ } && let Err(e) = self.go(&x, w.clone(), lsp_mn)
{
log::error!("gtd: {e}");
}
diff --git a/src/edi/input_handlers/cursor.rs b/src/edi/input_handlers/cursor.rs
index 953d320..8887045 100644
--- a/src/edi/input_handlers/cursor.rs
+++ b/src/edi/input_handlers/cursor.rs
@@ -3,11 +3,11 @@ use std::sync::Arc;
use Default::default;
use implicit_fn::implicit_fn;
-use lsp_types::request::*;
use lsp_types::*;
use rust_fsm::StateMachine;
use tokio::task::spawn_blocking;
use tokio_util::task::AbortOnDropHandle as DropH;
+use url::Url;
use winit::window::Window;
enum Set<T> {
To(T),
@@ -17,6 +17,7 @@ enum Set<T> {
use crate::edi::*;
use crate::hov::{DiagnosticHovr, Hoverable, Hovring};
use crate::lsp::BehaviourAfter;
+use crate::lsp::communication::send;
use crate::rnd::CellBuffer;
impl Editor {
#[implicit_fn]
@@ -221,12 +222,15 @@ impl Editor {
.is_none_or(|&(_, x)| x != cursor_position)
{
let handle = lsp.runtime.spawn(
- lsp.request::<lsp_request!("textDocument/definition")>(
- &GotoDefinitionParams {
- text_document_position_params: tdpp.clone(),
- work_done_progress_params: default(),
- partial_result_params: default(),
- },
+ send!(
+ lsp.request,
+ "textDocument/definition",
+ _ {
+ text_document_position_params: tdpp
+ .clone(),
+ work_done_progress_params: default(),
+ partial_result_params: default(),
+ },
)
.unwrap()
.0,
@@ -279,29 +283,30 @@ impl Editor {
return Ok(None::<Hovr>);
};
let (width, cells) = spawn_blocking(move || {
+ #[allow(deprecated)]
let mut x = match &x.contents {
- lsp_types::HoverContents::Scalar(
- marked_string,
- ) => match marked_string {
- MarkedString::LanguageString(x) =>
- Cow::Borrowed(&*x.value),
- MarkedString::String(x) => Cow::Borrowed(&**x),
- },
- lsp_types::HoverContents::Array(
- marked_strings,
- ) => Cow::Owned(
- marked_strings
- .iter()
- .map(|x| match x {
- MarkedString::LanguageString(x) =>
- &*x.value,
- MarkedString::String(x) => &*x,
- })
- .collect::<String>(),
- ),
- lsp_types::HoverContents::Markup(
- markup_content,
- ) => Cow::Borrowed(&*markup_content.value),
+ Contents::MarkedString(marked_string) =>
+ match marked_string {
+ MarkedString::MarkedStringWithLanguage(
+ x,
+ ) => Cow::Borrowed(&*x.value),
+ MarkedString::String(x) =>
+ Cow::Borrowed(&**x),
+ },
+ Contents::MarkedStringList(marked_strings) =>
+ Cow::Owned(
+ marked_strings
+ .iter()
+ .map(|x| match x {
+ MarkedString::MarkedStringWithLanguage(
+ x,
+ ) => &*x.value,
+ MarkedString::String(x) => &*x,
+ })
+ .collect::<String>(),
+ ),
+ Contents::MarkupContent(markup_content) =>
+ Cow::Borrowed(&*markup_content.value),
};
if l.is_some_and(|l| {
matches!(
diff --git a/src/edi/input_handlers/keyboard.rs b/src/edi/input_handlers/keyboard.rs
index 7dadc9b..08376aa 100644
--- a/src/edi/input_handlers/keyboard.rs
+++ b/src/edi/input_handlers/keyboard.rs
@@ -5,11 +5,9 @@ use std::sync::Arc;
use Default::default;
use lsp_server::ResponseError;
-use lsp_types::request::*;
use lsp_types::*;
use regex::Regex;
use ropey::Rope;
-use rust_analyzer::lsp::ext::OnTypeFormatting;
use rust_fsm::StateMachine;
use tokio_util::task::AbortOnDropHandle as DropH;
use ttools::{IteratorOfTuples, IteratorOfTuplesWithF, hrf};
@@ -275,10 +273,10 @@ impl Editor {
self.hist.lc = self.text.cursor.clone();
self.hist.test_push(&mut self.text);
let act = lsp
- .request_immediate::<CodeActionResolveRequest>(&act)
+ .request_immediate::<rust_analyzer::lsp::ext::CodeActionResolveRequest>(&act)
.unwrap();
if let Some(x) = act.edit
- && let Err(e) = self.apply_wsedit(x)
+ && let Err(e) = self.apply_swsedit(x)
{
log::error!("{e}");
}
@@ -665,23 +663,22 @@ impl Editor {
|| t.iter().any(|y| y == x))
&& self.text.cursor.inner.len() == 1
&& change!(just self).is_some()
- && let Ok(Ok(Some(mut x))) = l.request_by::<OnTypeFormatting>(
- &DocumentOnTypeFormattingParams {
- text_document_position: TextDocumentPositionParams {
+ && let Ok(Ok(Some(mut x))) = l
+ .request_by::<rust_analyzer::lsp::ext::DocumentOnTypeFormattingRequest>(
+ &DocumentOnTypeFormattingParams {
text_document: p.tid(),
position: self
.text
.to_l_position(*self.text.cursor.first())
.unwrap(),
+ ch: x.into(),
+ options: FormattingOptions {
+ tab_size: 4,
+ ..default()
+ },
},
- ch: x.into(),
- options: FormattingOptions {
- tab_size: 4,
- ..default()
- },
- },
- acceptable_duration(),
- )
+ acceptable_duration(),
+ )
{
x.sort_tedits();
for x in x {
@@ -814,15 +811,16 @@ impl Editor {
let x = lsp
.request_immediate::<lsp_request!("textDocument/rename")>(
&RenameParams {
- text_document_position: TextDocumentPositionParams {
- text_document: f.tid(),
- position: self
- .text
- .to_l_position(
- self.text.cursor.first().position,
- )
- .unwrap(),
- },
+ text_document_position_params:
+ TextDocumentPositionParams {
+ text_document: f.tid(),
+ position: self
+ .text
+ .to_l_position(
+ self.text.cursor.first().position,
+ )
+ .unwrap(),
+ },
new_name,
work_done_progress_params: default(),
},
@@ -856,7 +854,7 @@ impl Editor {
return;
}
let r = lsp
- .request::<lsp_request!("textDocument/codeAction")>(
+ .request::<rust_analyzer::lsp::ext::CodeActionRequest>(
&CodeActionParams {
text_document: f.tid(),
range: self
@@ -867,7 +865,7 @@ impl Editor {
)
.unwrap(),
context: CodeActionContext {
- trigger_kind: Some(CodeActionTriggerKind::INVOKED),
+ trigger_kind: Some(CodeActionTriggerKind::Invoked),
// diagnostics: if let Some((lsp, p)) = lsp!() && let uri = Url::from_file_path(p).unwrap() && let Some(diag) = lsp.requests.diagnostics.get(&uri, &lsp.requests.diagnostics.guard()) { dbg!(diag.iter().filter(|x| {
// self.text.l_range(x.range).unwrap().contains(&self.text.cursor)
// }).cloned().collect()) } else { vec![] },
diff --git a/src/edi/lsp_impl.rs b/src/edi/lsp_impl.rs
index 269ddb0..6026a3d 100644
--- a/src/edi/lsp_impl.rs
+++ b/src/edi/lsp_impl.rs
@@ -2,8 +2,8 @@ use std::iter::repeat;
use Default::default;
use lsp_server::Request as LRq;
-use lsp_types::request::*;
use lsp_types::*;
+use rust_analyzer::lsp::ext::CodeAction;
use serde::{Deserialize, Serialize};
use ttools::{Tupl, With};
@@ -40,7 +40,7 @@ pub struct Requests {
Box<[SemanticToken]>,
Box<[SemanticToken]>,
(),
- RequestError<SemanticTokensFullRequest>,
+ RequestError<lsp_request!("textDocument/semanticTokens/full")>,
>,
pub diag: Rq<
String,
@@ -55,11 +55,11 @@ pub struct Requests {
(),
RequestError<lsp_request!("textDocument/inlayHint")>,
>,
- pub def: Rq<
+ pub def: crate::RqS<
LocationLink,
- Option<GotoDefinitionResponse>,
+ lsp_request!("textDocument/definition"),
(usize, usize),
- RequestError<lsp_request!("textDocument/definition")>,
+ // RequestError<lsp_request!("textDocument/definition")>,
>,
#[serde(skip)]
pub document_symbols: Rq<
@@ -71,6 +71,89 @@ pub struct Requests {
#[serde(skip)]
pub git_diff: Rq<imara_diff::Diff, imara_diff::Diff, (), ()>,
}
+use serde::ser::SerializeSeq;
+
+fn untokenr<'de, D>(
+ deserializer: D,
+) -> Result<Vec<SemanticToken>, D::Error>
+where
+ D: serde::Deserializer<'de>,
+{
+ let data = Vec::<u32>::deserialize(deserializer)?;
+ let chunks = data.chunks_exact(5);
+
+ if !chunks.remainder().is_empty() {
+ return Result::Err(serde::de::Error::custom(
+ "Length is not divisible by 5",
+ ));
+ }
+
+ Result::Ok(
+ chunks
+ .map(|chunk| SemanticToken {
+ delta_line: chunk[0],
+ delta_start: chunk[1],
+ length: chunk[2],
+ token_type: chunk[3],
+ token_modifiers_bitset: chunk[4],
+ })
+ .collect(),
+ )
+}
+
+fn tokenr<S>(
+ tokens: &[SemanticToken],
+ serializer: S,
+) -> Result<S::Ok, S::Error>
+where
+ S: serde::Serializer,
+{
+ let mut seq = serializer.serialize_seq(Some(tokens.len() * 5))?;
+ for token in tokens.iter() {
+ seq.serialize_element(&token.delta_line)?;
+ seq.serialize_element(&token.delta_start)?;
+ seq.serialize_element(&token.length)?;
+ seq.serialize_element(&token.token_type)?;
+ seq.serialize_element(&token.token_modifiers_bitset)?;
+ }
+ seq.end()
+}
+
+fn deserialize_tokens_opt<'de, D>(
+ deserializer: D,
+) -> Result<Option<Vec<SemanticToken>>, D::Error>
+where
+ D: serde::Deserializer<'de>,
+{
+ #[derive(Deserialize)]
+ #[serde(transparent)]
+ struct Wrapper {
+ #[serde(deserialize_with = "untokenr")]
+ tokens: Vec<SemanticToken>,
+ }
+
+ Ok(Option::<Wrapper>::deserialize(deserializer)?
+ .map(|wrapper| wrapper.tokens))
+}
+
+fn serialize_tokens_opt<S>(
+ data: Option<&[SemanticToken]>,
+ serializer: S,
+) -> Result<S::Ok, S::Error>
+where
+ S: serde::Serializer,
+{
+ #[derive(Serialize)]
+ #[serde(transparent)]
+ struct Wrapper<'a> {
+ #[serde(serialize_with = "tokenr")]
+ tokens: &'a [SemanticToken],
+ }
+
+ let opt = data.as_ref().map(|t| Wrapper { tokens: t });
+
+ opt.serialize(serializer)
+}
pub fn deserialize_tokens<'de, D: serde::Deserializer<'de>>(
ser: D,
) -> Result<
@@ -78,26 +161,44 @@ pub fn deserialize_tokens<'de, D: serde::Deserializer<'de>>(
Box<[SemanticToken]>,
Box<[SemanticToken]>,
(),
- RequestError<SemanticTokensFullRequest>,
+ RequestError<lsp_request!("textDocument/semanticTokens/full")>,
>,
D::Error,
> {
- SemanticToken::deserialize_tokens_opt(ser)
- .map(|x| Rq { result: x.map(Into::into), request: None })
+ {
+ #[derive(Deserialize)]
+ #[serde(transparent)]
+ struct Wrapper {
+ #[serde(deserialize_with = "untokenr")]
+ tokens: Vec<SemanticToken>,
+ }
+
+ Ok(Option::<Wrapper>::deserialize(ser)?
+ .map(|wrapper| wrapper.tokens))
+ }
+ .map(|x| Rq { result: x.map(Into::into), request: None })
}
pub fn serialize_tokens<S: serde::Serializer>(
s: &Rq<
Box<[SemanticToken]>,
Box<[SemanticToken]>,
(),
- RequestError<SemanticTokensFullRequest>,
+ RequestError<lsp_request!("textDocument/semanticTokens/full")>,
>,
ser: S,
) -> Result<S::Ok, S::Error> {
- SemanticToken::serialize_tokens_opt(
- &s.result.clone().map(|x| x.to_vec()),
- ser,
- )
+ {
+ let data: &Option<Vec<SemanticToken>> =
+ &s.result.clone().map(|x| x.to_vec());
+ #[derive(Serialize)]
+ #[serde(transparent)]
+ struct Wrapper {
+ #[serde(serialize_with = "tokenr")]
+ tokens: Vec<SemanticToken>,
+ }
+ let opt = data.as_ref().map(|t| Wrapper { tokens: t.to_vec() });
+ opt.serialize(ser)
+ }
}
impl crate::edi::Editor {
pub fn poll(&mut self) {
@@ -149,14 +250,7 @@ impl crate::edi::Editor {
}
State::CodeAction(x) => {
if x.poll(|x, _| {
- let lems: Vec<CodeAction> = x
- .ok()??
- .into_iter()
- .map(|x| match x {
- CodeActionOrCommand::CodeAction(x) => x,
- _ => panic!("alas we dont like these"),
- })
- .collect();
+ let lems = x.ok()??;
if lems.is_empty() {
self.bar.last_action =
"no code actions available".into();
@@ -218,18 +312,13 @@ impl crate::edi::Editor {
x.ok().map(|x| {
x.and_then(|x| try {
z.data.0 = match x {
- GotoDefinitionResponse::Scalar(
- location,
+ ImplementationResponse::Definition(
+ Definition::Location(location),
) => vec![(GoTo::from(
location,
),None)],
- GotoDefinitionResponse::Array(
- locations,
- ) => locations
- .into_iter()
- .map(GoTo::from).zip(repeat(None))
- .collect(),
- GotoDefinitionResponse::Link(
+
+ ImplementationResponse::DefinitionLinkList(
location_links,
) => location_links
.into_iter()
@@ -242,6 +331,7 @@ impl crate::edi::Editor {
)
}).zip(repeat(None))
.collect(),
+ ImplementationResponse::Definition(Definition::LocationList(x)) => {unimplemented!()},
};
});
})
@@ -281,7 +371,10 @@ impl crate::edi::Editor {
}
self.requests.def.poll(|x, _| {
x.ok().flatten().and_then(|x| match &x {
- GotoDefinitionResponse::Link([x, ..]) => Some(x.clone()),
+ // DefinitionResponse::Definition(x) => Some(x.clone()),
+ DefinitionResponse::DefinitionLinkList([x, ..]) =>
+ Some(x.clone()),
+ // DefinitionRequest::Definition([x, ..]) => Some(x.clone()),
_ => None,
})
});
@@ -303,8 +396,8 @@ impl crate::edi::Editor {
self.requests.git_diff.poll(|x, _| x.ok());
self.requests.document_symbols.poll(|x, _| {
x.ok().flatten().map(|x| match x {
- DocumentSymbolResponse::Flat(_) => None,
- DocumentSymbolResponse::Nested(x) => Some(x),
+ DocumentSymbolResponse::SymbolInformationList(_) => None,
+ DocumentSymbolResponse::DocumentSymbolList(x) => Some(x),
})
});
}
diff --git a/src/edi/lsp_mn.rs b/src/edi/lsp_mn.rs
index 25aa478..45cfd24 100644
--- a/src/edi/lsp_mn.rs
+++ b/src/edi/lsp_mn.rs
@@ -4,11 +4,11 @@ use std::path::PathBuf;
use std::process::Stdio;
use std::sync::Arc;
-use log::info;
-use lsp_server::{Connection, IoThreads};
+use lsp_server::Connection;
use lsp_types::*;
use tokio::sync::oneshot::Sender;
use tree_house::Language;
+use url::Url;
use winit::window::Window;
pub struct LSPM {
@@ -20,7 +20,12 @@ pub struct LoadedLSP {
pub iot: Option<IoThreads>,
pub comms: std::thread::JoinHandle<()>,
}
-
+impl LoadedLSP {
+ pub fn status(&self) {
+ assert!(!self.comms.is_finished());
+ }
+}
+mod stdio;
impl LSPM {
pub fn load(
&mut self,
@@ -45,6 +50,7 @@ impl LSPM {
Some((v.c.clone(), Some(w)))
}
}
+use crate::edi::lsp_mn::stdio::IoThreads;
use crate::lsp::Client;
pub fn load(
workspace: &PathBuf,
@@ -89,7 +95,7 @@ pub fn load(
})
.ok()?;
- let (x, iot) = Connection::stdio(
+ let (x, iot) = stdio::transport(
BufReader::new(c.stdout.take().unwrap()),
c.stdin.take().unwrap(),
);
diff --git a/src/edi/lsp_mn/stdio.rs b/src/edi/lsp_mn/stdio.rs
new file mode 100644
index 0000000..fa5a480
--- /dev/null
+++ b/src/edi/lsp_mn/stdio.rs
@@ -0,0 +1,75 @@
+use std::io::{self, Read, Stdin, Stdout, Write, stdin, stdout};
+use std::thread;
+
+use crossbeam_channel::{Receiver, Sender, bounded, unbounded};
+use log::trace;
+use lsp_server::{Connection, Message};
+/// Creates an LSP connection via stdio.
+pub fn transport(
+ mut read_from: impl Read + std::io::BufRead + Sync + Send + 'static,
+ mut write_to: impl Write + Sync + Send + 'static,
+) -> (Connection, IoThreads) {
+ let (writer_sender, writer_receiver) = unbounded::<Message>();
+ let writer = thread::Builder::new()
+ .name("send to lsp".to_owned())
+ .spawn(move || {
+ loop {
+ let it = writer_receiver.recv().unwrap();
+ trace!("sent message {it:#?}");
+ let result = it.write(&mut write_to).unwrap();
+ result
+ }
+ })
+ .unwrap();
+ let (reader_sender, reader_receiver) = bounded::<Message>(0);
+ let reader: thread::JoinHandle<Result<(), io::Error>> = thread::Builder::new()
+ .name("read from lsp".to_owned())
+ .spawn(move || {
+ while let Some(msg) = Message::read(&mut read_from)? {
+ let is_exit = matches!(&msg, Message::Notification(n) if n.method == "exit");
+ trace!("received message {msg:#?}");
+ if let Err(e) = reader_sender.send(msg) {
+ return Err(io::Error::other(e));
+ }
+
+ if is_exit {
+ break;
+ }
+ }
+ Ok(())
+ })
+ .unwrap();
+ let threads = IoThreads { reader, writer };
+ (
+ Connection { sender: writer_sender, receiver: reader_receiver },
+ threads,
+ )
+}
+
+// Creates an IoThreads
+pub(crate) fn make_io_threads(
+ reader: thread::JoinHandle<io::Result<()>>,
+ writer: thread::JoinHandle<io::Result<()>>,
+) -> IoThreads {
+ IoThreads { reader, writer }
+}
+
+pub struct IoThreads {
+ pub reader: thread::JoinHandle<io::Result<()>>,
+ pub writer: thread::JoinHandle<io::Result<()>>,
+}
+
+impl IoThreads {
+ pub fn join(self) -> io::Result<()> {
+ match self.reader.join() {
+ Ok(r) => r?,
+ Err(err) => std::panic::panic_any(err),
+ }
+ match self.writer.join() {
+ Ok(r) => r,
+ Err(err) => {
+ std::panic::panic_any(err);
+ }
+ }
+ }
+}
diff --git a/src/edi/ra.rs b/src/edi/ra.rs
index ef0c7c8..bed6931 100644
--- a/src/edi/ra.rs
+++ b/src/edi/ra.rs
@@ -31,7 +31,14 @@ pub fn ra(
println!("RA panic @ {}", info.location().unwrap());
}
}));
- rust_analyzer::bin::run_server(b).into_rootcause()
+
+ rayon::ThreadPoolBuilder::new()
+ .thread_name(|ix| format!("RayonWorker{}", ix))
+ .build_global()
+ .unwrap();
+
+ rust_analyzer::session::run_session(b, None, None)
+ .into_rootcause()
})
.unwrap();
(jh, a)
diff --git a/src/edi/st.rs b/src/edi/st.rs
index efc2081..40be312 100644
--- a/src/edi/st.rs
+++ b/src/edi/st.rs
@@ -1,10 +1,9 @@
#![allow(dead_code, unused, unexpected_cfgs)]
use Default::default;
use NamedKey::*;
-use lsp_types::request::HoverRequest;
use lsp_types::*;
use regex::Regex;
-use rust_analyzer::lsp::ext::Runnable;
+use rust_analyzer::lsp::ext::{CodeAction, Runnable};
use winit::event::MouseButton;
use winit::keyboard::{Key, NamedKey, SmolStr};
@@ -125,7 +124,7 @@ Runnables(_x) => {
K(Key::Named(Escape)) => Default,
},
#[cfg(target_family = "unix")]
-Runnables(RqS::<Run, rust_analyzer::lsp::ext::Runnables> => Rq { result: Some(mut x), request }) => {
+Runnables(RqS::<Run, rust_analyzer::lsp::ext::RunnablesRequest> => Rq { result: Some(mut x), request }) => {
#[cfg(target_family = "unix")]
K(Key::Named(Tab) if shift()) => Runnables({ x.next(); Rq { result: Some(x), request }}),
#[cfg(target_family = "unix")]
@@ -193,7 +192,7 @@ CodeAction(Rq { result : Some(_x), request }) => {
K(Key::Named(Enter | ArrowRight)) => _ [CASelectRight],
K(Key::Named(ArrowLeft)) => _ [CASelectLeft],
},
-CodeAction(RqS<act::CodeActions, lsp_request!("textDocument/codeAction")> => rq) => {
+CodeAction(RqS<act::CodeActions, rust_analyzer::lsp::ext::CodeActionRequest> => rq) => {
K(Key::Named(Escape)) => Default,
C(_) => _,
M(_) => _,
diff --git a/src/edi/wsedit.rs b/src/edi/wsedit.rs
index eb11a8b..55e0827 100644
--- a/src/edi/wsedit.rs
+++ b/src/edi/wsedit.rs
@@ -5,6 +5,10 @@ use lsp_types::*;
use rootcause::prelude::{IteratorExt, ResultExt};
use rootcause::report;
use ropey::Rope;
+use rust_analyzer::lsp::ext::{
+ SnippetDocumentChangeOperation, SnippetTextDocumentEdit,
+ SnippetWorkspaceEdit,
+};
use super::*;
use crate::error::WDebug;
@@ -52,23 +56,221 @@ impl Editor {
) -> rootcause::Result<()> {
self.apply_tds(
&text_document
+ .text_document_identifier
.uri
.to_file_path()
.map_err(|_| report!("sad"))?,
edits,
- TextArea::apply_snippet_tedit,
- TextArea::apply_snippet_tedit_raw,
+ |t, e| match e {
+ Edit::AnnotatedTextEdit(AnnotatedTextEdit {
+ text_edit,
+ ..
+ })
+ | Edit::TextEdit(text_edit) =>
+ Ok(drop(t.apply(text_edit)?)),
+ Edit::SnippetTextEdit(SnippetTextEdit {
+ range,
+ snippet,
+ annotation_id,
+ }) => {
+ let x2 = rust_analyzer::lsp::ext::SnippetTextEdit {
+ range: *range,
+ new_text: snippet.value.clone(),
+ insert_text_format: None,
+ annotation_id: annotation_id.clone(),
+ };
+ t.apply_snippet_tedit(&x2)
+ }
+ },
+ |e, t| match e {
+ Edit::AnnotatedTextEdit(AnnotatedTextEdit {
+ text_edit,
+ ..
+ })
+ | Edit::TextEdit(text_edit) =>
+ TextArea::apply_raw(text_edit, t),
+ Edit::SnippetTextEdit(SnippetTextEdit {
+ range,
+ snippet,
+ annotation_id,
+ }) => {
+ let x2 = rust_analyzer::lsp::ext::SnippetTextEdit {
+ range: *range,
+ new_text: snippet.value.clone(),
+ insert_text_format: None,
+ annotation_id: annotation_id.clone(),
+ };
+ TextArea::apply_snippet_tedit_raw(&x2, t)
+ }
+ },
+ // TextArea::apply_snippet_tedit,
+ // TextArea::apply_snippet_tedit_raw,
)
}
- fn apply_dco(
+ fn apply_sdc(
&mut self,
- op: DocumentChangeOperation,
+ op: SnippetDocumentChangeOperation,
) -> rootcause::Result<()> {
match op.clone() {
- DocumentChangeOperation::Edit(t) => self.apply_tde(t)?,
- DocumentChangeOperation::Op(ResourceOp::Create(
- CreateFile { uri, options, .. },
- )) => {
+ SnippetDocumentChangeOperation::Edit(
+ SnippetTextDocumentEdit { text_document, edits },
+ ) => self.apply_tds(
+ &text_document
+ .text_document_identifier
+ .uri
+ .to_file_path()
+ .map_err(|_| report!("sad"))?,
+ edits,
+ TextArea::apply_snippet_tedit,
+ TextArea::apply_snippet_tedit_raw,
+ ),
+ SnippetDocumentChangeOperation::Change(dc) =>
+ self.apply_dc(dc),
+ }
+ }
+ // pub fn apply_sdc(
+ // &mut self,
+ // x: SnippetDocumentChangeOperation,
+ // ) -> rootcause::Result<()> {
+ // match x {
+ // // self.apply_tde(x)
+ // DocumentChange::TextDocumentEdit(text_document_edit) =>
+ // self.apply_tde(text_document_edit)?,
+ // DocumentChange::CreateFile(CreateFile {
+ // uri,
+ // options,
+ // ..
+ // }) => {
+ // let f = uri
+ // .to_file_path()
+ // .map_err(|()| report!("not path"))?;
+ // let mut opts = OpenOptions::new();
+ // opts.write(true)
+ // // .create(true)
+ // .create(matches!(
+ // options,
+ // Some(CreateFileOptions {
+ // ignore_if_exists: Some(true) | None,
+ // ..
+ // }) | None
+ // ))
+ // .create_new(matches!(
+ // options,
+ // Some(CreateFileOptions {
+ // ignore_if_exists: Some(false),
+ // ..
+ // })
+ // ))
+ // .truncate(true);
+ // match opts.open(&f) {
+ // Ok(_f) => {}
+ // Err(e)
+ // if let Some(CreateFileOptions {
+ // overwrite: Some(true),
+ // ..
+ // }) = options
+ // && e.kind()
+ // == std::io::ErrorKind::AlreadyExists => {}
+ // Err(e) =>
+ // Err(e)
+ // .context_custom::<WDebug, _>(f)
+ // .context_custom::<WDebug, _>((opts, options))?,
+ // };
+ // }
+ // DocumentChange::RenameFile(RenameFile {
+ // old_uri,
+ // new_uri,
+ // options,
+ // annotation_id,
+ // }) => {
+ // let old_f = old_uri
+ // .to_file_path()
+ // .map_err(|()| report!("not path"))?;
+ // let new_f = new_uri
+ // .to_file_path()
+ // .map_err(|()| report!("not path"))?;
+
+ // // FIXME: overwrite
+ // if let Some(p) = new_f.parent()
+ // && !p.exists()
+ // {
+ // std::fs::create_dir_all(p)?;
+ // }
+ // match std::fs::rename(&old_f, &new_f) {
+ // Err(e)
+ // if e.kind()
+ // == std::io::ErrorKind::IsADirectory =>
+ // {
+ // do yeet report!("unhandled case: dir rename");
+ // }
+ // Err(e)
+ // if let Some(RenameFileOptions {
+ // ignore_if_exists: Some(true),
+ // ..
+ // }) = options
+ // && e.kind()
+ // == std::io::ErrorKind::AlreadyExists => {}
+ // Ok(_) => {}
+ // Err(e) => Err(e).context_with(|| {
+ // format!("renaming {old_f:?} to {new_f:?}")
+ // })?,
+ // }
+ // if let Some(f) = self.files.get_mut(&old_f)
+ // // .or(Some(self).filter(|x| x.origin == Some(old_f)))
+ // {
+ // f.bar.last_action =
+ // annotation_id.unwrap_or("renamed".into());
+ // f.origin = Some(new_f);
+ // f.mtime = Editor::modify(f.origin.as_deref());
+ // } else if self.origin == Some(old_f) {
+ // self.bar.last_action =
+ // annotation_id.unwrap_or("renamed".into());
+ // self.origin = Some(new_f);
+ // self.mtime = Editor::modify(self.origin.as_deref());
+ // }
+ // }
+ // DocumentChange::DeleteFile(DeleteFile {
+ // uri,
+ // options,
+ // ..
+ // }) => {
+ // let f = uri
+ // .to_file_path()
+ // .map_err(|()| report!("not path"))?;
+ // match std::fs::remove_file(&f) {
+ // Ok(()) => (),
+ // Err(e)
+ // if e.kind()
+ // == std::io::ErrorKind::IsADirectory =>
+ // {
+ // std::fs::remove_dir_all(f)?;
+ // }
+ // Err(e)
+ // if let Some(DeleteFileOptions {
+ // ignore_if_not_exists: Some(true),
+ // ..
+ // }) = options
+ // && e.kind()
+ // == std::io::ErrorKind::NotFound => {}
+ // Err(e) => do yeet e,
+ // }
+ // }
+ // };
+ // Ok(())
+ // }
+ pub fn apply_dc(
+ &mut self,
+ x: DocumentChange,
+ ) -> rootcause::Result<()> {
+ match x {
+ // self.apply_tde(x)
+ DocumentChange::TextDocumentEdit(text_document_edit) =>
+ self.apply_tde(text_document_edit)?,
+ DocumentChange::CreateFile(CreateFile {
+ uri,
+ options,
+ ..
+ }) => {
let f = uri
.to_file_path()
.map_err(|()| report!("not path"))?;
@@ -105,9 +307,12 @@ impl Editor {
.context_custom::<WDebug, _>((opts, options))?,
};
}
- DocumentChangeOperation::Op(ResourceOp::Rename(
- RenameFile { old_uri, new_uri, options, annotation_id },
- )) => {
+ DocumentChange::RenameFile(RenameFile {
+ old_uri,
+ new_uri,
+ options,
+ annotation_id,
+ }) => {
let old_f = old_uri
.to_file_path()
.map_err(|()| report!("not path"))?;
@@ -154,31 +359,11 @@ impl Editor {
self.mtime = Editor::modify(self.origin.as_deref());
}
}
- DocumentChangeOperation::Op(ResourceOp::Delete(
- DeleteFile {
- uri,
- options:
- Some(DeleteFileOptions {
- recursive: Some(true), // ??? seems redundant
- ignore_if_not_exists,
- ..
- }),
- },
- )) => {
- let f = uri
- .to_file_path()
- .map_err(|()| report!("not path"))?;
- match std::fs::remove_dir_all(f) {
- Ok(()) => (),
- Err(e)
- if e.kind() == std::io::ErrorKind::NotFound
- && ignore_if_not_exists == Some(true) => {}
- Err(e) => do yeet e,
- }
- }
- DocumentChangeOperation::Op(ResourceOp::Delete(
- DeleteFile { uri, options },
- )) => {
+ DocumentChange::DeleteFile(DeleteFile {
+ uri,
+ options,
+ ..
+ }) => {
let f = uri
.to_file_path()
.map_err(|()| report!("not path"))?;
@@ -200,8 +385,41 @@ impl Editor {
Err(e) => do yeet e,
}
}
+ };
+ Ok(())
+ }
+ pub fn apply_swsedit(
+ &mut self,
+ x: SnippetWorkspaceEdit,
+ ) -> rootcause::Result<()> {
+ match x {
+ SnippetWorkspaceEdit { document_changes: Some(x), .. } => x
+ .into_iter()
+ .map(|x| self.apply_sdc(x))
+ .collect_reports()
+ .context("couldnt apply one or more wsedits")?,
+ SnippetWorkspaceEdit { changes: Some(x), .. } => x
+ .into_iter()
+ .map(|(p, e)| {
+ self.apply_tds(
+ &p.to_file_path().map_err(|_| {
+ report!("evil path")
+ .context_custom::<WDebug, _>(e.clone())
+ })?,
+ e.clone(),
+ |x, y| x.apply(y).map(drop),
+ TextArea::apply_raw,
+ )
+ .context_custom::<WDebug, _>(e)
+ })
+ .collect_reports()
+ .context("couldnt apply one or more fs operations")?,
+ x =>
+ do yeet report!("strange workspace edit")
+ .context_custom::<WDebug, _>(x),
}
-
+ change!(self);
+ self.hist.record(&self.text);
Ok(())
}
#[must_use]
@@ -210,27 +428,11 @@ impl Editor {
x: WorkspaceEdit,
) -> rootcause::Result<()> {
match x {
- WorkspaceEdit {
- document_changes: Some(DocumentChanges::Edits(x)),
- ..
- } => x
+ WorkspaceEdit { document_changes: Some(x), .. } => x
.into_iter()
- .map(|x| self.apply_tde(x))
+ .map(|x| self.apply_dc(x))
.collect_reports()
.context("couldnt apply one or more wsedits")?,
- WorkspaceEdit {
- document_changes: Some(DocumentChanges::Operations(x)),
- ..
- } => x
- .clone()
- .into_iter()
- .map(|op: DocumentChangeOperation| {
- self.apply_dco(op.clone())
- .context_custom::<WDebug, _>(op)
- })
- .collect_reports()
- .context("couldnt apply one or more fs operations")
- .context_custom::<WDebug, _>(x)?,
WorkspaceEdit { changes: Some(x), .. } => x
.into_iter()
.map(|(p, e)| {
diff --git a/src/gotolist.rs b/src/gotolist.rs
index bed2abf..1999446 100644
--- a/src/gotolist.rs
+++ b/src/gotolist.rs
@@ -4,10 +4,10 @@ use std::path::Path;
use dsb::Cell;
use dsb::cell::Style;
-use lsp_types::request::GotoImplementation;
use lsp_types::{
- CallHierarchyIncomingCall, CallHierarchyOutgoingCall, Location,
- LocationLink, Range,
+ CallHierarchyIncomingCall, CallHierarchyOutgoingCall, Definition,
+ DefinitionResponse, ImplementationRequest, Location, LocationLink,
+ LocationUriOnly, Range, WorkspaceSymbolLocation,
};
use crate::FG;
@@ -20,8 +20,8 @@ pub type GoToList = GenericMenu<GTL>;
pub enum GTL {}
#[derive(Debug)]
pub enum O {
- Impl(RqS<(), GotoImplementation>),
- References(RqS<(), lsp_types::request::References>),
+ Impl(RqS<(), ImplementationRequest>),
+ References(RqS<(), lsp_types::ReferencesRequest>),
Incoming(
Rq<(), Vec<CallHierarchyIncomingCall>, (), rootcause::Report>,
),
@@ -118,6 +118,22 @@ impl<'a> Hash for GoTo<'a> {
self.path.hash(state);
}
}
+impl From<&LocationUriOnly> for GoTo<'static> {
+ fn from(LocationUriOnly { uri }: &LocationUriOnly) -> Self {
+ Self {
+ path: Cow::Owned(uri.to_file_path().unwrap()),
+ at: At::P(0),
+ }
+ }
+}
+impl<'a> From<&'a WorkspaceSymbolLocation> for GoTo<'static> {
+ fn from(value: &'a WorkspaceSymbolLocation) -> Self {
+ match value {
+ WorkspaceSymbolLocation::Location(location) => location.into(),
+ WorkspaceSymbolLocation::LocationUriOnly(x) => x.into(),
+ }
+ }
+}
impl From<Location> for GoTo<'static> {
fn from(Location { uri, range }: Location) -> Self {
Self {
@@ -135,6 +151,16 @@ impl From<&Location> for GoTo<'static> {
}
}
+impl From<&Definition> for GoTo<'static> {
+ fn from(x: &Definition) -> Self {
+ match x {
+ Definition::LocationList([x]) | Definition::Location(x) =>
+ x.into(),
+ _ => panic!(),
+ }
+ }
+}
+
impl From<&LocationLink> for GoTo<'static> {
fn from(
LocationLink { target_uri, target_range, .. }: &LocationLink,
diff --git a/src/hov.rs b/src/hov.rs
index 2c3f4b8..96725dc 100644
--- a/src/hov.rs
+++ b/src/hov.rs
@@ -496,12 +496,15 @@ pub fn to_snippet<'a: 'c, 'b: 'c, 'c>(
) -> annotate_snippets::Group<'c> {
use annotate_snippets::*;
match severity {
- Some(DiagnosticSeverity::WARNING) => Level::WARNING,
- Some(DiagnosticSeverity::INFORMATION) => Level::INFO,
- Some(DiagnosticSeverity::HINT) => Level::HELP,
+ Some(DiagnosticSeverity::Warning) => Level::WARNING,
+ Some(DiagnosticSeverity::Information) => Level::INFO,
+ Some(DiagnosticSeverity::Hint) => Level::HELP,
_ => Level::ERROR,
}
- .primary_title(message)
+ .primary_title(match message {
+ lsp_types::Message::String(x) => x,
+ lsp_types::Message::MarkupContent(_) => unimplemented!(),
+ })
.element(Snippet::source(t).annotation(
AnnotationKind::Primary.span(t.l_range(*range).unwrap()),
))
diff --git a/src/lsp.rs b/src/lsp.rs
index 5345fbd..4312cf8 100644
--- a/src/lsp.rs
+++ b/src/lsp.rs
@@ -12,14 +12,12 @@ use helix_core::syntax::config::{
use json_value_merge::Merge;
use log::info;
use lsp_server::Message;
-use lsp_types::notification::*;
-use lsp_types::request::*;
use lsp_types::*;
use rootcause::report;
use tokio::sync::oneshot;
use winit::window::Window;
mod client;
-mod communication;
+pub(crate) mod communication;
pub use client::*;
mod init_opts;
mod rq;
@@ -45,12 +43,14 @@ pub fn run(
let (not_tx, not_rx) = unbounded();
let (_req_tx, _req_rx) = unbounded();
let (window_tx, window_rx) = oneshot::channel::<Arc<dyn Window>>();
+ let mut rt = tokio::runtime::Builder::new_multi_thread();
+ #[cfg(target_family = "unix")]
+ rt.enable_io();
let mut c = Client {
tx: Tx(tx),
progress: Box::leak(Box::new(papaya::HashMap::new())),
- runtime: tokio::runtime::Builder::new_multi_thread()
+ runtime: rt
.enable_time()
- // .enable_io()
.worker_threads(3)
.thread_name("lsp runtime")
.build()?,
@@ -76,12 +76,16 @@ pub fn run(
}
};
info!("spawned {}", serde_json::to_string_pretty(&opts).unwrap());
- _ = c.request::<Initialize>(&opts)?;
+ _ = c.request::<InitializeRequest>(&opts)?;
let x = rx
.iter()
.find_map(|x| {
serde_json::from_value::<InitializeResult>(
- x.response()?.result?,
+ match x {
+ Message::Notification(_) | Message::Request(_) => None,
+ Message::Response(response) => Some(response),
+ }?
+ .result?,
)
.ok()
})
@@ -92,10 +96,8 @@ pub fn run(
// Some(PositionEncodingKind::UTF8)
// );
c.initialized = Some(x);
- c.notify::<lsp_types::notification::Initialized>(
- &InitializedParams {},
- )?;
- c.notify::<SetTrace>(&SetTraceParams {
+ c.notify::<lsp_types::InitializedNotification>(&InitializedParams {})?;
+ c.notify::<SetTraceNotification>(&SetTraceParams {
value: lsp_types::TraceValue::Verbose,
})?;
let progress = c.progress;
diff --git a/src/lsp/client.rs b/src/lsp/client.rs
index a0db994..ddbe7c4 100644
--- a/src/lsp/client.rs
+++ b/src/lsp/client.rs
@@ -14,15 +14,15 @@ use log::debug;
use lsp_server::{
Message, Notification as N, Request as LRq, Response as Re,
};
-use lsp_types::notification::*;
-use lsp_types::request::*;
use lsp_types::*;
use rootcause::option_ext::OptionExt;
use rust_analyzer::lsp::ext::*;
use tokio::sync::oneshot;
use ttools::*;
+use url::Url;
use crate::lsp::BehaviourAfter::{self, *};
+use crate::lsp::communication::{WorkDoneProgress, send};
use crate::lsp::{RequestError, Require, Requiring, Rq, RqSendError};
use crate::text::cursor::ceach;
use crate::text::{LOADER, RopeExt, SortTedits, TextArea};
@@ -55,7 +55,7 @@ pub struct Client {
ProgressToken,
Option<(WorkDoneProgress, WorkDoneProgressBegin)>,
>,
- pub diagnostics: &'static papaya::HashMap<Url, Vec<Diagnostic>>,
+ pub diagnostics: &'static papaya::HashMap<url::Url, Vec<Diagnostic>>,
#[allow(dead_code)]
// TODO: handle notifications from the server
pub not_rx: Receiver<N>,
@@ -70,7 +70,7 @@ pub struct Client {
impl Drop for Client {
fn drop(&mut self) {
- _ = self.notify::<Exit>(&());
+ _ = self.notify::<ExitNotification>(&());
println!(
"dropped lsp({}) @ {}",
self.lsp_data.1.name, self.workspace.uri
@@ -90,22 +90,25 @@ impl Client {
l: helix_core::Language,
) -> Result<(), SendError<Message>> {
let l = LOADER.language(l).config();
- self.notify::<DidOpenTextDocument>(&DidOpenTextDocumentParams {
- text_document: TextDocumentItem {
- uri: url::Url::from_file_path(f).unwrap(),
- language_id: l
- .language_server_language_id
- .clone()
- .unwrap_or(l.language_id.clone()),
- version: 0,
- text,
+ self.notify::<DidOpenTextDocumentNotification>(
+ &DidOpenTextDocumentParams {
+ text_document: TextDocumentItem {
+ uri: url::Url::from_file_path(f).unwrap(),
+ language_id: l
+ .language_server_language_id
+ .clone()
+ .unwrap_or(l.language_id.clone())
+ .into(),
+ version: 0,
+ text,
+ },
},
- })
+ )
}
pub fn close(&self, f: &Path) -> Result<(), SendError<Message>> {
- self.notify::<DidCloseTextDocument>(&DidCloseTextDocumentParams {
- text_document: f.tid(),
- })
+ self.notify::<DidCloseTextDocumentNotification>(
+ &DidCloseTextDocumentParams { text_document: f.tid() },
+ )
}
pub fn edit(
&self,
@@ -113,17 +116,16 @@ impl Client {
text: String,
) -> Result<(), SendError<Message>> {
static V: AtomicI32 = AtomicI32::new(0);
- self.notify::<lsp_types::notification::DidChangeTextDocument>(
+ self.notify::<lsp_types::DidChangeTextDocumentNotification>(
&DidChangeTextDocumentParams {
text_document: VersionedTextDocumentIdentifier {
- uri: url::Url::from_file_path(f).unwrap(),
+ text_document_identifier: f.tid(),
version: V.fetch_add(1, Relaxed),
},
- content_changes: vec![TextDocumentContentChangeEvent {
- range: None,
- range_length: None,
- text,
- }],
+ content_changes: vec![
+ (TextDocumentContentChangeWholeDocument { text })
+ .into(),
+ ],
},
)
}
@@ -131,8 +133,13 @@ impl Client {
pub fn resolve(
&self,
x: CompletionItem,
- ) -> Result<CompletionItem, RequestError<ResolveCompletionItem>> {
- self.request_immediate::<ResolveCompletionItem>(&x)
+ ) -> Result<
+ CompletionItem,
+ RequestError<lsp_request!("completionItem/resolve")>,
+ > {
+ self.request_immediate::<lsp_request!("completionItem/resolve")>(
+ &x,
+ )
}
pub fn request_complete<'me>(
@@ -145,18 +152,15 @@ impl Client {
impl Future<
Output = Result<
Option<CompletionResponse>,
- RequestError<Completion>,
+ RequestError<lsp_request!("textDocument/completion")>,
>,
> + use<>,
> {
self.caps().completion_provider.require()?;
let (rx, _) = self
- .request_::<Completion, { Redraw }>(&CompletionParams {
- text_document_position: TextDocumentPositionParams {
- text_document: f.tid(),
- position: Position { line: y as _, character: x as _ },
- },
+ .request_::<lsp_request!("textDocument/completion"), { Redraw }>(&CompletionParams {
+ text_document_position_params: TextDocumentPositionParams::new(f.tid(), Position { line: y as _, character: x as _ }),
work_done_progress_params: default(),
partial_result_params: default(),
context: Some(c),
@@ -268,7 +272,7 @@ impl Client {
.diagnostic_provider
.as_ref()?
{
- DiagnosticServerCapabilities::RegistrationOptions(
+ DiagnosticProvider::DiagnosticRegistrationOptions(
x,
) => x.diagnostic_options.identifier.clone()?,
_ => None?,
@@ -293,8 +297,8 @@ impl Client {
};
// dbg!(&x);
match x.clone() {
- DocumentDiagnosticReportResult::Report(
- DocumentDiagnosticReport::Full(
+ // DocumentDiagnosticReport::DocumentDiagnosticReport(
+ DocumentDiagnosticReport::RelatedFullDocumentDiagnosticReport(
RelatedFullDocumentDiagnosticReport {
related_documents,
full_document_diagnostic_report:
@@ -303,7 +307,7 @@ impl Client {
result_id,
},
},
- ),
+
) => {
let l = self.diagnostics.guard();
self.diagnostics.insert(f.tid().uri, items, &l);
@@ -311,14 +315,14 @@ impl Client {
related_documents.into_iter().flatten()
{
match rel {
- DocumentDiagnosticReportKind::Full(
+ RelatedDocument::FullDocumentDiagnosticReport(
FullDocumentDiagnosticReport {
items, ..
},
) => {
self.diagnostics.insert(uri, items, &l);
}
- DocumentDiagnosticReportKind::Unchanged(_) => {
+ RelatedDocument::UnchangedDocumentDiagnosticReport(_) => {
}
}
}
@@ -343,15 +347,14 @@ impl Client {
> + use<>,
> {
self.caps().document_highlight_provider.require()?;
- let p = DocumentHighlightParams {
+ Ok(send!(self.request_::<{Redraw}>, "textDocument/documentHighlight", _ {
text_document_position_params: TextDocumentPositionParams {
text_document: f.tid(),
position: cursor,
},
work_done_progress_params: default(),
partial_result_params: default(),
- };
- Ok(self.request_::<lsp_request!("textDocument/documentHighlight"), {Redraw}>(&p)
+ })
.unwrap()
.0
.map(|x| x.map(|x| x.unwrap_or_default())))
@@ -369,8 +372,7 @@ impl Client {
> + use<>,
> {
self.caps().document_symbol_provider.require()?;
- Ok(self.request_::<lsp_request!("textDocument/documentSymbol"), { Redraw }>(
- &DocumentSymbolParams {
+ Ok(send!(self.request_::<{ Redraw }>, "textDocument/documentSymbol", _ {
text_document: p.tid(),
work_done_progress_params: default(),
partial_result_params: default(),
@@ -387,20 +389,22 @@ impl Client {
impl Future<
Output = Result<
Option<WorkspaceSymbolResponse>,
- RequestError<lsp_request!("workspace/symbol")>,
+ RequestError<
+ rust_analyzer::lsp::ext::WorkspaceSymbolRequest,
+ >,
>,
> + use<>,
> {
self.caps().workspace_symbol_provider.require()?;
Ok(self
- .request_::<lsp_request!("workspace/symbol"), { Redraw }>(
- &lsp_types::WorkspaceSymbolParams {
+ .request_::<rust_analyzer::lsp::ext::WorkspaceSymbolRequest, { Redraw }>(
+ &rust_analyzer::lsp::ext::WorkspaceSymbolParams {
query: f,
search_scope: Some(
- lsp_types::WorkspaceSymbolSearchScope::Workspace,
+ WorkspaceSymbolSearchScope::Workspace,
),
search_kind: Some(
- lsp_types::WorkspaceSymbolSearchKind::AllSymbols,
+ WorkspaceSymbolSearchKind::AllSymbols,
),
..Default::default()
},
@@ -413,11 +417,10 @@ impl Client {
&self,
f: &Path,
x: Vec<Position>,
- ) -> Result<Vec<Option<Position>>, RequestError<MatchingBrace>> {
- self.request_immediate::<MatchingBrace>(&MatchingBraceParams {
- text_document: f.tid(),
- positions: x,
- })
+ ) -> Result<Vec<[Position;2]>, RequestError<MatchingBraceRequest>> {
+ self.request_immediate::<MatchingBraceRequest>(
+ &MatchingBraceParams { text_document: f.tid(), positions: x },
+ )
}
pub fn matching_brace<'a>(&self, f: &Path, t: &'a mut TextArea) {
@@ -425,16 +428,23 @@ impl Client {
self.matching_brace_at(f, t.cursor.positions(&t.rope))
{
for (c, p) in t.cursor.inner.iter_mut().zip(x) {
- if let Some(p) = p {
- c.position = t.rope.l_position(p).unwrap();
- }
+ // if let Some(p) = p {
+ c.position = t.rope.l_position(p[1]).unwrap();
+ // }
}
}
}
pub fn legend(&self) -> Option<&SemanticTokensLegend> {
- match &self.caps(){
- ServerCapabilities {semantic_tokens_provider:Some(SemanticTokensServerCapabilities::SemanticTokensOptions(SemanticTokensOptions{legend,..})), ..}=> {Some(legend)},_ => None,
+ match &self.caps() {
+ ServerCapabilities {
+ semantic_tokens_provider:
+ Some(SemanticTokensProvider::SemanticTokensOptions(
+ SemanticTokensOptions { legend, .. },
+ )),
+ ..
+ } => Some(legend),
+ _ => None,
}
}
pub fn inlay(
@@ -451,7 +461,7 @@ impl Client {
> + use<>,
> {
self.caps().inlay_hint_provider.require()?;
- Ok(self.request_::<lsp_request!("textDocument/inlayHint"), { Redraw }>(&InlayHintParams {
+ Ok(send!(self.request_::<{ Redraw }>, "textDocument/inlayHint", _ {
work_done_progress_params: default(),
text_document: f.tid(),
range: t.to_l_range(lower::saturating::math!{
@@ -481,28 +491,26 @@ impl Client {
impl Future<
Output = Result<
Option<Vec<TextEdit>>,
- RequestError<Formatting>,
+ RequestError<lsp_request!("textDocument/formatting")>,
>,
>,
> {
self.caps().document_formatting_provider.require()?;
- Ok(self
- .request::<lsp_request!("textDocument/formatting")>(
- &DocumentFormattingParams {
- text_document: f.tid(),
- options: FormattingOptions {
- tab_size: 4,
- insert_spaces: false,
- properties: default(),
- trim_trailing_whitespace: Some(true),
- insert_final_newline: Some(true),
- trim_final_newlines: Some(false),
- },
- work_done_progress_params: default(),
- },
- )
- .unwrap()
- .0)
+ Ok(send!(self.request, "textDocument/formatting",
+ _ {
+ text_document: f.tid(),
+ options: FormattingOptions {
+ tab_size: 4,
+ insert_spaces: false,
+ // properties: default(),
+ trim_trailing_whitespace: Some(true),
+ insert_final_newline: Some(true),
+ trim_final_newlines: Some(false),
+ },
+ work_done_progress_params: default(),
+ })
+ .unwrap()
+ .0)
}
pub fn rq_semantic_tokens(
&self,
@@ -510,12 +518,15 @@ impl Client {
Box<[SemanticToken]>,
Box<[SemanticToken]>,
(),
- RequestError<SemanticTokensFullRequest>,
+ RequestError<lsp_request!("textDocument/semanticTokens/full")>,
>,
f: &Path,
) -> Requiring<
"semantic_tokens",
- Result<(), RequestError<SemanticTokensFullRequest>>,
+ Result<
+ (),
+ RequestError<lsp_request!("textDocument/semanticTokens/full")>,
+ >,
> {
self.caps().semantic_tokens_provider.require()?;
debug!("requested semantic tokens");
@@ -524,25 +535,23 @@ impl Client {
// return Ok(());
// };
Ok(try bikeshed Result<(), RequestError<_>> {
- let (rx, _) = self.request::<SemanticTokensFullRequest>(
- &SemanticTokensParams {
- work_done_progress_params: default(),
- partial_result_params: default(),
- text_document: f.tid(),
- },
- )?;
+ let (rx, _) = send!(self.request, "textDocument/semanticTokens/full", _ {
+ work_done_progress_params: default(),
+ partial_result_params: default(),
+ text_document: f.tid(),
+ })?;
let x = self.runtime.spawn(async move {
let t = rx.await;
let y =
t?.ok_or(RequestError::Rx(std::marker::PhantomData))?;
debug!("received semantic tokens");
- let r = match y {
- SemanticTokensResult::Partial(_) =>
- panic!("i told the lsp i dont support this"),
- SemanticTokensResult::Tokens(x) =>
- x.data.into_boxed_slice(),
- };
- Ok(r)
+ // let r = match y {
+ // SemanticTokensResult::Partial(_) =>
+ // panic!("i told the lsp i dont support this"),
+ // SemanticTokensResult::Tokens(x) =>
+ // x.data.into_boxed_slice(),
+ // };
+ Ok(y.data.into_boxed_slice())
});
to.request(x);
})
@@ -555,7 +564,7 @@ impl Client {
) -> rootcause::Result<()> {
ceach!(t.cursor, |c| try bikeshed rootcause::Result<()> {
let r = self
- .request_by::<OnEnter>(
+ .request_by::<OnEnterRequest>(
&TextDocumentPositionParams {
text_document: f.tid(),
position: t.to_l_position(*c).unwrap(),
@@ -580,11 +589,12 @@ impl Client {
t: &Path,
c: Option<Position>,
) -> Result<
- impl Future<Output = Result<Vec<Runnable>, RequestError<Runnables>>>
- + use<>,
- RqSendError<Runnables>,
+ impl Future<
+ Output = Result<Vec<Runnable>, RequestError<RunnablesRequest>>,
+ > + use<>,
+ RqSendError<RunnablesRequest>,
> {
- self.request::<Runnables>(&RunnablesParams {
+ self.request::<RunnablesRequest>(&RunnablesParams {
text_document: t.tid(),
position: c,
})
@@ -598,13 +608,13 @@ impl Client {
) -> Result<
impl Future<
Output = Result<
- <ChildModules as Request>::Result,
- RequestError<ChildModules>,
+ <ChildModulesRequest as Request>::Result,
+ RequestError<ChildModulesRequest>,
>,
>,
- RqSendError<ChildModules>,
+ RqSendError<ChildModulesRequest>,
> {
- self.request::<ChildModules>(&TextDocumentPositionParams {
+ self.request::<ChildModulesRequest>(&TextDocumentPositionParams {
position: p,
text_document: t.tid(),
})
@@ -616,17 +626,19 @@ impl Client {
) -> Result<
impl Future<
Output = Result<
- <GotoImplementation as Request>::Result,
- RequestError<GotoImplementation>,
+ <lsp_request!("textDocument/implementation") as Request>::Result,
+ RequestError<lsp_request!("textDocument/implementation")>,
>,
> + use<>,
- RqSendError<GotoImplementation>,
- > {
- self.request::<GotoImplementation>(&GotoImplementationParams {
- text_document_position_params: tdpp,
- work_done_progress_params: default(),
- partial_result_params: default(),
- })
+ RqSendError<lsp_request!("textDocument/implementation")>,
+ >{
+ send!(self.request, "textDocument/implementation",
+ _ {
+ text_document_position_params: tdpp,
+ work_done_progress_params: default(),
+ partial_result_params: default(),
+ },
+ )
.map(fst)
}
@@ -637,17 +649,19 @@ impl Client {
impl Future<
Output = Result<
Option<Vec<Location>>,
- RequestError<References>,
+ RequestError<lsp_request!("textDocument/references")>,
>,
> + use<>,
- RqSendError<References>,
+ RqSendError<lsp_request!("textDocument/references")>,
> {
- self.request::<References>(&ReferenceParams {
- text_document_position: tdpp,
- work_done_progress_params: default(),
- partial_result_params: default(),
- context: ReferenceContext { include_declaration: false },
- })
+ send!(self.request, "textDocument/references",
+ _ {
+ text_document_position_params: tdpp,
+ work_done_progress_params: default(),
+ partial_result_params: default(),
+ context: ReferenceContext { include_declaration: false },
+ },
+ )
.map(fst)
}
@@ -666,15 +680,19 @@ impl Client {
impl Future<
Output = Result<
Option<CallHierarchyItem>,
- RequestError<CallHierarchyPrepare>,
+ RequestError<
+ lsp_request!("textDocument/prepareCallHierarchy"),
+ >,
>,
> + use<>,
- RqSendError<CallHierarchyPrepare>,
+ RqSendError<lsp_request!("textDocument/prepareCallHierarchy")>,
> {
- self.request::<CallHierarchyPrepare>(&CallHierarchyPrepareParams {
- text_document_position_params: at,
- work_done_progress_params: default(),
- })
+ send!(self.request, "textDocument/prepareCallHierarchy",
+ _ {
+ text_document_position_params: at,
+ work_done_progress_params: default(),
+ }
+ )
.map(fst)
.map(|x| x.map(|x| x.map(|x| x.and_then(|mut x| x.try_remove(0)))))
}
@@ -683,7 +701,7 @@ impl Client {
at: TextDocumentPositionParams,
) -> rootcause::Result<Vec<CallHierarchyIncomingCall>> {
let calls = self
- .request::<CallHierarchyIncomingCalls>(
+ .request::<CallHierarchyIncomingCallsRequest>(
&CallHierarchyIncomingCallsParams {
item: self
.find_function(at)?
@@ -703,7 +721,7 @@ impl Client {
at: TextDocumentPositionParams,
) -> rootcause::Result<Vec<CallHierarchyOutgoingCall>> {
let calls = self
- .request::<CallHierarchyOutgoingCalls>(
+ .request::<CallHierarchyOutgoingCallsRequest>(
&CallHierarchyOutgoingCallsParams {
item: self
.find_function(at)?
diff --git a/src/lsp/communication.rs b/src/lsp/communication.rs
index 4c4f49d..efc44ee 100644
--- a/src/lsp/communication.rs
+++ b/src/lsp/communication.rs
@@ -7,22 +7,29 @@ use std::time::Instant;
use crossbeam::channel::{Receiver, RecvError, SendError, Sender};
use log::{debug, error, trace};
use lsp_server::{
- ErrorCode, Message, Notification as N, Request as LRq, Response as Re,
- ResponseError,
+ ErrorCode, ExtractError, Message, Notification as N, Request as LRq,
+ RequestId, Response as Re, ResponseError,
};
-use lsp_types::notification::*;
-use lsp_types::request::*;
use lsp_types::*;
+use serde::{Deserialize, Serialize};
use tokio::sync::oneshot;
use tokio::time::error::Elapsed;
+use url::Url;
use winit::window::Window;
+#[derive(Debug, PartialEq, Deserialize, Serialize, Clone)]
+#[serde(untagged)]
+pub enum WorkDoneProgress {
+ Begin(WorkDoneProgressBegin),
+ Report(WorkDoneProgressReport),
+ End(WorkDoneProgressEnd),
+}
use crate::lsp::BehaviourAfter::{self, *};
use crate::lsp::{RequestError, RqSendError};
pub fn handler(
window_rx: oneshot::Receiver<Arc<dyn Window + 'static>>,
progress: &papaya::HashMap<
- NumberOrString,
+ ProgressToken,
Option<(WorkDoneProgress, WorkDoneProgressBegin)>,
>,
_req_tx: Sender<LRq>,
@@ -40,13 +47,13 @@ pub fn handler(
Ok((.., BehaviourAfter::RedrawNow)) => w.request_redraw(),
Ok((x, y, and)) => {
debug!("received request {x}");
- assert!(map.insert(x, (y, Instant::now(), and)).is_none());
+ assert!(map.insert(RequestId::from(x), (y, Instant::now(), and)).is_none());
}
Err(RecvError) => return,
},
recv(rx) -> x => match x {
Ok(Message::Request(rq @ LRq { method: "window/workDoneProgress/create", .. })) => {
- match rq.load::<WorkDoneProgressCreate>() {
+ match load_rq::<lsp_request!("window/workDoneProgress/create")>(rq) {
Ok((_, x)) => {
let g = progress.guard();
progress.insert(x.token, None, &g);
@@ -67,13 +74,13 @@ pub fn handler(
if let Some(e) = &x.error {
if e.code == ErrorCode::RequestCanceled as i32 {}
else if e.code == ErrorCode::ServerCancelled as i32 {
- if let Some((s, _, t)) = map.remove(&x.id.i32()) {
+ if let Some((s, _, t)) = map.remove(&x.id) {
log::info!("request {} cancelled", x.id);
_ = s.send(x);
if t == Redraw { w.request_redraw() }
}
} else {
- if let Some((s, _, t)) = map.remove(&x.id.i32()) {
+ if let Some((s, _, t)) = map.remove(&x.id) {
_ = s.send(x.clone());
if t == Redraw { w.request_redraw() }
trace!("received error from lsp for response {x:?}");
@@ -82,7 +89,7 @@ pub fn handler(
}
}
}
- else if let Some((s, took, t)) = map.remove(&x.id.i32()) {
+ else if let Some((s, took, t)) = map.remove(&x.id) {
log::debug!("request {} took {:?}", x.id, took.elapsed());
match s.send(x) {
Ok(()) => {}
@@ -100,7 +107,7 @@ pub fn handler(
}
Ok(Message::Notification(rq @ N { method: "textDocument/publishDiagnostics", .. })) => {
debug!("got diagnostics");
- match rq.load::<PublishDiagnostics>() {
+ match load_n::<lsp_notification!("textDocument/publishDiagnostics")>(rq) {
Ok(x) => {
d.insert(x.uri, x.diagnostics, &d.guard());
w.request_redraw();
@@ -109,7 +116,8 @@ pub fn handler(
}
},
Ok(Message::Notification(x @ N { method: "$/progress", .. })) => {
- let ProgressParams {token,value:ProgressParamsValue::WorkDone(x) } = x.load::<Progress>().unwrap();
+ let ProgressParams {token,value:x } = load_n::<lsp_notification!("$/progress")>(x).unwrap();
+ let Ok(x) = serde_json::from_value::<WorkDoneProgress>(x.clone()) else { error!("{x:?}"); continue };
match x.clone() {
WorkDoneProgress::Begin(y) => {
progress.update(token, move |_| Some((x.clone(), y.clone())), &progress.guard());
@@ -131,6 +139,34 @@ pub fn handler(
}
}
}
+#[derive(Debug)]
+#[allow(dead_code)]
+pub enum ExtractErr<T> {
+ /// The extracted message was of a different method than expected.
+ MethodMismatch(T),
+ /// Failed to deserialize the message.
+ JsonError { method: String, error: serde_json::Error },
+}
+fn load_n<T: lsp_types::Notification>(
+ me: lsp_server::Notification,
+) -> Result<T::Params, ExtractErr<lsp_server::Notification>> {
+ (T::METHOD.as_str() == me.method)
+ .ok_or(ExtractErr::MethodMismatch(me.clone()))?;
+ serde_json::from_value(me.params)
+ .map_err(|e| ExtractErr::JsonError { method: me.method, error: e })
+}
+pub fn load_rq<P: lsp_types::Request>(
+ me: LRq,
+) -> Result<(RequestId, P::Params), ExtractError<LRq>> {
+ if me.method != P::METHOD.to_string() {
+ return Err(ExtractError::MethodMismatch(me));
+ }
+ match serde_json::from_value(me.params) {
+ Ok(params) => Ok((me.id, params)),
+ Err(error) =>
+ Err(ExtractError::JsonError { method: me.method, error }),
+ }
+}
impl super::Tx {
pub fn notify<X: Notification>(
&self,
@@ -142,7 +178,9 @@ impl super::Tx {
}))
}
pub fn cancel(&self, rid: i32) {
- _ = self.notify::<Cancel>(&CancelParams { id: rid.into() });
+ _ = self.notify::<CancelNotification>(&CancelParams {
+ id: rid.into(),
+ });
}
}
impl super::Client {
@@ -266,3 +304,13 @@ impl super::Client {
self.send_to.send((0, tx, BehaviourAfter::RedrawNow))
}
}
+macro_rules! send
+ {
+ ($c:ident.$call:ident$(::<$($arg:block),*>)?, $request:tt, _ { $($field:ident: $expr:expr),* $(,)? $(,..$base:expr)? } $(,)?) => {{
+ type R = lsp_request!($request);
+ type P = <R as Request>::Params;
+ $c.$call::<R $($(,$arg)*)?>(&P { $($field: $expr),* })
+ }};
+}
+
+pub(crate) use send;
diff --git a/src/lsp/init_opts.rs b/src/lsp/init_opts.rs
index 345e2a4..797ba17 100644
--- a/src/lsp/init_opts.rs
+++ b/src/lsp/init_opts.rs
@@ -6,13 +6,13 @@ pub fn get(
conf: &Option<serde_json::Value>,
is_ra: bool,
) -> InitializeParams {
- let sym = Some(if is_ra {
- SymbolKind::ALL.to_vec()
- } else {
- (1..=26).map(SymbolKind).collect()
- });
+ // let sym = Some(if is_ra {
+ // SymbolKind::ALL.to_vec()
+ // } else {
+ // (1..=26).map(SymbolKind).collect()
+ // });
InitializeParams {
- process_id: Some(std::process::id()),
+ process_id: Some(std::process::id() as _),
capabilities: ClientCapabilities {
window: Some(WindowClientCapabilities {
@@ -21,20 +21,18 @@ pub fn get(
}),
workspace: Some(WorkspaceClientCapabilities {
symbol: Some(WorkspaceSymbolClientCapabilities {
- symbol_kind: Some(SymbolKindCapability {
- value_set: sym.clone(),
+ // symbol_kind: Some(ClientSymbolKindOptions {
+ // value_set: sym.clone(),
+ // }),
+ // tag_support: Some(ClientSymbolTagOptions {
+ // value_set: SymbolTag::ALL.to_vec(),
+ // }),
+ resolve_support: Some(ClientSymbolResolveOptions {
+ properties: vec!["location".into()],
}),
- tag_support: Some(TagSupport {
- value_set: SymbolTag::ALL.to_vec(),
- }),
- resolve_support: Some(
- WorkspaceSymbolResolveSupportCapability {
- properties: vec!["location".into()],
- },
- ),
..default()
}),
- diagnostic: Some(DiagnosticWorkspaceClientCapabilities {
+ diagnostics: Some(DiagnosticWorkspaceClientCapabilities {
refresh_support: Some(true),
}),
inlay_hint: Some(InlayHintWorkspaceClientCapabilities {
@@ -50,10 +48,12 @@ pub fn get(
failure_handling: Some(FailureHandlingKind::Abort),
normalizes_line_endings: Some(false),
change_annotation_support: Some(
- ChangeAnnotationWorkspaceEditClientCapabilities {
+ ChangeAnnotationsSupportOptions {
groups_on_label: Some(false),
},
),
+ metadata_support: None,
+ snippet_edit_support: Some(true),
}),
..default()
}),
@@ -64,47 +64,45 @@ pub fn get(
},
),
document_highlight: Some(default()),
- formatting: Some(DynamicRegistrationClientCapabilities {
+ formatting: Some(DocumentFormattingClientCapabilities {
dynamic_registration: Some(false),
}),
inlay_hint: Some(InlayHintClientCapabilities {
dynamic_registration: None,
- resolve_support: Some(
- InlayHintResolveClientCapabilities {
- properties: vec![
- "textEdits".into(),
- "tooltip".into(),
- "label.tooltip".into(),
- "label.command".into(),
- ],
- },
- ),
+ resolve_support: Some(ClientInlayHintResolveOptions {
+ properties: vec![
+ "textEdits".into(),
+ "tooltip".into(),
+ "label.tooltip".into(),
+ "label.command".into(),
+ ],
+ }),
}),
document_symbol: Some(DocumentSymbolClientCapabilities {
- tag_support: Some(TagSupport {
- value_set: SymbolTag::ALL.to_vec(),
- }),
- symbol_kind: Some(SymbolKindCapability {
- value_set: sym,
- }),
+ // tag_support: Some(ClientSymbolTagSupport {
+ // value_set: SymbolTag::ALL.to_vec(),
+ // }),
+ // symbol_kind: Some(ClientSymbolKindOptions {
+ // value_set: sym,
+ // }),
hierarchical_document_symbol_support: Some(true),
..default()
}),
- definition: Some(GotoCapability {
+ definition: Some(DefinitionClientCapabilities {
link_support: Some(true),
..default()
}),
code_action: Some(CodeActionClientCapabilities {
data_support: Some(true),
resolve_support: Some(
- CodeActionCapabilityResolveSupport {
+ ClientCodeActionResolveOptions {
properties: vec!["edit".to_string()],
},
),
code_action_literal_support: Some(
- CodeActionLiteralSupport {
+ ClientCodeActionLiteralOptions {
code_action_kind:
- CodeActionKindLiteralSupport {
+ ClientCodeActionKindOptions {
value_set: [
"",
"Empty",
@@ -123,7 +121,7 @@ pub fn get(
"source",
"source.organizeImports",
]
- .map(String::from)
+ .map(Into::into)
.into(),
},
},
@@ -133,7 +131,7 @@ pub fn get(
rename: Some(RenameClientCapabilities {
prepare_support: Some(true),
prepare_support_default_behavior: Some(
- PrepareSupportDefaultBehavior::IDENTIFIER,
+ PrepareSupportDefaultBehavior::Identifier,
),
honors_change_annotations: Some(false),
..default()
@@ -148,36 +146,40 @@ pub fn get(
diagnostic: Some(DiagnosticClientCapabilities {
dynamic_registration: None,
related_document_support: Some(true),
+ markup_message_support: None,
+ diagnostics_capabilities: default(),
}),
publish_diagnostics: Some(
PublishDiagnosticsClientCapabilities {
- related_information: Some(true),
- code_description_support: Some(true),
- data_support: Some(true),
+ // related_information: Some(true),
+ // code_description_support: Some(true),
+ // data_support: Some(true),
..default()
},
),
signature_help: Some(SignatureHelpClientCapabilities {
dynamic_registration: None,
signature_information: Some(
- SignatureInformationSettings {
+ ClientSignatureInformationOptions {
documentation_format: Some(vec![
MarkupKind::Markdown,
MarkupKind::PlainText,
]),
parameter_information: Some(
- ParameterInformationSettings {
+ ClientSignatureParameterInformationOptions {
label_offset_support: Some(true),
},
),
active_parameter_support: Some(true),
+ no_active_parameter_support: Some(true),
+
},
),
context_support: Some(false),
}),
completion: Some(CompletionClientCapabilities {
dynamic_registration: Some(false),
- completion_item: Some(CompletionItemCapability {
+ completion_item: Some(ClientCompletionItemOptions {
snippet_support: Some(true),
commit_characters_support: Some(true),
documentation_format: Some(vec![
@@ -186,12 +188,12 @@ pub fn get(
]),
deprecated_support: None,
preselect_support: None,
- tag_support: Some(TagSupport {
- value_set: vec![CompletionItemTag::DEPRECATED],
+ tag_support: Some(CompletionItemTagOptions {
+ value_set: vec![CompletionItemTag::Deprecated],
}),
resolve_support: Some(
- CompletionItemCapabilityResolveSupport {
+ ClientCompletionItemResolveOptions {
properties: vec![
"additionalTextEdits".into(),
"documentation".into(),
@@ -200,60 +202,56 @@ pub fn get(
),
insert_replace_support: Some(false),
insert_text_mode_support: Some(
- InsertTextModeSupport {
- value_set: vec![InsertTextMode::AS_IS],
+ ClientCompletionItemInsertTextModeOptions {
+ value_set: vec![InsertTextMode::AsIs],
},
),
label_details_support: Some(true),
..default()
}),
completion_item_kind: Some(
- CompletionItemKindCapability {
+ ClientCompletionItemOptionsKind {
value_set: Some(vec![
- CompletionItemKind::TEXT,
- CompletionItemKind::METHOD,
- CompletionItemKind::FUNCTION,
- CompletionItemKind::CONSTRUCTOR,
- CompletionItemKind::FIELD,
- CompletionItemKind::VARIABLE,
- CompletionItemKind::CLASS,
- CompletionItemKind::INTERFACE,
- CompletionItemKind::MODULE,
- CompletionItemKind::PROPERTY,
- CompletionItemKind::UNIT,
- CompletionItemKind::VALUE,
- CompletionItemKind::ENUM,
- CompletionItemKind::KEYWORD,
- CompletionItemKind::SNIPPET,
- CompletionItemKind::COLOR,
- CompletionItemKind::FILE,
- CompletionItemKind::REFERENCE,
- CompletionItemKind::FOLDER,
- CompletionItemKind::ENUM_MEMBER,
- CompletionItemKind::CONSTANT,
- CompletionItemKind::STRUCT,
- CompletionItemKind::EVENT,
- CompletionItemKind::OPERATOR,
- CompletionItemKind::TYPE_PARAMETER,
+ CompletionItemKind::Text,
+ CompletionItemKind::Method,
+ CompletionItemKind::Function,
+ CompletionItemKind::Constructor,
+ CompletionItemKind::Field,
+ CompletionItemKind::Variable,
+ CompletionItemKind::Class,
+ CompletionItemKind::Interface,
+ CompletionItemKind::Module,
+ CompletionItemKind::Property,
+ CompletionItemKind::Unit,
+ CompletionItemKind::Value,
+ CompletionItemKind::Enum,
+ CompletionItemKind::Keyword,
+ CompletionItemKind::Snippet,
+ CompletionItemKind::Color,
+ CompletionItemKind::File,
+ CompletionItemKind::Reference,
+ CompletionItemKind::Folder,
+ CompletionItemKind::EnumMember,
+ CompletionItemKind::Constant,
+ CompletionItemKind::Struct,
+ CompletionItemKind::Event,
+ CompletionItemKind::Operator,
+ CompletionItemKind::TypeParameter,
]),
- // value_set: Some(vec![CompletionItemKind::]),
},
),
context_support: None,
- insert_text_mode: Some(InsertTextMode::AS_IS),
- completion_list: Some(CompletionListCapability {
+ insert_text_mode: Some(InsertTextMode::AsIs),
+ completion_list: Some(CompletionListCapabilities {
item_defaults: None,
+ apply_kind_support: None,
}),
}),
semantic_tokens: Some(SemanticTokensClientCapabilities {
dynamic_registration: Some(false),
- requests: SemanticTokensClientCapabilitiesRequests {
- range: Some(true),
- full: Some(
- lsp_types::SemanticTokensFullOptions::Bool(
- true,
- ),
- ),
+ requests: ClientSemanticTokensRequestOptions {
+ range: Some(true.into()),
+ full: Some(true.into()),
},
token_modifiers: [
"associated",
@@ -313,8 +311,10 @@ pub fn get(
}),
initialization_options: conf.clone(),
trace: None,
- workspace_folders: Some(vec![workspace]),
-
+ workspace_folders_initialize_params:
+ WorkspaceFoldersInitializeParams {
+ workspace_folders: Some(vec![workspace].into()),
+ },
..default()
}
}
diff --git a/src/lsp/rq.rs b/src/lsp/rq.rs
index b7e42e0..50a6fd3 100644
--- a/src/lsp/rq.rs
+++ b/src/lsp/rq.rs
@@ -4,8 +4,10 @@ use std::marker::PhantomData;
use crossbeam::channel::SendError;
use lsp_server::{Message, Response as Re};
-use lsp_types::DiagnosticServerCancellationData;
-use lsp_types::request::Request;
+use lsp_types::{
+ DiagnosticServerCancellationData, LspRequestMethod, MessageDirection,
+ Request,
+};
use serde::{Deserialize, Serialize};
use tokio::sync::oneshot;
use tokio::task;
@@ -26,7 +28,10 @@ pub type AQErr = RequestError<LSPError>;
impl Request for LSPError {
type Params = ();
type Result = ();
- const METHOD: &'static str = "<unknown method>";
+ const MESSAGE_DIRECTION: lsp_types::MessageDirection =
+ MessageDirection::ServerToClient;
+ const METHOD: LspRequestMethod<'static> =
+ LspRequestMethod::Custom("<unknown method>");
}
#[derive(Debug)]
pub struct LSPError {}
@@ -158,11 +163,11 @@ impl<T: Clone, R, D, E> Clone for Rq<T, R, D, E> {
}
}
#[derive(serde_derive::Serialize, serde_derive::Deserialize)]
-pub struct Rq<T, R, D = (), E = RequestError<R>> {
+pub struct Rq<Output, Res, Data = (), Error = LSPError> {
#[serde(skip_serializing_if = "Option::is_none", default = "none")]
- pub result: Option<T>,
+ pub result: Option<Output>,
#[serde(skip, default = "none")]
- pub request: Option<(AbortOnDropHandle<Result<R, E>>, D)>,
+ pub request: Option<(AbortOnDropHandle<Result<Res, Error>>, Data)>,
}
impl<T: Debug, R, D: Debug, E> Debug for Rq<T, R, D, E> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
diff --git a/src/main.rs b/src/main.rs
index 8c617ba..9ac477a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,5 @@
#![feature(
+ const_convert,
unsized_const_params,
exact_div,
yeet_expr,
@@ -64,8 +65,10 @@ use Default::default;
use NamedKey::*;
use dsb::cell::Style;
use dsb::{Cell, F};
+use env_logger::{Env, TimestampPrecision};
use fimg::Image;
use libc::{atexit, signal};
+use log::LevelFilter;
use lsp::Rq;
use lsp_types::*;
use rust_fsm::StateMachine;
@@ -103,10 +106,15 @@ fn main() {
let _x = 4;
// let x = HashMap::new();
unsafe { std::env::set_var("CARGO_UNSTABLE_RUSTC_UNICODE", "true") };
- env_logger::builder()
- .filter_level(log::LevelFilter::Info)
- .parse_env("GRA_LOG")
- .init();
+ env_logger::builder().filter_level(LevelFilter::Error).init();
+ // .format_timestamp(Some(TimestampPrecision::Seconds))
+ // .filter(Some("regex_cursor"), LevelFilter::Error)
+ // .filter(Some("calloop"), LevelFilter::Error)
+ // .filter(Some("tracing::span"), LevelFilter::Error)
+ // .parse_env(Env::new().default_filter_or("info"))
+ // .filter_level(log::LevelFilter::Info)
+ // .parse_env("G"RA_LOG")
+ // .init();
// lsp::x();
entry(EventLoop::new().unwrap())
}
@@ -236,7 +244,12 @@ pub(crate) fn entry(event_loop: EventLoop) {
if let Some((.., c)) = &mut ed.lsp && let Some(c) = c.take() {
c.send(window.clone()).unwrap();
}
+
let lsp_mn = &mut lsp_mn;
+ for lem in &lsp_mn.four {
+ lem.1.status();
+ // dbg!(lem.1);
+ }
let (fw, fh) = dsb::dims(&FONT, ppem);
let (c, r) = dsb::fit(
&FONT,
@@ -504,11 +517,11 @@ rust_fsm::state_machine! {
pub(crate) CompletionState => #[derive(Debug)] pub(crate) CompletionAction<'i> => pub(crate) CDo
None => Click => None,
None => K(Key<&'i str> => Key::Character(k @ ("." | ":"))) => Complete(
- RqS<Complete, lsp_types::request::Completion, usize> => default()
- ) [Request(CompletionContext => CompletionContext {trigger_kind: CompletionTriggerKind::TRIGGER_CHARACTER, trigger_character:Some(k.to_string()) })],
- None => K(Key::Character(" ") if ctrl()) => Complete(default()) [Request(CompletionContext { trigger_kind: CompletionTriggerKind::INVOKED, trigger_character:None })],
+ RqS<Complete, lsp_types::CompletionRequest, usize> => default()
+ ) [Request(CompletionContext => CompletionContext {trigger_kind: CompletionTriggerKind::TriggerCharacter, trigger_character:Some(k.to_string()) })],
+ None => K(Key::Character(" ") if ctrl()) => Complete(default()) [Request(CompletionContext { trigger_kind: CompletionTriggerKind::Invoked, trigger_character:None })],
None => K(Key::Character(x) if x.chars().all(char::is_alphabetic)
- && !matches!(x, "w"|"a"|"s"|"d" if alt())) => Complete(default()) [Request(CompletionContext { trigger_kind: CompletionTriggerKind::INVOKED, trigger_character:None })],
+ && !matches!(x, "w"|"a"|"s"|"d" if alt())) => Complete(default()) [Request(CompletionContext { trigger_kind: CompletionTriggerKind::Invoked, trigger_character:None })],
None => K(_) => _,
// when
@@ -526,7 +539,7 @@ rust_fsm::state_machine! {
Complete(Rq { result: Some(x), .. }) => K(Key::Named(NamedKey::Enter)) => None [Finish(Complete => x)],
- Complete(_x) => K(_) => _ [Request(CompletionContext { trigger_kind: CompletionTriggerKind::TRIGGER_FOR_INCOMPLETE_COMPLETIONS, trigger_character:None })],
+ Complete(_x) => K(_) => _ [Request(CompletionContext { trigger_kind: CompletionTriggerKind::TriggerForIncompleteCompletions, trigger_character:None })],
}
use complete::Complete;
diff --git a/src/rnd.rs b/src/rnd.rs
index 2f458ad..181f48b 100644
--- a/src/rnd.rs
+++ b/src/rnd.rs
@@ -262,14 +262,23 @@ pub fn render(
.flat_map(|diag| {
let sev = diag
.severity
- .unwrap_or(DiagnosticSeverity::ERROR);
+ .unwrap_or(DiagnosticSeverity::Error);
let sev_ = match sev {
- DiagnosticSeverity::ERROR => EType::Error,
- DiagnosticSeverity::WARNING => EType::Warning,
- DiagnosticSeverity::HINT => EType::Hint,
+ DiagnosticSeverity::Error => EType::Error,
+ DiagnosticSeverity::Warning => EType::Warning,
+ DiagnosticSeverity::Hint => EType::Hint,
_ => EType::Info,
};
- once((diag.range, &*diag.message, sev_)).chain(
+ once((
+ diag.range,
+ match &diag.message {
+ Message::String(x) => &**x,
+ Message::MarkupContent(x) =>
+ unimplemented!(),
+ },
+ sev_,
+ ))
+ .chain(
diag.related_information
.iter()
.flatten()
@@ -285,7 +294,7 @@ pub fn render(
})
.for_each(|(mut r, m, sev)| {
if let EType::Related(x) = sev
- && x != DiagnosticSeverity::ERROR
+ && x != DiagnosticSeverity::Error
{
return;
}
@@ -301,7 +310,7 @@ pub fn render(
| EType::Hint
| EType::Info => col!("#9469242c"),
EType::Related(
- DiagnosticSeverity::ERROR,
+ DiagnosticSeverity::Error,
) => col!("#dfbfff26"),
EType::Related(_) => col!("#ffad6625"),
});
@@ -342,7 +351,7 @@ pub fn render(
col!("#ff942f1b", "#f26462")
}
EType::Related(
- DiagnosticSeverity::WARNING,
+ DiagnosticSeverity::Warning,
) => {
col!("#dfbfff26", "#DFBFFF")
}
@@ -581,13 +590,13 @@ pub fn render(
continue;
}
- let r = if let Some(r) = e.sticky_range {
- let r = text.l_range(r).unwrap();
- text.char_to_line(r.start)..=text.char_to_line(r.end)
- } else {
- let x = text.char_to_line(p);
- x..=x
- };
+ // let r = if let Some(r) = e.sticky_range {
+ // let r = text.l_range(r).unwrap();
+ // text.char_to_line(r.start)..=text.char_to_line(r.end)
+ // } else {
+ let x = text.char_to_line(p);
+ let r = x..=x;
+ // };
let d = Cell {
style: Style {
diff --git a/src/sig.rs b/src/sig.rs
index e1e0cfd..884fbac 100644
--- a/src/sig.rs
+++ b/src/sig.rs
@@ -3,8 +3,8 @@ use std::iter::repeat_n;
use dsb::Cell;
use dsb::cell::Style;
use lsp_types::{
- MarkupContent, ParameterInformation, SignatureHelp,
- SignatureInformation,
+ MarkupContent, ParameterInformation, ParameterInformationLabel,
+ SignatureHelp, SignatureInformation,
};
use crate::FG;
@@ -16,9 +16,14 @@ pub fn active(
let y = &sig.signatures.get(sig.active_signature? as usize)?;
Some((
y,
- sig.active_parameter
- .zip(y.parameters.as_ref())
- .and_then(|(i, x)| x.get(i as usize)),
+ sig.active_parameter.zip(y.parameters.as_ref()).and_then(
+ |(i, x)| {
+ x.get(match i {
+ lsp_types::ActiveParameter::Int(n) => n as usize,
+ lsp_types::ActiveParameter::Null => return None,
+ })
+ },
+ ),
))
}
@@ -32,8 +37,8 @@ pub fn sig(
let sig = y.label.chars().zip(0..).map(|(x, i)| {
let mut a = ds.basic(x);
if p.is_some_and(|x| match x.label {
- lsp_types::ParameterLabel::Simple(_) => false,
- lsp_types::ParameterLabel::LabelOffsets([a, b]) =>
+ ParameterInformationLabel::String(_) => false,
+ ParameterInformationLabel::Tuple((a, b)) =>
(a..b).contains(&i),
}) {
a.style |= (Style::BOLD, color_("#ffcc66"));
diff --git a/src/sym.rs b/src/sym.rs
index 1ceb2b4..fbffbef 100644
--- a/src/sym.rs
+++ b/src/sym.rs
@@ -5,10 +5,12 @@ use std::path::{Path, PathBuf};
use Default::default;
use dsb::Cell;
use dsb::cell::Style;
-use itern::Iter3;
+use itern::{Iter3, Iter4};
use lsp_types::*;
+use url::Url;
use crate::FG;
+use crate::complete::i;
use crate::gotolist::At;
pub use crate::gotolist::GoTo;
use crate::menu::generic::{GenericMenu, MenuData};
@@ -32,38 +34,48 @@ impl MenuData for Symb {
(r, tree, bmks, _, origin): &Self::Data,
) -> impl Iterator<Item = Self::Element<'_>> {
match r {
- SymbolsList::Document(DocumentSymbolResponse::Flat(x)) =>
- Iter3::A(x.iter().map(UsedSI::from)),
- SymbolsList::Document(DocumentSymbolResponse::Nested(x)) =>
- Iter3::B(
- gen {
- for bmk in &**bmks {
- yield UsedSI {
- name: &bmk.text,
- kind: SymbolKind::BOOKMARK,
- tags: None,
- at: GoTo {
- path: origin.into(),
- at: At::P(bmk.position),
- },
- right: None,
- }
+ SymbolsList::Document(
+ DocumentSymbolResponse::SymbolInformationList(x),
+ ) => Iter4::A(x.iter().map(UsedSI::from)),
+ SymbolsList::Document(
+ DocumentSymbolResponse::DocumentSymbolList(x),
+ ) => Iter4::B(
+ gen {
+ for bmk in &**bmks {
+ yield UsedSI {
+ name: &bmk.text,
+ // kind: SymbolKind::Bookmark,
+ kind: SymbolKind::Class, // FIXME
+ tags: None,
+ at: GoTo {
+ path: origin.into(),
+ at: At::P(bmk.position),
+ },
+ right: None,
}
}
- .chain(x.iter().flat_map(
- move |x| gen move {
- let mut q = VecDeque::with_capacity(12);
- q.push_back(x);
- while let Some(x) = q.pop_front() {
- q.extend(x.children.iter().flatten());
- yield (x, origin).into();
- }
- },
- )),
- ),
- SymbolsList::Workspace(WorkspaceSymbolResponse::Flat(x)) =>
- Iter3::C(chain(tree, x.iter()).map(UsedSI::from)),
- _ => unreachable!("please no"),
+ }
+ .chain(x.iter().flat_map(
+ move |x| gen move {
+ let mut q = VecDeque::with_capacity(12);
+ q.push_back(x);
+ while let Some(x) = q.pop_front() {
+ q.extend(x.children.iter().flatten());
+ yield (x, origin).into();
+ }
+ },
+ )),
+ ),
+ SymbolsList::Workspace(
+ WorkspaceSymbolResponse::WorkspaceSymbolList(x),
+ ) => Iter4::C(chain(
+ tree.iter().map(UsedSI::from),
+ x.iter().map(UsedSI::from),
+ )),
+ SymbolsList::Workspace(
+ WorkspaceSymbolResponse::SymbolInformationList(x),
+ ) => Iter4::D(chain(tree, x.iter()).map(UsedSI::from)),
+ // _ => unreachable!("please no"),
}
}
@@ -97,7 +109,7 @@ pub struct UsedSI<'a> {
impl<'a> std::hash::Hash for UsedSI<'a> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.name.hash(state);
- self.kind.0.hash(state);
+ self.kind.hash(state);
self.at.hash(state);
self.right.hash(state);
}
@@ -105,11 +117,9 @@ impl<'a> std::hash::Hash for UsedSI<'a> {
impl<'a> From<&'a SymbolInformation> for UsedSI<'a> {
fn from(
SymbolInformation {
- name,
- kind,
- tags,
+ base_symbol_information:
+ BaseSymbolInformation { name, kind, tags, container_name },
location,
- container_name,
..
}: &'a SymbolInformation,
) -> Self {
@@ -122,6 +132,24 @@ impl<'a> From<&'a SymbolInformation> for UsedSI<'a> {
}
}
}
+impl<'a> From<&'a WorkspaceSymbol> for UsedSI<'a> {
+ fn from(
+ WorkspaceSymbol {
+ location,
+ data: _,
+ base_symbol_information:
+ BaseSymbolInformation { name, kind, tags, container_name },
+ }: &'a WorkspaceSymbol,
+ ) -> Self {
+ UsedSI {
+ name,
+ kind: *kind,
+ tags: tags.as_deref(),
+ at: location.into(),
+ right: container_name.as_deref(),
+ }
+ }
+}
impl<'a> From<(&'a DocumentSymbol, &'a PathBuf)> for UsedSI<'a> {
fn from(
(
@@ -160,7 +188,9 @@ pub enum SymbolsList {
}
impl Default for SymbolsList {
fn default() -> Self {
- Self::Workspace(WorkspaceSymbolResponse::Flat(vec![]))
+ Self::Workspace(WorkspaceSymbolResponse::WorkspaceSymbolList(
+ vec![],
+ ))
}
}
@@ -169,8 +199,17 @@ impl GenericMenu<Symb> {
let tree = tree
.iter()
.map(|x| SymbolInformation {
- name: x.file_name().unwrap().to_str().unwrap().to_string(),
- kind: SymbolKind::FILE,
+ base_symbol_information: BaseSymbolInformation {
+ name: x
+ .file_name()
+ .unwrap()
+ .to_str()
+ .unwrap()
+ .to_string(),
+ kind: SymbolKind::File,
+ container_name: None,
+ tags: None,
+ },
location: Location {
range: lsp_types::Range {
end: default(),
@@ -178,10 +217,9 @@ impl GenericMenu<Symb> {
},
uri: Url::from_file_path(&x).unwrap(),
},
- container_name: None,
+
#[allow(deprecated)]
deprecated: None,
- tags: None,
})
.collect();
Self { data: (default(), tree, bmk, default(), orig), ..default() }
@@ -211,35 +249,35 @@ fn r<'a>(
const MAP: [([u8; 3], [u8; 3], &str); 85] = {
(
amap::amap! {
- const { SymbolKind::FILE.0 as usize } => ("#9a9b9a", "󰈙 "),
- const { SymbolKind::METHOD.0 as usize } | const { SymbolKind::FUNCTION.0 as usize } => ("#FFD173", "λ "),
- const { SymbolKind::CONSTRUCTOR.0 as usize } => ("#FFAD66", "->"),
- const { SymbolKind::FIELD.0 as usize } => ("#E06C75", "x."),
- const { SymbolKind::VARIABLE.0 as usize } => ("#E06C75", "x "),
- const { SymbolKind::MODULE.0 as usize } => ("#D5FF80", "::"),
- const { SymbolKind::PROPERTY.0 as usize } => ("#e6e1cf", "x."),
- // const { SymbolKind::VALUE.0 as usize } => ("#DFBFFF", "4 "),
- const { SymbolKind::ENUM.0 as usize } => ("#73b9ff", "u󰓹"),
- const { SymbolKind::ENUM_MEMBER.0 as usize } => ("#73b9ff", ":󰓹"),
- // const { SymbolKind::SNIPPET.0 as usize } => ("#9a9b9a", "! "),
- const { SymbolKind::INTERFACE.0 as usize } => ("#E5C07B", "t "),
- // const { SymbolKind::REFERENCE.0 as usize } => ("#9a9b9a", "& "),
- const { SymbolKind::CONSTANT.0 as usize } => ("#DFBFFF", "N "),
- const { SymbolKind::STRUCT.0 as usize } => ("#73D0FF", "X{"),
- const { SymbolKind::OPERATOR.0 as usize } => ("#F29E74", "+ "),
- const { SymbolKind::TYPE_PARAMETER.0 as usize } => ("#9a9b9a", "T "),
- // const { SymbolKind::KEYWORD.0 as usize } => ("#FFAD66", "as"),
+ const { i(SymbolKind::File) } => ("#9a9b9a", "󰈙 "),
+ const { i(SymbolKind::Method) } | const { i(SymbolKind::Function) } => ("#FFD173", "λ "),
+ const { i(SymbolKind::Constructor) } => ("#FFAD66", "->"),
+ const { i(SymbolKind::Field) } => ("#E06C75", "x."),
+ const { i(SymbolKind::Variable) } => ("#E06C75", "x "),
+ const { i(SymbolKind::Module) } => ("#D5FF80", "::"),
+ const { i(SymbolKind::Property) } => ("#e6e1cf", "x."),
+ // const { SymbolKind::Val.0 as usize } => ("#DFBFFF", "4 "),
+ const { i(SymbolKind::Enum) } => ("#73b9ff", "u󰓹"),
+ const { i(SymbolKind::EnumMember) } => ("#73b9ff", ":󰓹"),
+ // const { SymbolKind::Snipp.0 as usize } => ("#9a9b9a", "! "),
+ const { i(SymbolKind::Interface) } => ("#E5C07B", "t "),
+ // const { SymbolKind::Referen.0 as usize } => ("#9a9b9a", "& "),
+ const { i(SymbolKind::Constant) } => ("#DFBFFF", "N "),
+ const { i(SymbolKind::Struct) } => ("#73D0FF", "X{"),
+ const { i(SymbolKind::Operator) } => ("#F29E74", "+ "),
+ const { i(SymbolKind::TypeParameter) } => ("#9a9b9a", "T "),
+ // const { SymbolKind::Keyword.0 as usize } => ("#FFAD66", "as"),
- const { SymbolKind::MACRO.0 as usize } => ("#f28f74", "! "),
- const { SymbolKind::PROC_MACRO.0 as usize } => ("#f28f74", "r!"),
- const { SymbolKind::BOOKMARK.0 as usize } => ("#73D0FF", "󰃀 "),
+ // const { SymbolKind::Macro.0 as usize } => ("#f28f74", "! "),
+ // const { SymbolKind::ProcMacro.0 as usize } => ("#f28f74", "r!"),
+ // const { SymbolKind::Bookmark.0 as usize } => ("#73D0FF", "󰃀 "),
_ => ("#9a9b9a", " ")
})
.map(
const |(x, y)| (set_a(color_(x), 0.5), color_(x), y),
)
};
- let (bgt, col, ty) = MAP[x.kind.0 as usize];
+ let (bgt, col, ty) = MAP[i(x.kind)];
b.iter_mut().zip(ty.chars()).for_each(|(x, c)| {
*x = (Style::new(col, bgt) | Style::BOLD).basic(c)
});
diff --git a/src/text.rs b/src/text.rs
index f3677b0..59dd5ae 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -16,14 +16,14 @@ use helix_core::syntax::{HighlightEvent, Loader};
use implicit_fn::implicit_fn;
use itertools::Itertools;
use lsp_types::{
- DocumentSymbol, Location, SemanticTokensLegend, SnippetTextEdit,
- TextEdit,
+ DocumentSymbol, Edit, Location, SemanticTokensLegend, TextEdit,
};
pub use manipulations::Manip;
use rootcause::option_ext::OptionExt;
use rootcause::prelude::{IteratorExt, ResultExt};
use rootcause::report;
use ropey::{Rope, RopeSlice};
+use rust_analyzer::lsp::ext::SnippetTextEdit;
use serde::{Deserialize, Serialize};
use tree_house::Language;
pub mod cursor;
@@ -358,7 +358,7 @@ impl TextArea {
text: &'b mut Rope,
) -> rootcause::Result<()> {
match insert_text_format {
- Some(lsp_types::InsertTextFormat::SNIPPET) => {
+ Some(lsp_types::InsertTextFormat::Snippet) => {
let begin = text.l_position(range.start).ok_or_report()?;
let end = text.l_position(range.end).ok_or_report()?;
text.try_remove(begin..end)?;
@@ -380,7 +380,7 @@ impl TextArea {
SnippetTextEdit { range,new_text, insert_text_format, .. }: &'b SnippetTextEdit,
) -> rootcause::Result<()> {
match insert_text_format {
- Some(lsp_types::InsertTextFormat::SNIPPET) => self
+ Some(lsp_types::InsertTextFormat::Snippet) => self
.apply_snippet(&TextEdit {
range: range.clone(),
new_text: new_text.clone(),
@@ -523,13 +523,11 @@ impl TextArea {
Some(x) => {
self.cursor.one(Cursor::new(x.r().end, &self.rope));
}
- None => {
- self.cursor.one(Cursor::new(
- x.last.clone().unwrap().r().end,
- &self.rope,
- ));
+ None if let Some(x) = &x.last => {
+ self.cursor.one(Cursor::new(x.r().end, &self.rope));
self.tabstops = None;
}
+ None => self.tabstops = None,
},
}
}
@@ -1449,12 +1447,21 @@ fn apply2() {
pub trait SortTedits {
fn sort_tedits(&mut self);
}
+impl SortTedits for [Edit] {
+ fn sort_tedits(&mut self) {
+ self.as_mut().sort_by_key(|t| match t {
+ Edit::TextEdit(t) => Reverse(t.range.start),
+ Edit::AnnotatedTextEdit(t) => Reverse(t.text_edit.range.start),
+ Edit::SnippetTextEdit(t) => Reverse(t.range.start),
+ });
+ }
+}
impl SortTedits for [TextEdit] {
fn sort_tedits(&mut self) {
self.as_mut().sort_by_key(|t| Reverse(t.range.start));
}
}
-impl SortTedits for [SnippetTextEdit] {
+impl SortTedits for [rust_analyzer::lsp::ext::SnippetTextEdit] {
fn sort_tedits(&mut self) {
self.as_mut().sort_by_key(|t| Reverse(t.range.start));
}
@@ -1462,13 +1469,13 @@ impl SortTedits for [SnippetTextEdit] {
#[test]
fn inlays() {
- use lsp_types::{InlayHint, InlayHintLabel};
+ use lsp_types::InlayHint;
let mut t = TextArea::default();
_ = t.insert("let x = 4;");
t.set_inlay(&[InlayHint {
position: lsp_types::Position { line: 0, character: 4 },
- label: InlayHintLabel::String("u".into()),
- kind: Some(lsp_types::InlayHintKind::TYPE),
+ label: lsp_types::Label::String("u".into()),
+ kind: Some(lsp_types::InlayHintKind::Type),
text_edits: None,
tooltip: None,
padding_left: None,
diff --git a/src/text/hist.rs b/src/text/hist.rs
index df678d2..05a5bcb 100644
--- a/src/text/hist.rs
+++ b/src/text/hist.rs
@@ -224,7 +224,7 @@ impl Hist {
t.cursor
.inner
.iter_mut()
- .for_each(|x| x.position = x.position.max(l));
+ .for_each(|x| x.position = x.position.min(l));
r
}
pub fn redo(&mut self, t: &mut TextArea) -> ropey::Result<Option<()>> {
diff --git a/src/text/inlay.rs b/src/text/inlay.rs
index 6712069..049aad7 100644
--- a/src/text/inlay.rs
+++ b/src/text/inlay.rs
@@ -1,5 +1,5 @@
use Default::default;
-use lsp_types::{InlayHint, InlayHintLabel, Location};
+use lsp_types::{InlayHint, Label, Location};
use serde_derive::{Deserialize, Serialize};
use crate::text::{RopeExt, TextArea};
@@ -39,9 +39,9 @@ impl TextArea {
.iter()
.filter_map(|i| {
let mut label = match &i.label {
- InlayHintLabel::String(x) =>
+ Label::String(x) =>
x.chars().map(|x| (x, None)).collect::<Vec<_>>(),
- InlayHintLabel::LabelParts(v) => v
+ Label::InlayHintLabelPartList(v) => v
.iter()
.flat_map(|x| {
x.value