updates to proxy

This commit is contained in:
Dongdong Zhou 2020-11-21 17:09:44 +00:00
parent 8d473ab51f
commit 2f06af7ce7
7 changed files with 205 additions and 19 deletions

View File

@ -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;

View File

@ -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};

View File

@ -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,

View File

@ -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"] }

View File

@ -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
}

View File

@ -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,
}));

View File

@ -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()]),
}
}