Improve obvious faults

This commit is contained in:
Kirill Bulatov 2023-05-31 21:11:24 +03:00
parent 79b97f9e75
commit 7a268b1cf6
3 changed files with 106 additions and 71 deletions

View file

@ -1178,6 +1178,7 @@ impl InlayHintState {
pub fn update_if_newer(&self, new_hints: Vec<InlayHint>, new_timestamp: usize) { pub fn update_if_newer(&self, new_hints: Vec<InlayHint>, new_timestamp: usize) {
let last_updated_timestamp = self.last_updated_timestamp.load(atomic::Ordering::Acquire); let last_updated_timestamp = self.last_updated_timestamp.load(atomic::Ordering::Acquire);
dbg!(last_updated_timestamp, new_timestamp, new_hints.len());
if last_updated_timestamp < new_timestamp { if last_updated_timestamp < new_timestamp {
let mut guard = self.hints.write(); let mut guard = self.hints.write();
match self.last_updated_timestamp.compare_exchange( match self.last_updated_timestamp.compare_exchange(
@ -1330,12 +1331,22 @@ impl Editor {
let soft_wrap_mode_override = let soft_wrap_mode_override =
(mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None); (mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None);
let mut project_subscription = None; let mut project_subscriptions = Vec::new();
if mode == EditorMode::Full && buffer.read(cx).is_singleton() { if mode == EditorMode::Full && buffer.read(cx).is_singleton() {
if let Some(project) = project.as_ref() { if let Some(project) = project.as_ref() {
project_subscription = Some(cx.observe(project, |_, _, cx| { project_subscriptions.push(cx.observe(project, |_, _, cx| {
cx.emit(Event::TitleChanged); cx.emit(Event::TitleChanged);
})) }));
project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
match event {
project::Event::LanguageServerReady(_) => {
dbg!("@@@@@@@@@@@@@ ReceiveD event");
editor.update_inlay_hints(cx);
}
_ => {}
};
cx.notify()
}));
} }
} }
@ -1399,9 +1410,7 @@ impl Editor {
], ],
}; };
if let Some(project_subscription) = project_subscription { this._subscriptions.extend(project_subscriptions);
this._subscriptions.push(project_subscription);
}
this.end_selection(cx); this.end_selection(cx);
this.scroll_manager.show_scrollbar(cx); this.scroll_manager.show_scrollbar(cx);
@ -1415,8 +1424,6 @@ impl Editor {
} }
this.report_editor_event("open", None, cx); this.report_editor_event("open", None, cx);
// this.update_inlay_hints(cx);
this this
} }
@ -2644,14 +2651,12 @@ impl Editor {
// This way we can reuse tasks result for the same timestamp? The counter has to be global among all buffer changes & other reloads. // This way we can reuse tasks result for the same timestamp? The counter has to be global among all buffer changes & other reloads.
let new_timestamp = self.inlay_hints.new_timestamp(); let new_timestamp = self.inlay_hints.new_timestamp();
// TODO kb this would not work until the language server is ready, how to wait for it?
// TODO kb waiting before the server starts and handling workspace/inlayHint/refresh commands is kind of orthogonal? // TODO kb waiting before the server starts and handling workspace/inlayHint/refresh commands is kind of orthogonal?
// need to be able to not to start new tasks, if current one is running on the same state already. // need to be able to not to start new tasks, if current one is running on the same state already.
cx.spawn(|editor, mut cx| async move { cx.spawn(|editor, mut cx| async move {
let task = editor.update(&mut cx, |editor, cx| { let task = editor.update(&mut cx, |editor, cx| {
editor.project.as_ref().map(|project| { editor.project.as_ref().map(|project| {
project.update(cx, |project, cx| { project.update(cx, |project, cx| {
// TODO kb use visible_lines as a range instead?
let end = generator_buffer.read(cx).len(); let end = generator_buffer.read(cx).len();
project.inlay_hints(generator_buffer, 0..end, cx) project.inlay_hints(generator_buffer, 0..end, cx)
}) })
@ -6707,10 +6712,7 @@ impl Editor {
) -> Option<TransactionId> { ) -> Option<TransactionId> {
self.start_transaction_at(Instant::now(), cx); self.start_transaction_at(Instant::now(), cx);
update(self, cx); update(self, cx);
let transaction_id = self.end_transaction_at(Instant::now(), cx); self.end_transaction_at(Instant::now(), cx)
// TODO kb is this the right idea? Maybe instead we should react on `BufferEvent::Edited`?
self.update_inlay_hints(cx);
transaction_id
} }
fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) { fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
@ -7190,7 +7192,7 @@ impl Editor {
event: &multi_buffer::Event, event: &multi_buffer::Event,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) { ) {
match event { let update_inlay_hints = match event {
multi_buffer::Event::Edited => { multi_buffer::Event::Edited => {
self.refresh_active_diagnostics(cx); self.refresh_active_diagnostics(cx);
self.refresh_code_actions(cx); self.refresh_code_actions(cx);
@ -7198,30 +7200,62 @@ impl Editor {
self.update_visible_copilot_suggestion(cx); self.update_visible_copilot_suggestion(cx);
} }
cx.emit(Event::BufferEdited); cx.emit(Event::BufferEdited);
true
} }
multi_buffer::Event::ExcerptsAdded { multi_buffer::Event::ExcerptsAdded {
buffer, buffer,
predecessor, predecessor,
excerpts, excerpts,
} => cx.emit(Event::ExcerptsAdded { } => {
buffer: buffer.clone(), cx.emit(Event::ExcerptsAdded {
predecessor: *predecessor, buffer: buffer.clone(),
excerpts: excerpts.clone(), predecessor: *predecessor,
}), excerpts: excerpts.clone(),
multi_buffer::Event::ExcerptsRemoved { ids } => { });
cx.emit(Event::ExcerptsRemoved { ids: ids.clone() }) // TODO kb wrong?
false
}
multi_buffer::Event::ExcerptsRemoved { ids } => {
cx.emit(Event::ExcerptsRemoved { ids: ids.clone() });
false
}
multi_buffer::Event::Reparsed => {
cx.emit(Event::Reparsed);
true
}
multi_buffer::Event::DirtyChanged => {
cx.emit(Event::DirtyChanged);
true
}
multi_buffer::Event::Saved => {
cx.emit(Event::Saved);
false
}
multi_buffer::Event::FileHandleChanged => {
cx.emit(Event::TitleChanged);
true
}
multi_buffer::Event::Reloaded => {
cx.emit(Event::TitleChanged);
true
}
multi_buffer::Event::DiffBaseChanged => {
cx.emit(Event::DiffBaseChanged);
true
}
multi_buffer::Event::Closed => {
cx.emit(Event::Closed);
false
} }
multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
multi_buffer::Event::Saved => cx.emit(Event::Saved),
multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
multi_buffer::Event::Closed => cx.emit(Event::Closed),
multi_buffer::Event::DiagnosticsUpdated => { multi_buffer::Event::DiagnosticsUpdated => {
self.refresh_active_diagnostics(cx); self.refresh_active_diagnostics(cx);
false
} }
_ => {} _ => true,
};
if update_inlay_hints {
self.update_inlay_hints(cx);
} }
} }

View file

@ -1819,9 +1819,9 @@ impl LineWithInvisibles {
cx, cx,
); );
// TODO kb bad: cloning happens very frequently, check the timestamp first // TODO kb bad: syscalls + cloning happen very frequently, check the timestamp first
let new_hints = editor.inlay_hints.read(); let new_hints = editor.inlay_hints.read();
// dbg!(new_hints); dbg!(new_hints.last());
self.draw_invisibles( self.draw_invisibles(
&selection_ranges, &selection_ranges,

View file

@ -254,6 +254,7 @@ pub enum Event {
LanguageServerAdded(LanguageServerId), LanguageServerAdded(LanguageServerId),
LanguageServerRemoved(LanguageServerId), LanguageServerRemoved(LanguageServerId),
LanguageServerLog(LanguageServerId, String), LanguageServerLog(LanguageServerId, String),
LanguageServerReady(LanguageServerId),
Notification(String), Notification(String),
ActiveEntryChanged(Option<ProjectEntryId>), ActiveEntryChanged(Option<ProjectEntryId>),
WorktreeAdded, WorktreeAdded,
@ -2814,15 +2815,18 @@ impl Project {
.on_request::<lsp::request::InlayHintRefreshRequest, _, _>({ .on_request::<lsp::request::InlayHintRefreshRequest, _, _>({
dbg!("!!!!!!!!!!!!!!"); dbg!("!!!!!!!!!!!!!!");
let this = this.downgrade(); let this = this.downgrade();
move |params, cx| async move { move |params, mut cx| async move {
// TODO kb: trigger an event, to call on every open editor
// TODO kb does not get called now, why? // TODO kb does not get called now, why?
dbg!("@@@@@@@@@@@@@@@@@@@@@@@@@@"); dbg!("#########################");
let _this = this let this = this
.upgrade(&cx) .upgrade(&cx)
.ok_or_else(|| anyhow!("project dropped"))?; .ok_or_else(|| anyhow!("project dropped"))?;
dbg!(params); dbg!(params);
this.update(&mut cx, |_, cx| {
dbg!("@@@@@@@@@@@@@ SENT event");
cx.emit(Event::LanguageServerReady(server_id));
});
Ok(()) Ok(())
} }
}) })
@ -5477,41 +5481,39 @@ impl Project {
let abs_path = worktree_handle.read(cx).abs_path(); let abs_path = worktree_handle.read(cx).abs_path();
for server_id in &language_server_ids { for server_id in &language_server_ids {
if let Some(server) = self.language_servers.get(server_id) { if let Some(LanguageServerState::Running {
if let LanguageServerState::Running { server,
server, watched_paths,
watched_paths, ..
.. }) = self.language_servers.get(server_id)
} = server {
{ if let Some(watched_paths) = watched_paths.get(&worktree_id) {
if let Some(watched_paths) = watched_paths.get(&worktree_id) { let params = lsp::DidChangeWatchedFilesParams {
let params = lsp::DidChangeWatchedFilesParams { changes: changes
changes: changes .iter()
.iter() .filter_map(|(path, _, change)| {
.filter_map(|(path, _, change)| { if !watched_paths.is_match(&path) {
if !watched_paths.is_match(&path) { return None;
return None; }
} let typ = match change {
let typ = match change { PathChange::Loaded => return None,
PathChange::Loaded => return None, PathChange::Added => lsp::FileChangeType::CREATED,
PathChange::Added => lsp::FileChangeType::CREATED, PathChange::Removed => lsp::FileChangeType::DELETED,
PathChange::Removed => lsp::FileChangeType::DELETED, PathChange::Updated => lsp::FileChangeType::CHANGED,
PathChange::Updated => lsp::FileChangeType::CHANGED, PathChange::AddedOrUpdated => lsp::FileChangeType::CHANGED,
PathChange::AddedOrUpdated => lsp::FileChangeType::CHANGED, };
}; Some(lsp::FileEvent {
Some(lsp::FileEvent { uri: lsp::Url::from_file_path(abs_path.join(path)).unwrap(),
uri: lsp::Url::from_file_path(abs_path.join(path)).unwrap(), typ,
typ,
})
}) })
.collect(), })
}; .collect(),
};
if !params.changes.is_empty() { if !params.changes.is_empty() {
server server
.notify::<lsp::notification::DidChangeWatchedFiles>(params) .notify::<lsp::notification::DidChangeWatchedFiles>(params)
.log_err(); .log_err();
}
} }
} }
} }
@ -7385,10 +7387,9 @@ impl Project {
self.language_server_ids_for_buffer(buffer, cx) self.language_server_ids_for_buffer(buffer, cx)
.into_iter() .into_iter()
.filter_map(|server_id| { .filter_map(|server_id| {
let server = self.language_servers.get(&server_id)?;
if let LanguageServerState::Running { if let LanguageServerState::Running {
adapter, server, .. adapter, server, ..
} = server } = self.language_servers.get(&server_id)?
{ {
Some((adapter, server)) Some((adapter, server))
} else { } else {