mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-20 02:47:34 +03:00
Color diagnostic messages based on their severity
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
f39942863b
commit
1a8b23e118
@ -8,7 +8,7 @@ pub use block_map::{BlockDisposition, BlockId, BlockProperties, BufferRows, Chun
|
||||
use block_map::{BlockMap, BlockPoint};
|
||||
use buffer::Rope;
|
||||
use fold_map::{FoldMap, ToFoldPoint as _};
|
||||
use gpui::{fonts::FontId, Entity, ModelContext, ModelHandle};
|
||||
use gpui::{fonts::FontId, AppContext, Entity, ModelContext, ModelHandle};
|
||||
use language::{Anchor, Buffer, Point, ToOffset, ToPoint};
|
||||
use std::{collections::HashSet, ops::Range};
|
||||
use sum_tree::Bias;
|
||||
@ -230,7 +230,7 @@ impl DisplayMapSnapshot {
|
||||
|
||||
pub fn text_chunks(&self, display_row: u32) -> impl Iterator<Item = &str> {
|
||||
self.blocks_snapshot
|
||||
.chunks(display_row..self.max_point().row() + 1, None)
|
||||
.chunks(display_row..self.max_point().row() + 1, None, None)
|
||||
.map(|h| h.text)
|
||||
}
|
||||
|
||||
@ -238,8 +238,9 @@ impl DisplayMapSnapshot {
|
||||
&'a self,
|
||||
display_rows: Range<u32>,
|
||||
theme: Option<&'a SyntaxTheme>,
|
||||
cx: &'a AppContext,
|
||||
) -> block_map::Chunks<'a> {
|
||||
self.blocks_snapshot.chunks(display_rows, theme)
|
||||
self.blocks_snapshot.chunks(display_rows, theme, Some(cx))
|
||||
}
|
||||
|
||||
pub fn chars_at<'a>(&'a self, point: DisplayPoint) -> impl Iterator<Item = char> + 'a {
|
||||
@ -1025,7 +1026,7 @@ mod tests {
|
||||
) -> Vec<(String, Option<Color>)> {
|
||||
let snapshot = map.update(cx, |map, cx| map.snapshot(cx));
|
||||
let mut chunks: Vec<(String, Option<Color>)> = Vec::new();
|
||||
for chunk in snapshot.chunks(rows, Some(theme)) {
|
||||
for chunk in snapshot.chunks(rows, Some(theme), cx) {
|
||||
let color = chunk.highlight_style.map(|s| s.color);
|
||||
if let Some((last_chunk, last_color)) = chunks.last_mut() {
|
||||
if color == *last_color {
|
||||
|
@ -6,13 +6,14 @@ use parking_lot::Mutex;
|
||||
use std::{
|
||||
cmp::{self, Ordering},
|
||||
collections::HashSet,
|
||||
fmt::Debug,
|
||||
iter,
|
||||
ops::Range,
|
||||
slice,
|
||||
sync::{
|
||||
atomic::{AtomicUsize, Ordering::SeqCst},
|
||||
Arc,
|
||||
},
|
||||
vec,
|
||||
};
|
||||
use sum_tree::SumTree;
|
||||
use theme::SyntaxTheme;
|
||||
@ -44,12 +45,11 @@ struct BlockRow(u32);
|
||||
#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
|
||||
struct WrapRow(u32);
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Block {
|
||||
id: BlockId,
|
||||
position: Anchor,
|
||||
text: Rope,
|
||||
runs: Vec<(usize, HighlightStyle)>,
|
||||
build_runs: Option<Arc<dyn Fn(&AppContext) -> Vec<(usize, HighlightStyle)>>>,
|
||||
disposition: BlockDisposition,
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ where
|
||||
{
|
||||
pub position: P,
|
||||
pub text: T,
|
||||
pub runs: Vec<(usize, HighlightStyle)>,
|
||||
pub build_runs: Option<Arc<dyn Fn(&AppContext) -> Vec<(usize, HighlightStyle)>>>,
|
||||
pub disposition: BlockDisposition,
|
||||
}
|
||||
|
||||
@ -92,11 +92,12 @@ pub struct Chunks<'a> {
|
||||
block_chunks: Option<BlockChunks<'a>>,
|
||||
output_row: u32,
|
||||
max_output_row: u32,
|
||||
cx: Option<&'a AppContext>,
|
||||
}
|
||||
|
||||
struct BlockChunks<'a> {
|
||||
chunks: rope::Chunks<'a>,
|
||||
runs: iter::Peekable<slice::Iter<'a, (usize, HighlightStyle)>>,
|
||||
runs: iter::Peekable<vec::IntoIter<(usize, HighlightStyle)>>,
|
||||
chunk: Option<&'a str>,
|
||||
run_start: usize,
|
||||
offset: usize,
|
||||
@ -403,7 +404,7 @@ impl<'a> BlockMapWriter<'a> {
|
||||
id,
|
||||
position,
|
||||
text: block.text.into(),
|
||||
runs: block.runs,
|
||||
build_runs: block.build_runs,
|
||||
disposition: block.disposition,
|
||||
}),
|
||||
);
|
||||
@ -460,12 +461,17 @@ impl<'a> BlockMapWriter<'a> {
|
||||
impl BlockSnapshot {
|
||||
#[cfg(test)]
|
||||
fn text(&mut self) -> String {
|
||||
self.chunks(0..self.transforms.summary().output_rows, None)
|
||||
self.chunks(0..self.transforms.summary().output_rows, None, None)
|
||||
.map(|chunk| chunk.text)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn chunks<'a>(&'a self, rows: Range<u32>, theme: Option<&'a SyntaxTheme>) -> Chunks<'a> {
|
||||
pub fn chunks<'a>(
|
||||
&'a self,
|
||||
rows: Range<u32>,
|
||||
theme: Option<&'a SyntaxTheme>,
|
||||
cx: Option<&'a AppContext>,
|
||||
) -> Chunks<'a> {
|
||||
let max_output_row = cmp::min(rows.end, self.transforms.summary().output_rows);
|
||||
let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>();
|
||||
let input_end = {
|
||||
@ -499,6 +505,7 @@ impl BlockSnapshot {
|
||||
transforms: cursor,
|
||||
output_row: rows.start,
|
||||
max_output_row,
|
||||
cx,
|
||||
}
|
||||
}
|
||||
|
||||
@ -709,7 +716,11 @@ impl<'a> Iterator for Chunks<'a> {
|
||||
let start_in_block = self.output_row - block_start;
|
||||
let end_in_block = cmp::min(self.max_output_row, block_end) - block_start;
|
||||
self.transforms.next(&());
|
||||
self.block_chunks = Some(BlockChunks::new(block, start_in_block..end_in_block));
|
||||
self.block_chunks = Some(BlockChunks::new(
|
||||
block,
|
||||
start_in_block..end_in_block,
|
||||
self.cx,
|
||||
));
|
||||
return self.next();
|
||||
}
|
||||
|
||||
@ -748,11 +759,18 @@ impl<'a> Iterator for Chunks<'a> {
|
||||
}
|
||||
|
||||
impl<'a> BlockChunks<'a> {
|
||||
fn new(block: &'a Block, rows: Range<u32>) -> Self {
|
||||
fn new(block: &'a Block, rows: Range<u32>, cx: Option<&'a AppContext>) -> Self {
|
||||
let offset_range = block.text.point_to_offset(Point::new(rows.start, 0))
|
||||
..block.text.point_to_offset(Point::new(rows.end, 0));
|
||||
|
||||
let mut runs = block.runs.iter().peekable();
|
||||
let mut runs = block
|
||||
.build_runs
|
||||
.as_ref()
|
||||
.zip(cx)
|
||||
.map(|(build_runs, cx)| build_runs(cx))
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.peekable();
|
||||
let mut run_start = 0;
|
||||
while let Some((run_len, _)) = runs.peek() {
|
||||
let run_end = run_start + run_len;
|
||||
@ -874,6 +892,17 @@ impl BlockDisposition {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Block {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Block")
|
||||
.field("id", &self.id)
|
||||
.field("position", &self.position)
|
||||
.field("text", &self.text)
|
||||
.field("disposition", &self.disposition)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
// Count the number of bytes prior to a target point. If the string doesn't contain the target
|
||||
// point, return its total extent. Otherwise return the target point itself.
|
||||
fn offset_for_row(s: &str, target: u32) -> (u32, usize) {
|
||||
@ -938,19 +967,19 @@ mod tests {
|
||||
position: Point::new(1, 0),
|
||||
text: "BLOCK 1",
|
||||
disposition: BlockDisposition::Above,
|
||||
runs: vec![],
|
||||
build_runs: None,
|
||||
},
|
||||
BlockProperties {
|
||||
position: Point::new(1, 2),
|
||||
text: "BLOCK 2",
|
||||
disposition: BlockDisposition::Above,
|
||||
runs: vec![],
|
||||
build_runs: None,
|
||||
},
|
||||
BlockProperties {
|
||||
position: Point::new(3, 2),
|
||||
text: "BLOCK 3",
|
||||
disposition: BlockDisposition::Below,
|
||||
runs: vec![],
|
||||
build_runs: None,
|
||||
},
|
||||
],
|
||||
cx,
|
||||
@ -1078,13 +1107,13 @@ mod tests {
|
||||
position: Point::new(1, 12),
|
||||
text: "<BLOCK 1",
|
||||
disposition: BlockDisposition::Above,
|
||||
runs: vec![],
|
||||
build_runs: None,
|
||||
},
|
||||
BlockProperties {
|
||||
position: Point::new(1, 1),
|
||||
text: ">BLOCK 2",
|
||||
disposition: BlockDisposition::Below,
|
||||
runs: vec![],
|
||||
build_runs: None,
|
||||
},
|
||||
],
|
||||
cx,
|
||||
@ -1177,7 +1206,7 @@ mod tests {
|
||||
BlockProperties {
|
||||
position,
|
||||
text,
|
||||
runs: Vec::<(usize, HighlightStyle)>::new(),
|
||||
build_runs: None,
|
||||
disposition,
|
||||
}
|
||||
})
|
||||
@ -1252,7 +1281,7 @@ mod tests {
|
||||
BlockProperties {
|
||||
position: row,
|
||||
text: block.text,
|
||||
runs: block.runs,
|
||||
build_runs: block.build_runs.clone(),
|
||||
disposition: block.disposition,
|
||||
},
|
||||
)
|
||||
@ -1313,7 +1342,7 @@ mod tests {
|
||||
for start_row in 0..expected_row_count {
|
||||
let expected_text = expected_lines[start_row..].join("\n");
|
||||
let actual_text = blocks_snapshot
|
||||
.chunks(start_row as u32..expected_row_count as u32, None)
|
||||
.chunks(start_row as u32..expected_row_count as u32, None, None)
|
||||
.map(|chunk| chunk.text)
|
||||
.collect::<String>();
|
||||
assert_eq!(
|
||||
|
@ -17,7 +17,7 @@ use gpui::{
|
||||
MutableAppContext, PaintContext, Quad, Scene, SizeConstraint, ViewContext, WeakViewHandle,
|
||||
};
|
||||
use json::json;
|
||||
use language::{Chunk, DiagnosticSeverity};
|
||||
use language::Chunk;
|
||||
use smallvec::SmallVec;
|
||||
use std::{
|
||||
cmp::{self, Ordering},
|
||||
@ -493,7 +493,7 @@ impl EditorElement {
|
||||
let mut styles = Vec::new();
|
||||
let mut row = rows.start;
|
||||
let mut line_exceeded_max_len = false;
|
||||
let chunks = snapshot.chunks(rows.clone(), Some(&style.syntax));
|
||||
let chunks = snapshot.chunks(rows.clone(), Some(&style.syntax), cx);
|
||||
|
||||
let newline_chunk = Chunk {
|
||||
text: "\n",
|
||||
@ -541,13 +541,7 @@ impl EditorElement {
|
||||
}
|
||||
|
||||
let underline = if let Some(severity) = chunk.diagnostic {
|
||||
match severity {
|
||||
DiagnosticSeverity::ERROR => Some(style.error_underline),
|
||||
DiagnosticSeverity::WARNING => Some(style.warning_underline),
|
||||
DiagnosticSeverity::INFORMATION => Some(style.information_underline),
|
||||
DiagnosticSeverity::HINT => Some(style.hint_underline),
|
||||
_ => highlight_style.underline,
|
||||
}
|
||||
Some(super::diagnostic_color(severity, style))
|
||||
} else {
|
||||
highlight_style.underline
|
||||
};
|
||||
|
@ -12,6 +12,7 @@ use display_map::*;
|
||||
pub use element::*;
|
||||
use gpui::{
|
||||
action,
|
||||
color::Color,
|
||||
geometry::vector::{vec2f, Vector2F},
|
||||
keymap::Binding,
|
||||
text_layout, AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle,
|
||||
@ -2250,21 +2251,30 @@ impl Editor {
|
||||
let buffer = self.buffer.read(cx);
|
||||
let diagnostic_group = buffer
|
||||
.diagnostic_group::<Point>(group_id)
|
||||
.map(|(range, diagnostic)| (range, diagnostic.message.clone()))
|
||||
.map(|(range, diagnostic)| (range, diagnostic.clone()))
|
||||
.collect::<Vec<_>>();
|
||||
let primary_range = buffer.anchor_after(primary_range.start)
|
||||
..buffer.anchor_before(primary_range.end);
|
||||
|
||||
let block_ids = display_map
|
||||
.insert_blocks(
|
||||
diagnostic_group
|
||||
.iter()
|
||||
.map(|(range, message)| BlockProperties {
|
||||
diagnostic_group.iter().map(|(range, diagnostic)| {
|
||||
let build_settings = self.build_settings.clone();
|
||||
let message_len = diagnostic.message.len();
|
||||
let severity = diagnostic.severity;
|
||||
BlockProperties {
|
||||
position: range.start,
|
||||
text: message.as_str(),
|
||||
runs: vec![],
|
||||
disposition: BlockDisposition::Above,
|
||||
}),
|
||||
text: diagnostic.message.as_str(),
|
||||
build_runs: Some(Arc::new(move |cx| {
|
||||
let settings = build_settings.borrow()(cx);
|
||||
vec![(
|
||||
message_len,
|
||||
diagnostic_color(severity, &settings.style).into(),
|
||||
)]
|
||||
})),
|
||||
disposition: BlockDisposition::Below,
|
||||
}
|
||||
}),
|
||||
cx,
|
||||
)
|
||||
.into_iter()
|
||||
@ -2813,8 +2823,9 @@ impl Snapshot {
|
||||
&'a self,
|
||||
display_rows: Range<u32>,
|
||||
theme: Option<&'a SyntaxTheme>,
|
||||
cx: &'a AppContext,
|
||||
) -> display_map::Chunks<'a> {
|
||||
self.display_snapshot.chunks(display_rows, theme)
|
||||
self.display_snapshot.chunks(display_rows, theme, cx)
|
||||
}
|
||||
|
||||
pub fn scroll_position(&self) -> Vector2F {
|
||||
@ -2882,10 +2893,10 @@ impl EditorSettings {
|
||||
selection: Default::default(),
|
||||
guest_selections: Default::default(),
|
||||
syntax: Default::default(),
|
||||
error_underline: Default::default(),
|
||||
warning_underline: Default::default(),
|
||||
information_underline: Default::default(),
|
||||
hint_underline: Default::default(),
|
||||
error_color: Default::default(),
|
||||
warning_color: Default::default(),
|
||||
information_color: Default::default(),
|
||||
hint_color: Default::default(),
|
||||
}
|
||||
},
|
||||
}
|
||||
@ -3009,6 +3020,16 @@ impl SelectionExt for Selection<Point> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn diagnostic_color(severity: DiagnosticSeverity, style: &EditorStyle) -> Color {
|
||||
match severity {
|
||||
DiagnosticSeverity::ERROR => style.error_color,
|
||||
DiagnosticSeverity::WARNING => style.warning_color,
|
||||
DiagnosticSeverity::INFORMATION => style.information_color,
|
||||
DiagnosticSeverity::HINT => style.hint_color,
|
||||
_ => style.text.color,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -227,12 +227,12 @@ pub struct EditorStyle {
|
||||
pub line_number_active: Color,
|
||||
pub guest_selections: Vec<SelectionStyle>,
|
||||
pub syntax: Arc<SyntaxTheme>,
|
||||
pub error_underline: Color,
|
||||
pub warning_underline: Color,
|
||||
pub error_color: Color,
|
||||
pub warning_color: Color,
|
||||
#[serde(default)]
|
||||
pub information_underline: Color,
|
||||
pub information_color: Color,
|
||||
#[serde(default)]
|
||||
pub hint_underline: Color,
|
||||
pub hint_color: Color,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default, Deserialize)]
|
||||
@ -273,10 +273,10 @@ impl InputEditorStyle {
|
||||
line_number_active: Default::default(),
|
||||
guest_selections: Default::default(),
|
||||
syntax: Default::default(),
|
||||
error_underline: Default::default(),
|
||||
warning_underline: Default::default(),
|
||||
information_underline: Default::default(),
|
||||
hint_underline: Default::default(),
|
||||
error_color: Default::default(),
|
||||
warning_color: Default::default(),
|
||||
information_color: Default::default(),
|
||||
hint_color: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ corner_radius = 6
|
||||
|
||||
[project_panel]
|
||||
extends = "$panel"
|
||||
padding.top = 6 # ($workspace.tab.height - $project_panel.entry.height) / 2
|
||||
padding.top = 6 # ($workspace.tab.height - $project_panel.entry.height) / 2
|
||||
|
||||
[project_panel.entry]
|
||||
text = "$text.1"
|
||||
@ -235,7 +235,7 @@ line_number = "$text.2.color"
|
||||
line_number_active = "$text.0.color"
|
||||
selection = "$selection.host"
|
||||
guest_selections = "$selection.guests"
|
||||
error_underline = "$status.bad"
|
||||
warning_underline = "$status.warn"
|
||||
info_underline = "$status.info"
|
||||
hint_underline = "$status.info"
|
||||
error_color = "$status.bad"
|
||||
warning_color = "$status.warn"
|
||||
info_color = "$status.info"
|
||||
hint_color = "$status.info"
|
||||
|
Loading…
Reference in New Issue
Block a user