mirror of https://github.com/lapce/lapce.git
updates to proxy
This commit is contained in:
parent
8d473ab51f
commit
2f06af7ce7
|
@ -536,6 +536,12 @@ fn apply_delta(
|
|||
self.rev,
|
||||
);
|
||||
state.lsp.lock().update(&self, &content_change, self.rev);
|
||||
state
|
||||
.proxy
|
||||
.lock()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.update(self.id, delta, self.rev);
|
||||
|
||||
let logical_start_line = self.rope.line_of_offset(iv.start);
|
||||
let new_logical_end_line = self.rope.line_of_offset(iv.start + newlen) + 1;
|
||||
|
|
|
@ -23,20 +23,7 @@
|
|||
};
|
||||
use xi_rope::RopeDelta;
|
||||
|
||||
use lsp_types::{
|
||||
ClientCapabilities, CodeActionCapability, CodeActionContext, CodeActionKind,
|
||||
CodeActionKindLiteralSupport, CodeActionLiteralSupport, CodeActionParams,
|
||||
CodeActionResponse, CompletionCapability, CompletionItemCapability,
|
||||
CompletionParams, DidChangeTextDocumentParams, DidOpenTextDocumentParams,
|
||||
DidSaveTextDocumentParams, DocumentFormattingParams, DocumentSymbolParams,
|
||||
DocumentSymbolResponse, FormattingOptions, GotoDefinitionParams,
|
||||
InitializeParams, InitializeResult, PartialResultParams, Position,
|
||||
PublishDiagnosticsParams, Range, SemanticTokensParams, ServerCapabilities,
|
||||
TextDocumentClientCapabilities, TextDocumentContentChangeEvent,
|
||||
TextDocumentIdentifier, TextDocumentItem, TextDocumentPositionParams,
|
||||
TextDocumentSyncCapability, TextDocumentSyncKind, TextEdit, TraceOption, Url,
|
||||
VersionedTextDocumentIdentifier, WorkDoneProgressParams,
|
||||
};
|
||||
use lsp_types::*;
|
||||
use serde_json::{json, to_value, Value};
|
||||
|
||||
use crate::buffer::{Buffer, BufferId};
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use serde_json::json;
|
||||
use serde_json::Value;
|
||||
use xi_rope::RopeDelta;
|
||||
use xi_rpc::Callback;
|
||||
use xi_rpc::Handler;
|
||||
use xi_rpc::RpcLoop;
|
||||
|
@ -50,6 +51,17 @@ pub fn new_buffer(&self, buffer_id: BufferId, path: PathBuf) -> Result<String> {
|
|||
return Ok(resp.content);
|
||||
}
|
||||
|
||||
pub fn update(&self, buffer_id: BufferId, delta: &RopeDelta, rev: u64) {
|
||||
self.peer.send_rpc_notification(
|
||||
"update",
|
||||
&json!({
|
||||
"buffer_id": buffer_id,
|
||||
"delta": delta,
|
||||
"rev": rev,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_completion(
|
||||
&self,
|
||||
request_id: usize,
|
||||
|
|
|
@ -7,7 +7,7 @@ edition = "2018"
|
|||
[dependencies]
|
||||
lapce-rpc = { path = "../rpc" }
|
||||
xi-rpc = { path = "../../xi-editor/rust/rpc/" }
|
||||
xi-rope = { path = "../../xi-editor/rust/rope/" }
|
||||
xi-rope = { path = "../../xi-editor/rust/rope/", features = ["serde"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
lsp-types = { version = "0.82.0", features = ["proposed"] }
|
||||
parking_lot = { version = "0.11.0", features = ["deadlock_detection"] }
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use lsp_types::*;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
use xi_rope::{
|
||||
interval::IntervalBounds, rope::Rope, Cursor, Delta, DeltaBuilder, Interval,
|
||||
|
@ -17,6 +18,7 @@ pub struct Buffer {
|
|||
pub id: BufferId,
|
||||
pub rope: Rope,
|
||||
pub path: PathBuf,
|
||||
pub rev: u64,
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
|
@ -32,12 +34,56 @@ pub fn new(id: BufferId, path: PathBuf) -> Buffer {
|
|||
rope,
|
||||
path,
|
||||
language_id,
|
||||
rev: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
delta: &RopeDelta,
|
||||
rev: u64,
|
||||
) -> Option<TextDocumentContentChangeEvent> {
|
||||
if self.rev + 1 != rev {
|
||||
return None;
|
||||
}
|
||||
self.rev += 1;
|
||||
let content_change = get_document_content_changes(delta, self);
|
||||
self.rope = delta.apply(&self.rope);
|
||||
let content_change = match content_change {
|
||||
Some(content_change) => content_change,
|
||||
None => TextDocumentContentChangeEvent {
|
||||
range: None,
|
||||
range_length: None,
|
||||
text: self.get_document(),
|
||||
},
|
||||
};
|
||||
Some(content_change)
|
||||
}
|
||||
|
||||
pub fn get_document(&self) -> String {
|
||||
self.rope.to_string()
|
||||
}
|
||||
|
||||
pub fn offset_of_line(&self, offset: usize) -> usize {
|
||||
self.rope.offset_of_line(offset)
|
||||
}
|
||||
|
||||
pub fn line_of_offset(&self, offset: usize) -> usize {
|
||||
self.rope.line_of_offset(offset)
|
||||
}
|
||||
|
||||
pub fn offset_to_line_col(&self, offset: usize) -> (usize, usize) {
|
||||
let line = self.line_of_offset(offset);
|
||||
(line, offset - self.offset_of_line(line))
|
||||
}
|
||||
|
||||
pub fn offset_to_position(&self, offset: usize) -> Position {
|
||||
let (line, col) = self.offset_to_line_col(offset);
|
||||
Position {
|
||||
line: line as u64,
|
||||
character: col as u64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn load_file(path: &PathBuf) -> Result<Rope> {
|
||||
|
@ -54,3 +100,45 @@ fn language_id_from_path(path: &PathBuf) -> Option<&str> {
|
|||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_document_content_changes(
|
||||
delta: &RopeDelta,
|
||||
buffer: &Buffer,
|
||||
) -> Option<TextDocumentContentChangeEvent> {
|
||||
let (interval, _) = delta.summary();
|
||||
let (start, end) = interval.start_end();
|
||||
|
||||
// TODO: Handle more trivial cases like typing when there's a selection or transpose
|
||||
if let Some(node) = delta.as_simple_insert() {
|
||||
let text = String::from(node);
|
||||
|
||||
let (start, end) = interval.start_end();
|
||||
let text_document_content_change_event = TextDocumentContentChangeEvent {
|
||||
range: Some(Range {
|
||||
start: buffer.offset_to_position(start),
|
||||
end: buffer.offset_to_position(end),
|
||||
}),
|
||||
range_length: Some((end - start) as u64),
|
||||
text,
|
||||
};
|
||||
|
||||
return Some(text_document_content_change_event);
|
||||
}
|
||||
// Or a simple delete
|
||||
else if delta.is_simple_delete() {
|
||||
let mut end_position = buffer.offset_to_position(end);
|
||||
|
||||
let text_document_content_change_event = TextDocumentContentChangeEvent {
|
||||
range: Some(Range {
|
||||
start: buffer.offset_to_position(start),
|
||||
end: end_position,
|
||||
}),
|
||||
range_length: Some((end - start) as u64),
|
||||
text: String::new(),
|
||||
};
|
||||
|
||||
return Some(text_document_content_change_event);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::{collections::HashMap, io};
|
||||
use xi_rope::{RopeDelta, RopeInfo};
|
||||
use xi_rpc::RpcPeer;
|
||||
use xi_rpc::{Handler, RpcCtx};
|
||||
|
||||
|
@ -32,7 +33,14 @@ pub struct Dispatcher {
|
|||
#[serde(rename_all = "snake_case")]
|
||||
#[serde(tag = "method", content = "params")]
|
||||
pub enum Notification {
|
||||
Initialize { workspace: PathBuf },
|
||||
Initialize {
|
||||
workspace: PathBuf,
|
||||
},
|
||||
Update {
|
||||
buffer_id: BufferId,
|
||||
delta: RopeDelta,
|
||||
rev: u64,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
@ -73,7 +81,6 @@ pub fn new(sender: Sender<Value>) -> Dispatcher {
|
|||
|
||||
pub fn mainloop(&self, receiver: Receiver<Value>) -> Result<()> {
|
||||
for msg in receiver {
|
||||
eprintln!("receive msg {}", msg);
|
||||
let rpc: RpcObject = msg.into();
|
||||
if rpc.is_response() {
|
||||
} else {
|
||||
|
@ -119,6 +126,17 @@ fn handle_notification(&self, rpc: Notification) {
|
|||
Notification::Initialize { workspace } => {
|
||||
*self.workspace.lock() = workspace;
|
||||
}
|
||||
Notification::Update {
|
||||
buffer_id,
|
||||
delta,
|
||||
rev,
|
||||
} => {
|
||||
let mut buffers = self.buffers.lock();
|
||||
let buffer = buffers.get_mut(&buffer_id).unwrap();
|
||||
if let Some(content_change) = buffer.update(&delta, rev) {
|
||||
self.lsp.lock().update(buffer, &content_change, buffer.rev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,9 +147,7 @@ fn handle_request(&self, id: RequestId, rpc: Request) {
|
|||
let content = buffer.rope.to_string();
|
||||
self.buffers.lock().insert(buffer_id, buffer);
|
||||
let resp = NewBufferResponse { content };
|
||||
eprintln!("proxy receive new buffer");
|
||||
self.sender.send(json!({
|
||||
"jsonrpc": "2.0",
|
||||
"id": id,
|
||||
"result": resp,
|
||||
}));
|
||||
|
|
|
@ -121,6 +121,17 @@ pub fn get_completion(
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&self,
|
||||
buffer: &Buffer,
|
||||
content_change: &TextDocumentContentChangeEvent,
|
||||
rev: u64,
|
||||
) {
|
||||
if let Some(client) = self.clients.get(&buffer.language_id) {
|
||||
client.update(buffer, content_change, rev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LspClient {
|
||||
|
@ -481,6 +492,52 @@ pub fn get_completion(
|
|||
// }
|
||||
})
|
||||
}
|
||||
|
||||
pub fn send_did_change(
|
||||
&self,
|
||||
buffer: &Buffer,
|
||||
changes: Vec<TextDocumentContentChangeEvent>,
|
||||
version: u64,
|
||||
) {
|
||||
let uri = self.get_uri(buffer);
|
||||
let text_document_did_change_params = DidChangeTextDocumentParams {
|
||||
text_document: VersionedTextDocumentIdentifier {
|
||||
uri,
|
||||
version: Some(version as i64),
|
||||
},
|
||||
content_changes: changes,
|
||||
};
|
||||
|
||||
let params = Params::from(
|
||||
serde_json::to_value(text_document_did_change_params).unwrap(),
|
||||
);
|
||||
self.send_notification("textDocument/didChange", params);
|
||||
}
|
||||
|
||||
pub fn get_sync_kind(&self) -> Option<TextDocumentSyncKind> {
|
||||
let state = self.state.lock();
|
||||
let text_document_sync = state
|
||||
.server_capabilities
|
||||
.as_ref()
|
||||
.and_then(|c| c.text_document_sync.as_ref())?;
|
||||
match &text_document_sync {
|
||||
&TextDocumentSyncCapability::Kind(kind) => Some(kind.clone()),
|
||||
&TextDocumentSyncCapability::Options(options) => options.clone().change,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&self,
|
||||
buffer: &Buffer,
|
||||
content_change: &TextDocumentContentChangeEvent,
|
||||
rev: u64,
|
||||
) {
|
||||
let sync_kind = self.get_sync_kind().unwrap_or(TextDocumentSyncKind::Full);
|
||||
let changes = get_change_for_sync_kind(sync_kind, buffer, content_change);
|
||||
if let Some(changes) = changes {
|
||||
self.send_did_change(buffer, changes, rev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum LspHeader {
|
||||
|
@ -550,3 +607,23 @@ pub fn read_message<T: BufRead>(reader: &mut T) -> Result<String> {
|
|||
let body = String::from_utf8(body_buffer)?;
|
||||
Ok(body)
|
||||
}
|
||||
|
||||
pub fn get_change_for_sync_kind(
|
||||
sync_kind: TextDocumentSyncKind,
|
||||
buffer: &Buffer,
|
||||
content_change: &TextDocumentContentChangeEvent,
|
||||
) -> Option<Vec<TextDocumentContentChangeEvent>> {
|
||||
match sync_kind {
|
||||
TextDocumentSyncKind::None => None,
|
||||
TextDocumentSyncKind::Full => {
|
||||
let text_document_content_change_event =
|
||||
TextDocumentContentChangeEvent {
|
||||
range: None,
|
||||
range_length: None,
|
||||
text: buffer.get_document(),
|
||||
};
|
||||
Some(vec![text_document_content_change_event])
|
||||
}
|
||||
TextDocumentSyncKind::Incremental => Some(vec![content_change.clone()]),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue