Fix context line handline in project diagnostic view

Max Brunsfeld created

Change summary

crates/diagnostics/src/diagnostics.rs       | 85 ++++++++++++++++++----
crates/language/build.rs                    |  1 
crates/server/src/auth.rs                   |  2 
crates/server/src/releases.rs               |  7 -
crates/text/src/tests.rs                    |  2 
crates/theme_selector/src/theme_selector.rs |  2 
6 files changed, 75 insertions(+), 24 deletions(-)

Detailed changes

crates/diagnostics/src/diagnostics.rs 🔗

@@ -16,6 +16,8 @@ use workspace::Workspace;
 
 action!(Toggle);
 
+const CONTEXT_LINE_COUNT: u32 = 1;
+
 pub fn init(cx: &mut MutableAppContext) {
     cx.add_bindings([Binding::new("alt-shift-D", Toggle, None)]);
     cx.add_action(ProjectDiagnosticsEditor::toggle);
@@ -96,15 +98,18 @@ impl ProjectDiagnosticsEditor {
                 for (ix, entry) in group.entries.iter().map(Some).chain([None]).enumerate() {
                     if let Some((range, start_ix)) = &mut pending_range {
                         if let Some(entry) = entry {
-                            if entry.range.start.row <= range.end.row + 1 {
+                            if entry.range.start.row <= range.end.row + 1 + CONTEXT_LINE_COUNT * 2 {
                                 range.end = range.end.max(entry.range.end);
                                 continue;
                             }
                         }
 
-                        let excerpt_start = Point::new(range.start.row.saturating_sub(1), 0);
-                        let excerpt_end = snapshot
-                            .clip_point(Point::new(range.end.row + 1, u32::MAX), Bias::Left);
+                        let excerpt_start =
+                            Point::new(range.start.row.saturating_sub(CONTEXT_LINE_COUNT), 0);
+                        let excerpt_end = snapshot.clip_point(
+                            Point::new(range.end.row + CONTEXT_LINE_COUNT, u32::MAX),
+                            Bias::Left,
+                        );
                         let excerpt_id = excerpts.push_excerpt(
                             ExcerptProperties {
                                 buffer: &buffer,
@@ -296,10 +301,8 @@ mod tests {
             b(y);
             // comment 1
             // comment 2
-            // comment 3
-            // comment 4
-            d(y);
-            e(x);
+            c(y);
+            d(x);
         }
         "
         .unindent();
@@ -310,6 +313,18 @@ mod tests {
                 .update_diagnostics(
                     None,
                     vec![
+                        DiagnosticEntry {
+                            range: PointUtf16::new(1, 8)..PointUtf16::new(1, 9),
+                            diagnostic: Diagnostic {
+                                message:
+                                    "move occurs because `x` has type `Vec<char>`, which does not implement the `Copy` trait"
+                                        .to_string(),
+                                severity: DiagnosticSeverity::INFORMATION,
+                                is_primary: false,
+                                group_id: 1,
+                                ..Default::default()
+                            },
+                        },
                         DiagnosticEntry {
                             range: PointUtf16::new(2, 8)..PointUtf16::new(2, 9),
                             diagnostic: Diagnostic {
@@ -322,6 +337,16 @@ mod tests {
                                 ..Default::default()
                             },
                         },
+                        DiagnosticEntry {
+                            range: PointUtf16::new(3, 6)..PointUtf16::new(3, 7),
+                            diagnostic: Diagnostic {
+                                message: "value moved here".to_string(),
+                                severity: DiagnosticSeverity::INFORMATION,
+                                is_primary: false,
+                                group_id: 1,
+                                ..Default::default()
+                            },
+                        },
                         DiagnosticEntry {
                             range: PointUtf16::new(4, 6)..PointUtf16::new(4, 7),
                             diagnostic: Diagnostic {
@@ -333,7 +358,7 @@ mod tests {
                             },
                         },
                         DiagnosticEntry {
-                            range: PointUtf16::new(8, 6)..PointUtf16::new(8, 7),
+                            range: PointUtf16::new(7, 6)..PointUtf16::new(7, 7),
                             diagnostic: Diagnostic {
                                 message: "use of moved value\nvalue used here after move".to_string(),
                                 severity: DiagnosticSeverity::ERROR,
@@ -342,6 +367,16 @@ mod tests {
                                 ..Default::default()
                             },
                         },
+                        DiagnosticEntry {
+                            range: PointUtf16::new(8, 6)..PointUtf16::new(8, 7),
+                            diagnostic: Diagnostic {
+                                message: "use of moved value\nvalue used here after move".to_string(),
+                                severity: DiagnosticSeverity::ERROR,
+                                is_primary: true,
+                                group_id: 1,
+                                ..Default::default()
+                            },
+                        },
                     ],
                     cx,
                 )
@@ -351,22 +386,40 @@ mod tests {
 
         view.update(cx, |view, cx| {
             view.populate_excerpts(buffer, cx);
+            let editor = view.editor.update(cx, |editor, cx| editor.snapshot(cx));
+
             assert_eq!(
-                view.editor.update(cx, |editor, cx| editor.display_text(cx)),
+                editor.text(),
                 concat!(
-                    "\n", // primary diagnostic message
+                    // Diagnostic group 1 (error for `y`)
+                    "\n", // primary message
                     "\n", // filename
                     "    let x = vec![];\n",
                     "    let y = vec![];\n",
-                    "    a(x);\n",
-                    "\n", // context ellipsis
+                    "\n", // supporting diagnostic
                     "    a(x);\n",
                     "    b(y);\n",
+                    "\n", // supporting diagnostic
                     "    // comment 1\n",
+                    "    // comment 2\n",
+                    "    c(y);\n",
+                    "\n", // supporting diagnostic
+                    "    d(x);\n",
+                    // Diagnostic group 2 (error for `x`)
+                    "\n", // primary message
+                    "\n", // filename
+                    "fn main() {\n",
+                    "    let x = vec![];\n",
+                    "\n", // supporting diagnostic
+                    "    let y = vec![];\n",
+                    "    a(x);\n",
+                    "\n", // supporting diagnostic
+                    "    b(y);\n",
                     "\n", // context ellipsis
-                    "    // comment 3\n",
-                    "    // comment 4\n",
-                    "    d(y);"
+                    "    c(y);\n",
+                    "    d(x);\n",
+                    "\n", // supporting diagnostic
+                    "}"
                 )
             );
         });

crates/server/src/auth.rs 🔗

@@ -11,6 +11,7 @@ use oauth2::{
     TokenResponse as _, TokenUrl,
 };
 use rand::thread_rng;
+use rpc::auth as zed_auth;
 use scrypt::{
     password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
     Scrypt,
@@ -19,7 +20,6 @@ use serde::{Deserialize, Serialize};
 use std::{borrow::Cow, convert::TryFrom, sync::Arc};
 use surf::{StatusCode, Url};
 use tide::{log, Error, Server};
-use rpc::auth as zed_auth;
 
 static CURRENT_GITHUB_USER: &'static str = "current_github_user";
 static GITHUB_AUTH_URL: &'static str = "https://github.com/login/oauth/authorize";

crates/server/src/releases.rs 🔗

@@ -2,16 +2,15 @@ use crate::{
     auth::RequestExt as _, github::Release, AppState, LayoutData, Request, RequestExt as _,
 };
 use comrak::ComrakOptions;
-use serde::{Serialize};
+use serde::Serialize;
 use std::sync::Arc;
-use tide::{http::mime};
+use tide::http::mime;
 
 pub fn add_routes(releases: &mut tide::Server<Arc<AppState>>) {
     releases.at("/releases").get(get_releases);
 }
 
 async fn get_releases(mut request: Request) -> tide::Result {
-
     #[derive(Serialize)]
     struct ReleasesData {
         #[serde(flatten)]
@@ -52,4 +51,4 @@ async fn get_releases(mut request: Request) -> tide::Result {
         .body(request.state().render_template("releases.hbs", &data)?)
         .content_type(mime::HTML)
         .build())
-}
+}

crates/text/src/tests.rs 🔗

@@ -561,7 +561,7 @@ fn test_random_concurrent_edits(mut rng: StdRng) {
         match rng.gen_range(0..=100) {
             0..=50 if mutation_count != 0 => {
                 let op = buffer.randomly_edit(&mut rng, 5).2;
-                network.broadcast(buffer.replica_id, vec!(op));
+                network.broadcast(buffer.replica_id, vec![op]);
                 log::info!("buffer {} text: {:?}", buffer.replica_id, buffer.text());
                 mutation_count -= 1;
             }

crates/theme_selector/src/theme_selector.rs 🔗

@@ -11,7 +11,7 @@ use parking_lot::Mutex;
 use postage::watch;
 use std::{cmp, sync::Arc};
 use theme::ThemeRegistry;
-use workspace::{Settings, Workspace, AppState};
+use workspace::{AppState, Settings, Workspace};
 
 #[derive(Clone)]
 pub struct ThemeSelectorParams {