WIP

Max Brunsfeld created

Change summary

Cargo.lock                            |  3 +
crates/diagnostics/Cargo.toml         |  3 +
crates/diagnostics/src/diagnostics.rs | 54 ++++++++++++++++++++++++++--
crates/editor/src/editor.rs           |  2 
crates/editor/src/multi_buffer.rs     |  6 +-
crates/language/src/buffer.rs         |  9 ++++
6 files changed, 68 insertions(+), 9 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -1414,8 +1414,11 @@ dependencies = [
 name = "diagnostics"
 version = "0.1.0"
 dependencies = [
+ "anyhow",
+ "collections",
  "editor",
  "gpui",
+ "language",
  "postage",
  "project",
  "workspace",

crates/diagnostics/Cargo.toml 🔗

@@ -7,7 +7,10 @@ edition = "2021"
 path = "src/diagnostics.rs"
 
 [dependencies]
+anyhow = "1.0"
+collections = { path = "../collections" }
 editor = { path = "../editor" }
+language = { path = "../language" }
 gpui = { path = "../gpui" }
 project = { path = "../project" }
 workspace = { path = "../workspace" }

crates/diagnostics/src/diagnostics.rs 🔗

@@ -1,5 +1,7 @@
-use editor::{Editor, MultiBuffer};
+use collections::HashMap;
+use editor::{Editor, ExcerptProperties, MultiBuffer};
 use gpui::{elements::*, Entity, ModelHandle, RenderContext, View, ViewContext, ViewHandle};
+use language::Point;
 use postage::watch;
 use project::Project;
 
@@ -14,10 +16,52 @@ impl ProjectDiagnostics {
         settings: watch::Receiver<workspace::Settings>,
         cx: &mut ViewContext<Self>,
     ) -> Self {
-        let mut buffer = cx.add_model(|cx| MultiBuffer::new(project.read(cx).replica_id(cx)));
-        for (project_path, diagnostic_summary) in project.read(cx).diagnostic_summaries(cx) {
-            //
-        }
+        let buffer = cx.add_model(|cx| MultiBuffer::new(project.read(cx).replica_id(cx)));
+
+        let project_paths = project
+            .read(cx)
+            .diagnostic_summaries(cx)
+            .map(|e| e.0)
+            .collect::<Vec<_>>();
+
+        cx.spawn(|this, mut cx| {
+            let project = project.clone();
+            async move {
+                let mut excerpts = Vec::new();
+                for project_path in project_paths {
+                    let buffer = project
+                        .update(&mut cx, |project, cx| project.open_buffer(project_path, cx))
+                        .await?;
+                    let snapshot = buffer.read_with(&cx, |b, _| b.snapshot());
+
+                    let mut grouped_diagnostics = HashMap::default();
+                    for entry in snapshot.all_diagnostics() {
+                        let mut group = grouped_diagnostics
+                            .entry(entry.diagnostic.group_id)
+                            .or_insert((Point::zero(), Vec::new()));
+                        if entry.diagnostic.is_primary {
+                            group.0 = entry.range.start;
+                        }
+                        group.1.push(entry);
+                    }
+                    let mut sorted_diagnostic_groups =
+                        grouped_diagnostics.into_values().collect::<Vec<_>>();
+                    sorted_diagnostic_groups.sort_by_key(|group| group.0);
+
+                    let mut prev_end_row = None;
+                    let mut pending_excerpt = None;
+                    for diagnostic in snapshot.all_diagnostics::<Point>() {
+                        excerpts.push(ExcerptProperties {
+                            buffer: &buffer,
+                            range: todo!(),
+                            header_height: todo!(),
+                        });
+                    }
+                }
+                Result::Ok::<_, anyhow::Error>(())
+            }
+        })
+        .detach();
 
         Self {
             editor: cx.add_view(|cx| {

crates/editor/src/editor.rs 🔗

@@ -26,10 +26,10 @@ use language::{
     BracketPair, Buffer, Diagnostic, DiagnosticSeverity, Language, Point, Selection, SelectionGoal,
     TransactionId,
 };
-pub use multi_buffer::MultiBuffer;
 use multi_buffer::{
     Anchor, AnchorRangeExt, MultiBufferChunks, MultiBufferSnapshot, ToOffset, ToPoint,
 };
+pub use multi_buffer::{ExcerptProperties, MultiBuffer};
 use postage::watch;
 use serde::{Deserialize, Serialize};
 use smallvec::SmallVec;

crates/editor/src/multi_buffer.rs 🔗

@@ -65,9 +65,9 @@ pub struct MultiBufferSnapshot {
 }
 
 pub struct ExcerptProperties<'a, T> {
-    buffer: &'a ModelHandle<Buffer>,
-    range: Range<T>,
-    header_height: u8,
+    pub buffer: &'a ModelHandle<Buffer>,
+    pub range: Range<T>,
+    pub header_height: u8,
 }
 
 #[derive(Clone)]

crates/language/src/buffer.rs 🔗

@@ -1674,6 +1674,15 @@ impl BufferSnapshot {
             })
     }
 
+    pub fn all_diagnostics<'a, O>(&'a self) -> impl 'a + Iterator<Item = DiagnosticEntry<O>>
+    where
+        O: 'a + FromAnchor,
+    {
+        self.diagnostics
+            .iter()
+            .map(|diagnostic| diagnostic.resolve(self))
+    }
+
     pub fn diagnostics_in_range<'a, T, O>(
         &'a self,
         search_range: Range<T>,