Reopen file in Copilot language server when language or URI changes
This commit is contained in:
parent
672cf6b8c7
commit
34bcf6f072
4 changed files with 64 additions and 26 deletions
|
@ -21,6 +21,7 @@ use settings::Settings;
|
||||||
use smol::{fs, io::BufReader, stream::StreamExt};
|
use smol::{fs, io::BufReader, stream::StreamExt};
|
||||||
use std::{
|
use std::{
|
||||||
ffi::OsString,
|
ffi::OsString,
|
||||||
|
mem,
|
||||||
ops::Range,
|
ops::Range,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
|
@ -148,7 +149,9 @@ impl Status {
|
||||||
|
|
||||||
struct RegisteredBuffer {
|
struct RegisteredBuffer {
|
||||||
uri: lsp::Url,
|
uri: lsp::Url,
|
||||||
snapshot: Option<(i32, BufferSnapshot)>,
|
language_id: String,
|
||||||
|
snapshot: BufferSnapshot,
|
||||||
|
snapshot_version: i32,
|
||||||
_subscriptions: [gpui::Subscription; 2],
|
_subscriptions: [gpui::Subscription; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,20 +161,15 @@ impl RegisteredBuffer {
|
||||||
buffer: &ModelHandle<Buffer>,
|
buffer: &ModelHandle<Buffer>,
|
||||||
server: &LanguageServer,
|
server: &LanguageServer,
|
||||||
cx: &AppContext,
|
cx: &AppContext,
|
||||||
) -> Result<(i32, BufferSnapshot)> {
|
) -> Result<()> {
|
||||||
let buffer = buffer.read(cx);
|
let buffer = buffer.read(cx);
|
||||||
let (version, prev_snapshot) = self
|
let new_snapshot = buffer.snapshot();
|
||||||
.snapshot
|
|
||||||
.as_ref()
|
|
||||||
.ok_or_else(|| anyhow!("expected at least one snapshot"))?;
|
|
||||||
let next_snapshot = buffer.snapshot();
|
|
||||||
|
|
||||||
let content_changes = buffer
|
let content_changes = buffer
|
||||||
.edits_since::<(PointUtf16, usize)>(prev_snapshot.version())
|
.edits_since::<(PointUtf16, usize)>(self.snapshot.version())
|
||||||
.map(|edit| {
|
.map(|edit| {
|
||||||
let edit_start = edit.new.start.0;
|
let edit_start = edit.new.start.0;
|
||||||
let edit_end = edit_start + (edit.old.end.0 - edit.old.start.0);
|
let edit_end = edit_start + (edit.old.end.0 - edit.old.start.0);
|
||||||
let new_text = next_snapshot
|
let new_text = new_snapshot
|
||||||
.text_for_range(edit.new.start.1..edit.new.end.1)
|
.text_for_range(edit.new.start.1..edit.new.end.1)
|
||||||
.collect();
|
.collect();
|
||||||
lsp::TextDocumentContentChangeEvent {
|
lsp::TextDocumentContentChangeEvent {
|
||||||
|
@ -185,24 +183,21 @@ impl RegisteredBuffer {
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if content_changes.is_empty() {
|
if !content_changes.is_empty() {
|
||||||
Ok((*version, prev_snapshot.clone()))
|
self.snapshot_version += 1;
|
||||||
} else {
|
self.snapshot = new_snapshot;
|
||||||
let next_version = version + 1;
|
|
||||||
self.snapshot = Some((next_version, next_snapshot.clone()));
|
|
||||||
|
|
||||||
server.notify::<lsp::notification::DidChangeTextDocument>(
|
server.notify::<lsp::notification::DidChangeTextDocument>(
|
||||||
lsp::DidChangeTextDocumentParams {
|
lsp::DidChangeTextDocumentParams {
|
||||||
text_document: lsp::VersionedTextDocumentIdentifier::new(
|
text_document: lsp::VersionedTextDocumentIdentifier::new(
|
||||||
self.uri.clone(),
|
self.uri.clone(),
|
||||||
next_version,
|
self.snapshot_version,
|
||||||
),
|
),
|
||||||
content_changes,
|
content_changes,
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok((next_version, next_snapshot))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,15 +510,16 @@ impl Copilot {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let uri: lsp::Url = format!("buffer://{}", buffer_id).parse().unwrap();
|
|
||||||
registered_buffers.entry(buffer.id()).or_insert_with(|| {
|
registered_buffers.entry(buffer.id()).or_insert_with(|| {
|
||||||
|
let uri: lsp::Url = uri_for_buffer(buffer, cx);
|
||||||
|
let language_id = id_for_language(buffer.read(cx).language());
|
||||||
let snapshot = buffer.read(cx).snapshot();
|
let snapshot = buffer.read(cx).snapshot();
|
||||||
server
|
server
|
||||||
.notify::<lsp::notification::DidOpenTextDocument>(
|
.notify::<lsp::notification::DidOpenTextDocument>(
|
||||||
lsp::DidOpenTextDocumentParams {
|
lsp::DidOpenTextDocumentParams {
|
||||||
text_document: lsp::TextDocumentItem {
|
text_document: lsp::TextDocumentItem {
|
||||||
uri: uri.clone(),
|
uri: uri.clone(),
|
||||||
language_id: id_for_language(buffer.read(cx).language()),
|
language_id: language_id.clone(),
|
||||||
version: 0,
|
version: 0,
|
||||||
text: snapshot.text(),
|
text: snapshot.text(),
|
||||||
},
|
},
|
||||||
|
@ -533,7 +529,9 @@ impl Copilot {
|
||||||
|
|
||||||
RegisteredBuffer {
|
RegisteredBuffer {
|
||||||
uri,
|
uri,
|
||||||
snapshot: Some((0, snapshot)),
|
language_id,
|
||||||
|
snapshot,
|
||||||
|
snapshot_version: 0,
|
||||||
_subscriptions: [
|
_subscriptions: [
|
||||||
cx.subscribe(buffer, |this, buffer, event, cx| {
|
cx.subscribe(buffer, |this, buffer, event, cx| {
|
||||||
this.handle_buffer_event(buffer, event, cx).log_err();
|
this.handle_buffer_event(buffer, event, cx).log_err();
|
||||||
|
@ -575,6 +573,31 @@ impl Copilot {
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
language::Event::FileHandleChanged | language::Event::LanguageChanged => {
|
||||||
|
let new_language_id = id_for_language(buffer.read(cx).language());
|
||||||
|
let new_uri = uri_for_buffer(&buffer, cx);
|
||||||
|
if new_uri != registered_buffer.uri
|
||||||
|
|| new_language_id != registered_buffer.language_id
|
||||||
|
{
|
||||||
|
let old_uri = mem::replace(&mut registered_buffer.uri, new_uri);
|
||||||
|
registered_buffer.language_id = new_language_id;
|
||||||
|
server.notify::<lsp::notification::DidCloseTextDocument>(
|
||||||
|
lsp::DidCloseTextDocumentParams {
|
||||||
|
text_document: lsp::TextDocumentIdentifier::new(old_uri),
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
server.notify::<lsp::notification::DidOpenTextDocument>(
|
||||||
|
lsp::DidOpenTextDocumentParams {
|
||||||
|
text_document: lsp::TextDocumentItem::new(
|
||||||
|
registered_buffer.uri.clone(),
|
||||||
|
registered_buffer.language_id.clone(),
|
||||||
|
registered_buffer.snapshot_version,
|
||||||
|
registered_buffer.snapshot.text(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -659,6 +682,10 @@ impl Copilot {
|
||||||
} => {
|
} => {
|
||||||
if matches!(status, SignInStatus::Authorized { .. }) {
|
if matches!(status, SignInStatus::Authorized { .. }) {
|
||||||
if let Some(registered_buffer) = registered_buffers.get_mut(&buffer.id()) {
|
if let Some(registered_buffer) = registered_buffers.get_mut(&buffer.id()) {
|
||||||
|
if let Err(error) = registered_buffer.report_changes(buffer, &server, cx) {
|
||||||
|
return Task::ready(Err(error));
|
||||||
|
}
|
||||||
|
|
||||||
(server.clone(), registered_buffer)
|
(server.clone(), registered_buffer)
|
||||||
} else {
|
} else {
|
||||||
return Task::ready(Err(anyhow!(
|
return Task::ready(Err(anyhow!(
|
||||||
|
@ -671,11 +698,9 @@ impl Copilot {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (version, snapshot) = match registered_buffer.report_changes(buffer, &server, cx) {
|
|
||||||
Ok((version, snapshot)) => (version, snapshot),
|
|
||||||
Err(error) => return Task::ready(Err(error)),
|
|
||||||
};
|
|
||||||
let uri = registered_buffer.uri.clone();
|
let uri = registered_buffer.uri.clone();
|
||||||
|
let snapshot = registered_buffer.snapshot.clone();
|
||||||
|
let version = registered_buffer.snapshot_version;
|
||||||
let settings = cx.global::<Settings>();
|
let settings = cx.global::<Settings>();
|
||||||
let position = position.to_point_utf16(&snapshot);
|
let position = position.to_point_utf16(&snapshot);
|
||||||
let language = snapshot.language_at(position);
|
let language = snapshot.language_at(position);
|
||||||
|
@ -784,6 +809,14 @@ fn id_for_language(language: Option<&Arc<Language>>) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn uri_for_buffer(buffer: &ModelHandle<Buffer>, cx: &AppContext) -> lsp::Url {
|
||||||
|
if let Some(file) = buffer.read(cx).file().and_then(|file| file.as_local()) {
|
||||||
|
lsp::Url::from_file_path(file.abs_path(cx)).unwrap()
|
||||||
|
} else {
|
||||||
|
format!("buffer://{}", buffer.id()).parse().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn clear_copilot_dir() {
|
async fn clear_copilot_dir() {
|
||||||
remove_matching(&paths::COPILOT_DIR, |_| true).await
|
remove_matching(&paths::COPILOT_DIR, |_| true).await
|
||||||
}
|
}
|
||||||
|
|
|
@ -6643,6 +6643,7 @@ impl Editor {
|
||||||
multi_buffer::Event::DiagnosticsUpdated => {
|
multi_buffer::Event::DiagnosticsUpdated => {
|
||||||
self.refresh_active_diagnostics(cx);
|
self.refresh_active_diagnostics(cx);
|
||||||
}
|
}
|
||||||
|
multi_buffer::Event::LanguageChanged => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ pub enum Event {
|
||||||
},
|
},
|
||||||
Edited,
|
Edited,
|
||||||
Reloaded,
|
Reloaded,
|
||||||
|
LanguageChanged,
|
||||||
Reparsed,
|
Reparsed,
|
||||||
Saved,
|
Saved,
|
||||||
FileHandleChanged,
|
FileHandleChanged,
|
||||||
|
@ -1302,6 +1303,7 @@ impl MultiBuffer {
|
||||||
language::Event::Saved => Event::Saved,
|
language::Event::Saved => Event::Saved,
|
||||||
language::Event::FileHandleChanged => Event::FileHandleChanged,
|
language::Event::FileHandleChanged => Event::FileHandleChanged,
|
||||||
language::Event::Reloaded => Event::Reloaded,
|
language::Event::Reloaded => Event::Reloaded,
|
||||||
|
language::Event::LanguageChanged => Event::LanguageChanged,
|
||||||
language::Event::Reparsed => Event::Reparsed,
|
language::Event::Reparsed => Event::Reparsed,
|
||||||
language::Event::DiagnosticsUpdated => Event::DiagnosticsUpdated,
|
language::Event::DiagnosticsUpdated => Event::DiagnosticsUpdated,
|
||||||
language::Event::Closed => Event::Closed,
|
language::Event::Closed => Event::Closed,
|
||||||
|
|
|
@ -187,6 +187,7 @@ pub enum Event {
|
||||||
Saved,
|
Saved,
|
||||||
FileHandleChanged,
|
FileHandleChanged,
|
||||||
Reloaded,
|
Reloaded,
|
||||||
|
LanguageChanged,
|
||||||
Reparsed,
|
Reparsed,
|
||||||
DiagnosticsUpdated,
|
DiagnosticsUpdated,
|
||||||
Closed,
|
Closed,
|
||||||
|
@ -536,6 +537,7 @@ impl Buffer {
|
||||||
self.syntax_map.lock().clear();
|
self.syntax_map.lock().clear();
|
||||||
self.language = language;
|
self.language = language;
|
||||||
self.reparse(cx);
|
self.reparse(cx);
|
||||||
|
cx.emit(Event::LanguageChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_language_registry(&mut self, language_registry: Arc<LanguageRegistry>) {
|
pub fn set_language_registry(&mut self, language_registry: Arc<LanguageRegistry>) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue