Further improve color inlay hints in multi buffers (#33642)
Follow-up of https://github.com/zed-industries/zed/pull/33605 Release Notes: - N/A
This commit is contained in:
parent
ac3328adb6
commit
ae6237178c
7 changed files with 230 additions and 128 deletions
|
@ -37,7 +37,9 @@ pub use block_map::{
|
||||||
use block_map::{BlockRow, BlockSnapshot};
|
use block_map::{BlockRow, BlockSnapshot};
|
||||||
use collections::{HashMap, HashSet};
|
use collections::{HashMap, HashSet};
|
||||||
pub use crease_map::*;
|
pub use crease_map::*;
|
||||||
pub use fold_map::{ChunkRenderer, ChunkRendererContext, Fold, FoldId, FoldPlaceholder, FoldPoint};
|
pub use fold_map::{
|
||||||
|
ChunkRenderer, ChunkRendererContext, ChunkRendererId, Fold, FoldId, FoldPlaceholder, FoldPoint,
|
||||||
|
};
|
||||||
use fold_map::{FoldMap, FoldSnapshot};
|
use fold_map::{FoldMap, FoldSnapshot};
|
||||||
use gpui::{App, Context, Entity, Font, HighlightStyle, LineLayout, Pixels, UnderlineStyle};
|
use gpui::{App, Context, Entity, Font, HighlightStyle, LineLayout, Pixels, UnderlineStyle};
|
||||||
pub use inlay_map::Inlay;
|
pub use inlay_map::Inlay;
|
||||||
|
@ -538,7 +540,7 @@ impl DisplayMap {
|
||||||
|
|
||||||
pub fn update_fold_widths(
|
pub fn update_fold_widths(
|
||||||
&mut self,
|
&mut self,
|
||||||
widths: impl IntoIterator<Item = (FoldId, Pixels)>,
|
widths: impl IntoIterator<Item = (ChunkRendererId, Pixels)>,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let snapshot = self.buffer.read(cx).snapshot(cx);
|
let snapshot = self.buffer.read(cx).snapshot(cx);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::display_map::inlay_map::InlayChunk;
|
use crate::{InlayId, display_map::inlay_map::InlayChunk};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
Highlights,
|
Highlights,
|
||||||
|
@ -277,13 +277,16 @@ impl FoldMapWriter<'_> {
|
||||||
|
|
||||||
pub(crate) fn update_fold_widths(
|
pub(crate) fn update_fold_widths(
|
||||||
&mut self,
|
&mut self,
|
||||||
new_widths: impl IntoIterator<Item = (FoldId, Pixels)>,
|
new_widths: impl IntoIterator<Item = (ChunkRendererId, Pixels)>,
|
||||||
) -> (FoldSnapshot, Vec<FoldEdit>) {
|
) -> (FoldSnapshot, Vec<FoldEdit>) {
|
||||||
let mut edits = Vec::new();
|
let mut edits = Vec::new();
|
||||||
let inlay_snapshot = self.0.snapshot.inlay_snapshot.clone();
|
let inlay_snapshot = self.0.snapshot.inlay_snapshot.clone();
|
||||||
let buffer = &inlay_snapshot.buffer;
|
let buffer = &inlay_snapshot.buffer;
|
||||||
|
|
||||||
for (id, new_width) in new_widths {
|
for (id, new_width) in new_widths {
|
||||||
|
let ChunkRendererId::Fold(id) = id else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
if let Some(metadata) = self.0.snapshot.fold_metadata_by_id.get(&id).cloned() {
|
if let Some(metadata) = self.0.snapshot.fold_metadata_by_id.get(&id).cloned() {
|
||||||
if Some(new_width) != metadata.width {
|
if Some(new_width) != metadata.width {
|
||||||
let buffer_start = metadata.range.start.to_offset(buffer);
|
let buffer_start = metadata.range.start.to_offset(buffer);
|
||||||
|
@ -529,7 +532,7 @@ impl FoldMap {
|
||||||
placeholder: Some(TransformPlaceholder {
|
placeholder: Some(TransformPlaceholder {
|
||||||
text: ELLIPSIS,
|
text: ELLIPSIS,
|
||||||
renderer: ChunkRenderer {
|
renderer: ChunkRenderer {
|
||||||
id: fold.id,
|
id: ChunkRendererId::Fold(fold.id),
|
||||||
render: Arc::new(move |cx| {
|
render: Arc::new(move |cx| {
|
||||||
(fold.placeholder.render)(
|
(fold.placeholder.render)(
|
||||||
fold_id,
|
fold_id,
|
||||||
|
@ -1267,11 +1270,17 @@ pub struct Chunk<'a> {
|
||||||
pub renderer: Option<ChunkRenderer>,
|
pub renderer: Option<ChunkRenderer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub enum ChunkRendererId {
|
||||||
|
Fold(FoldId),
|
||||||
|
Inlay(InlayId),
|
||||||
|
}
|
||||||
|
|
||||||
/// A recipe for how the chunk should be presented.
|
/// A recipe for how the chunk should be presented.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ChunkRenderer {
|
pub struct ChunkRenderer {
|
||||||
/// The id of the fold associated with this chunk.
|
/// The id of the renderer associated with this chunk.
|
||||||
pub id: FoldId,
|
pub id: ChunkRendererId,
|
||||||
/// Creates a custom element to represent this chunk.
|
/// Creates a custom element to represent this chunk.
|
||||||
pub render: Arc<dyn Send + Sync + Fn(&mut ChunkRendererContext) -> AnyElement>,
|
pub render: Arc<dyn Send + Sync + Fn(&mut ChunkRendererContext) -> AnyElement>,
|
||||||
/// If true, the element is constrained to the shaped width of the text.
|
/// If true, the element is constrained to the shaped width of the text.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{ChunkRenderer, HighlightStyles, InlayId, display_map::FoldId};
|
use crate::{ChunkRenderer, HighlightStyles, InlayId};
|
||||||
use collections::BTreeSet;
|
use collections::BTreeSet;
|
||||||
use gpui::{Hsla, Rgba};
|
use gpui::{Hsla, Rgba};
|
||||||
use language::{Chunk, Edit, Point, TextSummary};
|
use language::{Chunk, Edit, Point, TextSummary};
|
||||||
|
@ -14,7 +14,7 @@ use sum_tree::{Bias, Cursor, SumTree};
|
||||||
use text::{Patch, Rope};
|
use text::{Patch, Rope};
|
||||||
use ui::{ActiveTheme, IntoElement as _, ParentElement as _, Styled as _, div};
|
use ui::{ActiveTheme, IntoElement as _, ParentElement as _, Styled as _, div};
|
||||||
|
|
||||||
use super::{Highlights, custom_highlights::CustomHighlightsChunks};
|
use super::{Highlights, custom_highlights::CustomHighlightsChunks, fold_map::ChunkRendererId};
|
||||||
|
|
||||||
/// Decides where the [`Inlay`]s should be displayed.
|
/// Decides where the [`Inlay`]s should be displayed.
|
||||||
///
|
///
|
||||||
|
@ -338,10 +338,10 @@ impl<'a> Iterator for InlayChunks<'a> {
|
||||||
}
|
}
|
||||||
InlayId::Hint(_) => self.highlight_styles.inlay_hint,
|
InlayId::Hint(_) => self.highlight_styles.inlay_hint,
|
||||||
InlayId::DebuggerValue(_) => self.highlight_styles.inlay_hint,
|
InlayId::DebuggerValue(_) => self.highlight_styles.inlay_hint,
|
||||||
InlayId::Color(id) => {
|
InlayId::Color(_) => {
|
||||||
if let Some(color) = inlay.color {
|
if let Some(color) = inlay.color {
|
||||||
renderer = Some(ChunkRenderer {
|
renderer = Some(ChunkRenderer {
|
||||||
id: FoldId(id),
|
id: ChunkRendererId::Inlay(inlay.id),
|
||||||
render: Arc::new(move |cx| {
|
render: Arc::new(move |cx| {
|
||||||
div()
|
div()
|
||||||
.w_4()
|
.w_4()
|
||||||
|
|
|
@ -17333,9 +17333,9 @@ impl Editor {
|
||||||
self.active_indent_guides_state.dirty = true;
|
self.active_indent_guides_state.dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_fold_widths(
|
pub fn update_renderer_widths(
|
||||||
&mut self,
|
&mut self,
|
||||||
widths: impl IntoIterator<Item = (FoldId, Pixels)>,
|
widths: impl IntoIterator<Item = (ChunkRendererId, Pixels)>,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
self.display_map
|
self.display_map
|
||||||
|
|
|
@ -12,8 +12,8 @@ use crate::{
|
||||||
ToggleFold,
|
ToggleFold,
|
||||||
code_context_menus::{CodeActionsMenu, MENU_ASIDE_MAX_WIDTH, MENU_ASIDE_MIN_WIDTH, MENU_GAP},
|
code_context_menus::{CodeActionsMenu, MENU_ASIDE_MAX_WIDTH, MENU_ASIDE_MIN_WIDTH, MENU_GAP},
|
||||||
display_map::{
|
display_map::{
|
||||||
Block, BlockContext, BlockStyle, DisplaySnapshot, EditorMargins, FoldId, HighlightKey,
|
Block, BlockContext, BlockStyle, ChunkRendererId, DisplaySnapshot, EditorMargins,
|
||||||
HighlightedChunk, ToDisplayPoint,
|
HighlightKey, HighlightedChunk, ToDisplayPoint,
|
||||||
},
|
},
|
||||||
editor_settings::{
|
editor_settings::{
|
||||||
CurrentLineHighlight, DocumentColorsRenderMode, DoubleClickInMultibuffer, Minimap,
|
CurrentLineHighlight, DocumentColorsRenderMode, DoubleClickInMultibuffer, Minimap,
|
||||||
|
@ -7119,7 +7119,7 @@ pub(crate) struct LineWithInvisibles {
|
||||||
enum LineFragment {
|
enum LineFragment {
|
||||||
Text(ShapedLine),
|
Text(ShapedLine),
|
||||||
Element {
|
Element {
|
||||||
id: FoldId,
|
id: ChunkRendererId,
|
||||||
element: Option<AnyElement>,
|
element: Option<AnyElement>,
|
||||||
size: Size<Pixels>,
|
size: Size<Pixels>,
|
||||||
len: usize,
|
len: usize,
|
||||||
|
@ -8297,7 +8297,7 @@ impl Element for EditorElement {
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
let new_fold_widths = line_layouts
|
let new_renrerer_widths = line_layouts
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|layout| &layout.fragments)
|
.flat_map(|layout| &layout.fragments)
|
||||||
.filter_map(|fragment| {
|
.filter_map(|fragment| {
|
||||||
|
@ -8308,7 +8308,7 @@ impl Element for EditorElement {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if self.editor.update(cx, |editor, cx| {
|
if self.editor.update(cx, |editor, cx| {
|
||||||
editor.update_fold_widths(new_fold_widths, cx)
|
editor.update_renderer_widths(new_renrerer_widths, cx)
|
||||||
}) {
|
}) {
|
||||||
// If the fold widths have changed, we need to prepaint
|
// If the fold widths have changed, we need to prepaint
|
||||||
// the element again to account for any changes in
|
// the element again to account for any changes in
|
||||||
|
|
|
@ -19,18 +19,21 @@ use crate::{
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct LspColorData {
|
pub(super) struct LspColorData {
|
||||||
cache_version_used: usize,
|
buffer_colors: HashMap<BufferId, BufferColors>,
|
||||||
|
render_mode: DocumentColorsRenderMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
struct BufferColors {
|
||||||
colors: Vec<(Range<Anchor>, DocumentColor, InlayId)>,
|
colors: Vec<(Range<Anchor>, DocumentColor, InlayId)>,
|
||||||
inlay_colors: HashMap<InlayId, usize>,
|
inlay_colors: HashMap<InlayId, usize>,
|
||||||
render_mode: DocumentColorsRenderMode,
|
cache_version_used: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LspColorData {
|
impl LspColorData {
|
||||||
pub fn new(cx: &App) -> Self {
|
pub fn new(cx: &App) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cache_version_used: 0,
|
buffer_colors: HashMap::default(),
|
||||||
colors: Vec::new(),
|
|
||||||
inlay_colors: HashMap::default(),
|
|
||||||
render_mode: EditorSettings::get_global(cx).lsp_document_colors,
|
render_mode: EditorSettings::get_global(cx).lsp_document_colors,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,8 +50,9 @@ impl LspColorData {
|
||||||
DocumentColorsRenderMode::Inlay => Some(InlaySplice {
|
DocumentColorsRenderMode::Inlay => Some(InlaySplice {
|
||||||
to_remove: Vec::new(),
|
to_remove: Vec::new(),
|
||||||
to_insert: self
|
to_insert: self
|
||||||
.colors
|
.buffer_colors
|
||||||
.iter()
|
.iter()
|
||||||
|
.flat_map(|(_, buffer_colors)| buffer_colors.colors.iter())
|
||||||
.map(|(range, color, id)| {
|
.map(|(range, color, id)| {
|
||||||
Inlay::color(
|
Inlay::color(
|
||||||
id.id(),
|
id.id(),
|
||||||
|
@ -63,33 +67,49 @@ impl LspColorData {
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
}),
|
}),
|
||||||
DocumentColorsRenderMode::None => {
|
DocumentColorsRenderMode::None => Some(InlaySplice {
|
||||||
self.colors.clear();
|
to_remove: self
|
||||||
Some(InlaySplice {
|
.buffer_colors
|
||||||
to_remove: self.inlay_colors.drain().map(|(id, _)| id).collect(),
|
.drain()
|
||||||
to_insert: Vec::new(),
|
.flat_map(|(_, buffer_colors)| buffer_colors.inlay_colors)
|
||||||
})
|
.map(|(id, _)| id)
|
||||||
}
|
.collect(),
|
||||||
|
to_insert: Vec::new(),
|
||||||
|
}),
|
||||||
DocumentColorsRenderMode::Border | DocumentColorsRenderMode::Background => {
|
DocumentColorsRenderMode::Border | DocumentColorsRenderMode::Background => {
|
||||||
Some(InlaySplice {
|
Some(InlaySplice {
|
||||||
to_remove: self.inlay_colors.drain().map(|(id, _)| id).collect(),
|
to_remove: self
|
||||||
|
.buffer_colors
|
||||||
|
.iter_mut()
|
||||||
|
.flat_map(|(_, buffer_colors)| buffer_colors.inlay_colors.drain())
|
||||||
|
.map(|(id, _)| id)
|
||||||
|
.collect(),
|
||||||
to_insert: Vec::new(),
|
to_insert: Vec::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_colors(&mut self, colors: Vec<(Range<Anchor>, DocumentColor, InlayId)>) -> bool {
|
fn set_colors(
|
||||||
if self.colors == colors {
|
&mut self,
|
||||||
|
buffer_id: BufferId,
|
||||||
|
colors: Vec<(Range<Anchor>, DocumentColor, InlayId)>,
|
||||||
|
cache_version: Option<usize>,
|
||||||
|
) -> bool {
|
||||||
|
let buffer_colors = self.buffer_colors.entry(buffer_id).or_default();
|
||||||
|
if let Some(cache_version) = cache_version {
|
||||||
|
buffer_colors.cache_version_used = cache_version;
|
||||||
|
}
|
||||||
|
if buffer_colors.colors == colors {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.inlay_colors = colors
|
buffer_colors.inlay_colors = colors
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, (_, _, id))| (*id, i))
|
.map(|(i, (_, _, id))| (*id, i))
|
||||||
.collect();
|
.collect();
|
||||||
self.colors = colors;
|
buffer_colors.colors = colors;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,8 +123,9 @@ impl LspColorData {
|
||||||
{
|
{
|
||||||
Vec::new()
|
Vec::new()
|
||||||
} else {
|
} else {
|
||||||
self.colors
|
self.buffer_colors
|
||||||
.iter()
|
.iter()
|
||||||
|
.flat_map(|(_, buffer_colors)| &buffer_colors.colors)
|
||||||
.map(|(range, color, _)| {
|
.map(|(range, color, _)| {
|
||||||
let display_range = range.clone().to_display_points(snapshot);
|
let display_range = range.clone().to_display_points(snapshot);
|
||||||
let color = Hsla::from(Rgba {
|
let color = Hsla::from(Rgba {
|
||||||
|
@ -162,10 +183,9 @@ impl Editor {
|
||||||
ColorFetchStrategy::IgnoreCache
|
ColorFetchStrategy::IgnoreCache
|
||||||
} else {
|
} else {
|
||||||
ColorFetchStrategy::UseCache {
|
ColorFetchStrategy::UseCache {
|
||||||
known_cache_version: self
|
known_cache_version: self.colors.as_ref().and_then(|colors| {
|
||||||
.colors
|
Some(colors.buffer_colors.get(&buffer_id)?.cache_version_used)
|
||||||
.as_ref()
|
}),
|
||||||
.map(|colors| colors.cache_version_used),
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let colors_task = lsp_store.document_colors(fetch_strategy, buffer, cx)?;
|
let colors_task = lsp_store.document_colors(fetch_strategy, buffer, cx)?;
|
||||||
|
@ -201,15 +221,13 @@ impl Editor {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut cache_version = None;
|
let mut new_editor_colors = HashMap::default();
|
||||||
let mut new_editor_colors = Vec::<(Range<Anchor>, DocumentColor)>::new();
|
|
||||||
for (buffer_id, colors) in all_colors {
|
for (buffer_id, colors) in all_colors {
|
||||||
let Some(excerpts) = editor_excerpts.get(&buffer_id) else {
|
let Some(excerpts) = editor_excerpts.get(&buffer_id) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
match colors {
|
match colors {
|
||||||
Ok(colors) => {
|
Ok(colors) => {
|
||||||
cache_version = colors.cache_version;
|
|
||||||
for color in colors.colors {
|
for color in colors.colors {
|
||||||
let color_start = point_from_lsp(color.lsp_range.start);
|
let color_start = point_from_lsp(color.lsp_range.start);
|
||||||
let color_end = point_from_lsp(color.lsp_range.end);
|
let color_end = point_from_lsp(color.lsp_range.end);
|
||||||
|
@ -243,8 +261,15 @@ impl Editor {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let new_entry =
|
||||||
|
new_editor_colors.entry(buffer_id).or_insert_with(|| {
|
||||||
|
(Vec::<(Range<Anchor>, DocumentColor)>::new(), None)
|
||||||
|
});
|
||||||
|
new_entry.1 = colors.cache_version;
|
||||||
|
let new_buffer_colors = &mut new_entry.0;
|
||||||
|
|
||||||
let (Ok(i) | Err(i)) =
|
let (Ok(i) | Err(i)) =
|
||||||
new_editor_colors.binary_search_by(|(probe, _)| {
|
new_buffer_colors.binary_search_by(|(probe, _)| {
|
||||||
probe
|
probe
|
||||||
.start
|
.start
|
||||||
.cmp(&color_start_anchor, &multi_buffer_snapshot)
|
.cmp(&color_start_anchor, &multi_buffer_snapshot)
|
||||||
|
@ -254,7 +279,7 @@ impl Editor {
|
||||||
.cmp(&color_end_anchor, &multi_buffer_snapshot)
|
.cmp(&color_end_anchor, &multi_buffer_snapshot)
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
new_editor_colors
|
new_buffer_colors
|
||||||
.insert(i, (color_start_anchor..color_end_anchor, color));
|
.insert(i, (color_start_anchor..color_end_anchor, color));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -267,45 +292,70 @@ impl Editor {
|
||||||
editor
|
editor
|
||||||
.update(cx, |editor, cx| {
|
.update(cx, |editor, cx| {
|
||||||
let mut colors_splice = InlaySplice::default();
|
let mut colors_splice = InlaySplice::default();
|
||||||
let mut new_color_inlays = Vec::with_capacity(new_editor_colors.len());
|
|
||||||
let Some(colors) = &mut editor.colors else {
|
let Some(colors) = &mut editor.colors else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let mut existing_colors = colors.colors.iter().peekable();
|
let mut updated = false;
|
||||||
for (new_range, new_color) in new_editor_colors {
|
for (buffer_id, (new_buffer_colors, new_cache_version)) in new_editor_colors {
|
||||||
let rgba_color = Rgba {
|
let mut new_buffer_color_inlays =
|
||||||
r: new_color.color.red,
|
Vec::with_capacity(new_buffer_colors.len());
|
||||||
g: new_color.color.green,
|
let mut existing_buffer_colors = colors
|
||||||
b: new_color.color.blue,
|
.buffer_colors
|
||||||
a: new_color.color.alpha,
|
.entry(buffer_id)
|
||||||
};
|
.or_default()
|
||||||
|
.colors
|
||||||
|
.iter()
|
||||||
|
.peekable();
|
||||||
|
for (new_range, new_color) in new_buffer_colors {
|
||||||
|
let rgba_color = Rgba {
|
||||||
|
r: new_color.color.red,
|
||||||
|
g: new_color.color.green,
|
||||||
|
b: new_color.color.blue,
|
||||||
|
a: new_color.color.alpha,
|
||||||
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match existing_colors.peek() {
|
match existing_buffer_colors.peek() {
|
||||||
Some((existing_range, existing_color, existing_inlay_id)) => {
|
Some((existing_range, existing_color, existing_inlay_id)) => {
|
||||||
match existing_range
|
match existing_range
|
||||||
.start
|
.start
|
||||||
.cmp(&new_range.start, &multi_buffer_snapshot)
|
.cmp(&new_range.start, &multi_buffer_snapshot)
|
||||||
.then_with(|| {
|
.then_with(|| {
|
||||||
existing_range
|
existing_range
|
||||||
.end
|
.end
|
||||||
.cmp(&new_range.end, &multi_buffer_snapshot)
|
.cmp(&new_range.end, &multi_buffer_snapshot)
|
||||||
}) {
|
}) {
|
||||||
cmp::Ordering::Less => {
|
cmp::Ordering::Less => {
|
||||||
colors_splice.to_remove.push(*existing_inlay_id);
|
|
||||||
existing_colors.next();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
cmp::Ordering::Equal => {
|
|
||||||
if existing_color == &new_color {
|
|
||||||
new_color_inlays.push((
|
|
||||||
new_range,
|
|
||||||
new_color,
|
|
||||||
*existing_inlay_id,
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
colors_splice.to_remove.push(*existing_inlay_id);
|
colors_splice.to_remove.push(*existing_inlay_id);
|
||||||
|
existing_buffer_colors.next();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cmp::Ordering::Equal => {
|
||||||
|
if existing_color == &new_color {
|
||||||
|
new_buffer_color_inlays.push((
|
||||||
|
new_range,
|
||||||
|
new_color,
|
||||||
|
*existing_inlay_id,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
colors_splice
|
||||||
|
.to_remove
|
||||||
|
.push(*existing_inlay_id);
|
||||||
|
|
||||||
|
let inlay = Inlay::color(
|
||||||
|
post_inc(&mut editor.next_color_inlay_id),
|
||||||
|
new_range.start,
|
||||||
|
rgba_color,
|
||||||
|
);
|
||||||
|
let inlay_id = inlay.id;
|
||||||
|
colors_splice.to_insert.push(inlay);
|
||||||
|
new_buffer_color_inlays
|
||||||
|
.push((new_range, new_color, inlay_id));
|
||||||
|
}
|
||||||
|
existing_buffer_colors.next();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cmp::Ordering::Greater => {
|
||||||
let inlay = Inlay::color(
|
let inlay = Inlay::color(
|
||||||
post_inc(&mut editor.next_color_inlay_id),
|
post_inc(&mut editor.next_color_inlay_id),
|
||||||
new_range.start,
|
new_range.start,
|
||||||
|
@ -313,49 +363,40 @@ impl Editor {
|
||||||
);
|
);
|
||||||
let inlay_id = inlay.id;
|
let inlay_id = inlay.id;
|
||||||
colors_splice.to_insert.push(inlay);
|
colors_splice.to_insert.push(inlay);
|
||||||
new_color_inlays
|
new_buffer_color_inlays
|
||||||
.push((new_range, new_color, inlay_id));
|
.push((new_range, new_color, inlay_id));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
existing_colors.next();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cmp::Ordering::Greater => {
|
|
||||||
let inlay = Inlay::color(
|
|
||||||
post_inc(&mut editor.next_color_inlay_id),
|
|
||||||
new_range.start,
|
|
||||||
rgba_color,
|
|
||||||
);
|
|
||||||
let inlay_id = inlay.id;
|
|
||||||
colors_splice.to_insert.push(inlay);
|
|
||||||
new_color_inlays.push((new_range, new_color, inlay_id));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
None => {
|
||||||
None => {
|
let inlay = Inlay::color(
|
||||||
let inlay = Inlay::color(
|
post_inc(&mut editor.next_color_inlay_id),
|
||||||
post_inc(&mut editor.next_color_inlay_id),
|
new_range.start,
|
||||||
new_range.start,
|
rgba_color,
|
||||||
rgba_color,
|
);
|
||||||
);
|
let inlay_id = inlay.id;
|
||||||
let inlay_id = inlay.id;
|
colors_splice.to_insert.push(inlay);
|
||||||
colors_splice.to_insert.push(inlay);
|
new_buffer_color_inlays
|
||||||
new_color_inlays.push((new_range, new_color, inlay_id));
|
.push((new_range, new_color, inlay_id));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if existing_colors.peek().is_some() {
|
if existing_buffer_colors.peek().is_some() {
|
||||||
colors_splice
|
colors_splice
|
||||||
.to_remove
|
.to_remove
|
||||||
.extend(existing_colors.map(|(_, _, id)| *id));
|
.extend(existing_buffer_colors.map(|(_, _, id)| *id));
|
||||||
|
}
|
||||||
|
updated |= colors.set_colors(
|
||||||
|
buffer_id,
|
||||||
|
new_buffer_color_inlays,
|
||||||
|
new_cache_version,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut updated = colors.set_colors(new_color_inlays);
|
|
||||||
if let Some(cache_version) = cache_version {
|
|
||||||
colors.cache_version_used = cache_version;
|
|
||||||
}
|
|
||||||
if colors.render_mode == DocumentColorsRenderMode::Inlay
|
if colors.render_mode == DocumentColorsRenderMode::Inlay
|
||||||
&& (!colors_splice.to_insert.is_empty()
|
&& (!colors_splice.to_insert.is_empty()
|
||||||
|| !colors_splice.to_remove.is_empty())
|
|| !colors_splice.to_remove.is_empty())
|
||||||
|
|
|
@ -170,6 +170,7 @@ pub struct LocalLspStore {
|
||||||
_subscription: gpui::Subscription,
|
_subscription: gpui::Subscription,
|
||||||
lsp_tree: Entity<LanguageServerTree>,
|
lsp_tree: Entity<LanguageServerTree>,
|
||||||
registered_buffers: HashMap<BufferId, usize>,
|
registered_buffers: HashMap<BufferId, usize>,
|
||||||
|
buffers_opened_in_servers: HashMap<BufferId, HashSet<LanguageServerId>>,
|
||||||
buffer_pull_diagnostics_result_ids: HashMap<LanguageServerId, HashMap<PathBuf, Option<String>>>,
|
buffer_pull_diagnostics_result_ids: HashMap<LanguageServerId, HashMap<PathBuf, Option<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2546,6 +2547,10 @@ impl LocalLspStore {
|
||||||
vec![snapshot]
|
vec![snapshot]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.buffers_opened_in_servers
|
||||||
|
.entry(buffer_id)
|
||||||
|
.or_default()
|
||||||
|
.insert(server.server_id());
|
||||||
cx.emit(LspStoreEvent::LanguageServerUpdate {
|
cx.emit(LspStoreEvent::LanguageServerUpdate {
|
||||||
language_server_id: server.server_id(),
|
language_server_id: server.server_id(),
|
||||||
name: None,
|
name: None,
|
||||||
|
@ -3208,6 +3213,9 @@ impl LocalLspStore {
|
||||||
self.language_servers.remove(server_id_to_remove);
|
self.language_servers.remove(server_id_to_remove);
|
||||||
self.buffer_pull_diagnostics_result_ids
|
self.buffer_pull_diagnostics_result_ids
|
||||||
.remove(server_id_to_remove);
|
.remove(server_id_to_remove);
|
||||||
|
for buffer_servers in self.buffers_opened_in_servers.values_mut() {
|
||||||
|
buffer_servers.remove(server_id_to_remove);
|
||||||
|
}
|
||||||
cx.emit(LspStoreEvent::LanguageServerRemoved(*server_id_to_remove));
|
cx.emit(LspStoreEvent::LanguageServerRemoved(*server_id_to_remove));
|
||||||
}
|
}
|
||||||
servers_to_remove.into_keys().collect()
|
servers_to_remove.into_keys().collect()
|
||||||
|
@ -3787,6 +3795,7 @@ impl LspStore {
|
||||||
}),
|
}),
|
||||||
lsp_tree: LanguageServerTree::new(manifest_tree, languages.clone(), cx),
|
lsp_tree: LanguageServerTree::new(manifest_tree, languages.clone(), cx),
|
||||||
registered_buffers: HashMap::default(),
|
registered_buffers: HashMap::default(),
|
||||||
|
buffers_opened_in_servers: HashMap::default(),
|
||||||
buffer_pull_diagnostics_result_ids: HashMap::default(),
|
buffer_pull_diagnostics_result_ids: HashMap::default(),
|
||||||
}),
|
}),
|
||||||
last_formatting_failure: None,
|
last_formatting_failure: None,
|
||||||
|
@ -4159,6 +4168,7 @@ impl LspStore {
|
||||||
lsp_store.lsp_data.remove(&buffer_id);
|
lsp_store.lsp_data.remove(&buffer_id);
|
||||||
let local = lsp_store.as_local_mut().unwrap();
|
let local = lsp_store.as_local_mut().unwrap();
|
||||||
local.registered_buffers.remove(&buffer_id);
|
local.registered_buffers.remove(&buffer_id);
|
||||||
|
local.buffers_opened_in_servers.remove(&buffer_id);
|
||||||
if let Some(file) = File::from_dyn(buffer.read(cx).file()).cloned() {
|
if let Some(file) = File::from_dyn(buffer.read(cx).file()).cloned() {
|
||||||
local.unregister_old_buffer_from_language_servers(&buffer, &file, cx);
|
local.unregister_old_buffer_from_language_servers(&buffer, &file, cx);
|
||||||
}
|
}
|
||||||
|
@ -6235,21 +6245,31 @@ impl LspStore {
|
||||||
} => {
|
} => {
|
||||||
if let Some(cached_data) = self.lsp_data.get(&buffer_id) {
|
if let Some(cached_data) = self.lsp_data.get(&buffer_id) {
|
||||||
if !version_queried_for.changed_since(&cached_data.colors_for_version) {
|
if !version_queried_for.changed_since(&cached_data.colors_for_version) {
|
||||||
if Some(cached_data.cache_version) == known_cache_version {
|
let has_different_servers = self.as_local().is_some_and(|local| {
|
||||||
return None;
|
local
|
||||||
} else {
|
.buffers_opened_in_servers
|
||||||
return Some(
|
.get(&buffer_id)
|
||||||
Task::ready(Ok(DocumentColors {
|
.cloned()
|
||||||
colors: cached_data
|
.unwrap_or_default()
|
||||||
.colors
|
!= cached_data.colors.keys().copied().collect()
|
||||||
.values()
|
});
|
||||||
.flatten()
|
if !has_different_servers {
|
||||||
.cloned()
|
if Some(cached_data.cache_version) == known_cache_version {
|
||||||
.collect(),
|
return None;
|
||||||
cache_version: Some(cached_data.cache_version),
|
} else {
|
||||||
}))
|
return Some(
|
||||||
.shared(),
|
Task::ready(Ok(DocumentColors {
|
||||||
);
|
colors: cached_data
|
||||||
|
.colors
|
||||||
|
.values()
|
||||||
|
.flatten()
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
cache_version: Some(cached_data.cache_version),
|
||||||
|
}))
|
||||||
|
.shared(),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7522,6 +7542,14 @@ impl LspStore {
|
||||||
.unwrap_or(true)
|
.unwrap_or(true)
|
||||||
})
|
})
|
||||||
.map(|(_, server)| server.server_id())
|
.map(|(_, server)| server.server_id())
|
||||||
|
.filter(|server_id| {
|
||||||
|
self.as_local().is_none_or(|local| {
|
||||||
|
local
|
||||||
|
.buffers_opened_in_servers
|
||||||
|
.get(&snapshot.remote_id())
|
||||||
|
.is_some_and(|servers| servers.contains(server_id))
|
||||||
|
})
|
||||||
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -10084,6 +10112,7 @@ impl LspStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell the language server about every open buffer in the worktree that matches the language.
|
// Tell the language server about every open buffer in the worktree that matches the language.
|
||||||
|
let mut buffer_paths_registered = Vec::new();
|
||||||
self.buffer_store.clone().update(cx, |buffer_store, cx| {
|
self.buffer_store.clone().update(cx, |buffer_store, cx| {
|
||||||
for buffer_handle in buffer_store.buffers() {
|
for buffer_handle in buffer_store.buffers() {
|
||||||
let buffer = buffer_handle.read(cx);
|
let buffer = buffer_handle.read(cx);
|
||||||
|
@ -10142,6 +10171,12 @@ impl LspStore {
|
||||||
version,
|
version,
|
||||||
initial_snapshot.text(),
|
initial_snapshot.text(),
|
||||||
);
|
);
|
||||||
|
buffer_paths_registered.push(file.abs_path(cx));
|
||||||
|
local
|
||||||
|
.buffers_opened_in_servers
|
||||||
|
.entry(buffer.remote_id())
|
||||||
|
.or_default()
|
||||||
|
.insert(server_id);
|
||||||
}
|
}
|
||||||
buffer_handle.update(cx, |buffer, cx| {
|
buffer_handle.update(cx, |buffer, cx| {
|
||||||
buffer.set_completion_triggers(
|
buffer.set_completion_triggers(
|
||||||
|
@ -10163,6 +10198,18 @@ impl LspStore {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for abs_path in buffer_paths_registered {
|
||||||
|
cx.emit(LspStoreEvent::LanguageServerUpdate {
|
||||||
|
language_server_id: server_id,
|
||||||
|
name: Some(adapter.name()),
|
||||||
|
message: proto::update_language_server::Variant::RegisteredForBuffer(
|
||||||
|
proto::RegisteredForBuffer {
|
||||||
|
buffer_abs_path: abs_path.to_string_lossy().to_string(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10612,6 +10659,9 @@ impl LspStore {
|
||||||
}
|
}
|
||||||
if let Some(local) = self.as_local_mut() {
|
if let Some(local) = self.as_local_mut() {
|
||||||
local.buffer_pull_diagnostics_result_ids.remove(&for_server);
|
local.buffer_pull_diagnostics_result_ids.remove(&for_server);
|
||||||
|
for buffer_servers in local.buffers_opened_in_servers.values_mut() {
|
||||||
|
buffer_servers.remove(&for_server);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue