aboutsummaryrefslogtreecommitdiff
path: root/crates/ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide')
-rw-r--r--crates/ide/src/diagnostics.rs89
-rw-r--r--crates/ide/src/diagnostics/field_shorthand.rs32
-rw-r--r--crates/ide/src/doc_links.rs8
-rw-r--r--crates/ide/src/hover.rs2
-rw-r--r--crates/ide/src/inlay_hints.rs24
-rw-r--r--crates/ide/src/prime_caches.rs3
-rw-r--r--crates/ide/src/status.rs2
7 files changed, 85 insertions, 75 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 1e5ea4617..90574cb35 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -10,7 +10,10 @@ mod field_shorthand;
10use std::cell::RefCell; 10use std::cell::RefCell;
11 11
12use base_db::SourceDatabase; 12use base_db::SourceDatabase;
13use hir::{diagnostics::DiagnosticSinkBuilder, Semantics}; 13use hir::{
14 diagnostics::{Diagnostic as _, DiagnosticSinkBuilder},
15 Semantics,
16};
14use ide_db::RootDatabase; 17use ide_db::RootDatabase;
15use itertools::Itertools; 18use itertools::Itertools;
16use rustc_hash::FxHashSet; 19use rustc_hash::FxHashSet;
@@ -31,6 +34,25 @@ pub struct Diagnostic {
31 pub range: TextRange, 34 pub range: TextRange,
32 pub severity: Severity, 35 pub severity: Severity,
33 pub fix: Option<Fix>, 36 pub fix: Option<Fix>,
37 pub unused: bool,
38}
39
40impl Diagnostic {
41 fn error(range: TextRange, message: String) -> Self {
42 Self { message, range, severity: Severity::Error, fix: None, unused: false }
43 }
44
45 fn hint(range: TextRange, message: String) -> Self {
46 Self { message, range, severity: Severity::WeakWarning, fix: None, unused: false }
47 }
48
49 fn with_fix(self, fix: Option<Fix>) -> Self {
50 Self { fix, ..self }
51 }
52
53 fn with_unused(self, unused: bool) -> Self {
54 Self { unused, ..self }
55 }
34} 56}
35 57
36#[derive(Debug)] 58#[derive(Debug)]
@@ -71,13 +93,13 @@ pub(crate) fn diagnostics(
71 let mut res = Vec::new(); 93 let mut res = Vec::new();
72 94
73 // [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily. 95 // [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily.
74 res.extend(parse.errors().iter().take(128).map(|err| Diagnostic { 96 res.extend(
75 // name: None, 97 parse
76 range: err.range(), 98 .errors()
77 message: format!("Syntax Error: {}", err), 99 .iter()
78 severity: Severity::Error, 100 .take(128)
79 fix: None, 101 .map(|err| Diagnostic::error(err.range(), format!("Syntax Error: {}", err))),
80 })); 102 );
81 103
82 for node in parse.tree().syntax().descendants() { 104 for node in parse.tree().syntax().descendants() {
83 check_unnecessary_braces_in_use_statement(&mut res, file_id, &node); 105 check_unnecessary_braces_in_use_statement(&mut res, file_id, &node);
@@ -100,6 +122,13 @@ pub(crate) fn diagnostics(
100 .on::<hir::diagnostics::IncorrectCase, _>(|d| { 122 .on::<hir::diagnostics::IncorrectCase, _>(|d| {
101 res.borrow_mut().push(warning_with_fix(d, &sema)); 123 res.borrow_mut().push(warning_with_fix(d, &sema));
102 }) 124 })
125 .on::<hir::diagnostics::InactiveCode, _>(|d| {
126 // Override severity and mark as unused.
127 res.borrow_mut().push(
128 Diagnostic::hint(sema.diagnostics_display_range(d).range, d.message())
129 .with_unused(true),
130 );
131 })
103 // Only collect experimental diagnostics when they're enabled. 132 // Only collect experimental diagnostics when they're enabled.
104 .filter(|diag| !(diag.is_experimental() && config.disable_experimental)) 133 .filter(|diag| !(diag.is_experimental() && config.disable_experimental))
105 .filter(|diag| !config.disabled.contains(diag.code().as_str())); 134 .filter(|diag| !config.disabled.contains(diag.code().as_str()));
@@ -108,13 +137,8 @@ pub(crate) fn diagnostics(
108 let mut sink = sink_builder 137 let mut sink = sink_builder
109 // Diagnostics not handled above get no fix and default treatment. 138 // Diagnostics not handled above get no fix and default treatment.
110 .build(|d| { 139 .build(|d| {
111 res.borrow_mut().push(Diagnostic { 140 res.borrow_mut()
112 // name: Some(d.name().into()), 141 .push(Diagnostic::error(sema.diagnostics_display_range(d).range, d.message()));
113 message: d.message(),
114 range: sema.diagnostics_display_range(d).range,
115 severity: Severity::Error,
116 fix: None,
117 })
118 }); 142 });
119 143
120 if let Some(m) = sema.to_module_def(file_id) { 144 if let Some(m) = sema.to_module_def(file_id) {
@@ -125,22 +149,11 @@ pub(crate) fn diagnostics(
125} 149}
126 150
127fn diagnostic_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic { 151fn diagnostic_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic {
128 Diagnostic { 152 Diagnostic::error(sema.diagnostics_display_range(d).range, d.message()).with_fix(d.fix(&sema))
129 // name: Some(d.name().into()),
130 range: sema.diagnostics_display_range(d).range,
131 message: d.message(),
132 severity: Severity::Error,
133 fix: d.fix(&sema),
134 }
135} 153}
136 154
137fn warning_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic { 155fn warning_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic {
138 Diagnostic { 156 Diagnostic::hint(sema.diagnostics_display_range(d).range, d.message()).with_fix(d.fix(&sema))
139 range: sema.diagnostics_display_range(d).range,
140 message: d.message(),
141 severity: Severity::WeakWarning,
142 fix: d.fix(&sema),
143 }
144} 157}
145 158
146fn check_unnecessary_braces_in_use_statement( 159fn check_unnecessary_braces_in_use_statement(
@@ -161,17 +174,14 @@ fn check_unnecessary_braces_in_use_statement(
161 edit_builder.finish() 174 edit_builder.finish()
162 }); 175 });
163 176
164 acc.push(Diagnostic { 177 acc.push(
165 // name: None, 178 Diagnostic::hint(use_range, "Unnecessary braces in use statement".to_string())
166 range: use_range, 179 .with_fix(Some(Fix::new(
167 message: "Unnecessary braces in use statement".to_string(), 180 "Remove unnecessary braces",
168 severity: Severity::WeakWarning, 181 SourceFileEdit { file_id, edit }.into(),
169 fix: Some(Fix::new( 182 use_range,
170 "Remove unnecessary braces", 183 ))),
171 SourceFileEdit { file_id, edit }.into(), 184 );
172 use_range,
173 )),
174 });
175 } 185 }
176 186
177 Some(()) 187 Some(())
@@ -578,6 +588,7 @@ fn test_fn() {
578 fix_trigger_range: 0..8, 588 fix_trigger_range: 0..8,
579 }, 589 },
580 ), 590 ),
591 unused: false,
581 }, 592 },
582 ] 593 ]
583 "#]], 594 "#]],
diff --git a/crates/ide/src/diagnostics/field_shorthand.rs b/crates/ide/src/diagnostics/field_shorthand.rs
index 2c4acd783..54e9fce9e 100644
--- a/crates/ide/src/diagnostics/field_shorthand.rs
+++ b/crates/ide/src/diagnostics/field_shorthand.rs
@@ -6,7 +6,7 @@ use ide_db::source_change::SourceFileEdit;
6use syntax::{ast, match_ast, AstNode, SyntaxNode}; 6use syntax::{ast, match_ast, AstNode, SyntaxNode};
7use text_edit::TextEdit; 7use text_edit::TextEdit;
8 8
9use crate::{Diagnostic, Fix, Severity}; 9use crate::{Diagnostic, Fix};
10 10
11pub(super) fn check(acc: &mut Vec<Diagnostic>, file_id: FileId, node: &SyntaxNode) { 11pub(super) fn check(acc: &mut Vec<Diagnostic>, file_id: FileId, node: &SyntaxNode) {
12 match_ast! { 12 match_ast! {
@@ -46,17 +46,15 @@ fn check_expr_field_shorthand(
46 let edit = edit_builder.finish(); 46 let edit = edit_builder.finish();
47 47
48 let field_range = record_field.syntax().text_range(); 48 let field_range = record_field.syntax().text_range();
49 acc.push(Diagnostic { 49 acc.push(
50 // name: None, 50 Diagnostic::hint(field_range, "Shorthand struct initialization".to_string()).with_fix(
51 range: field_range, 51 Some(Fix::new(
52 message: "Shorthand struct initialization".to_string(), 52 "Use struct shorthand initialization",
53 severity: Severity::WeakWarning, 53 SourceFileEdit { file_id, edit }.into(),
54 fix: Some(Fix::new( 54 field_range,
55 "Use struct shorthand initialization", 55 )),
56 SourceFileEdit { file_id, edit }.into(), 56 ),
57 field_range, 57 );
58 )),
59 });
60 } 58 }
61} 59}
62 60
@@ -88,17 +86,13 @@ fn check_pat_field_shorthand(
88 let edit = edit_builder.finish(); 86 let edit = edit_builder.finish();
89 87
90 let field_range = record_pat_field.syntax().text_range(); 88 let field_range = record_pat_field.syntax().text_range();
91 acc.push(Diagnostic { 89 acc.push(Diagnostic::hint(field_range, "Shorthand struct pattern".to_string()).with_fix(
92 // name: None, 90 Some(Fix::new(
93 range: field_range,
94 message: "Shorthand struct pattern".to_string(),
95 severity: Severity::WeakWarning,
96 fix: Some(Fix::new(
97 "Use struct field shorthand", 91 "Use struct field shorthand",
98 SourceFileEdit { file_id, edit }.into(), 92 SourceFileEdit { file_id, edit }.into(),
99 field_range, 93 field_range,
100 )), 94 )),
101 }); 95 ));
102 } 96 }
103} 97}
104 98
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index d9dc63b33..b9d8b8a2b 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -130,7 +130,7 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> {
130 let module = definition.module(db)?; 130 let module = definition.module(db)?;
131 let krate = module.krate(); 131 let krate = module.krate();
132 let import_map = db.import_map(krate.into()); 132 let import_map = db.import_map(krate.into());
133 let base = once(krate.declaration_name(db)?.to_string()) 133 let base = once(krate.display_name(db)?.to_string())
134 .chain(import_map.path_of(ns)?.segments.iter().map(|name| name.to_string())) 134 .chain(import_map.path_of(ns)?.segments.iter().map(|name| name.to_string()))
135 .join("/"); 135 .join("/");
136 136
@@ -188,7 +188,7 @@ fn rewrite_intra_doc_link(
188 let krate = resolved.module(db)?.krate(); 188 let krate = resolved.module(db)?.krate();
189 let canonical_path = resolved.canonical_path(db)?; 189 let canonical_path = resolved.canonical_path(db)?;
190 let new_target = get_doc_url(db, &krate)? 190 let new_target = get_doc_url(db, &krate)?
191 .join(&format!("{}/", krate.declaration_name(db)?)) 191 .join(&format!("{}/", krate.display_name(db)?))
192 .ok()? 192 .ok()?
193 .join(&canonical_path.replace("::", "/")) 193 .join(&canonical_path.replace("::", "/"))
194 .ok()? 194 .ok()?
@@ -208,7 +208,7 @@ fn rewrite_url_link(db: &RootDatabase, def: ModuleDef, target: &str) -> Option<S
208 let module = def.module(db)?; 208 let module = def.module(db)?;
209 let krate = module.krate(); 209 let krate = module.krate();
210 let canonical_path = def.canonical_path(db)?; 210 let canonical_path = def.canonical_path(db)?;
211 let base = format!("{}/{}", krate.declaration_name(db)?, canonical_path.replace("::", "/")); 211 let base = format!("{}/{}", krate.display_name(db)?, canonical_path.replace("::", "/"));
212 212
213 get_doc_url(db, &krate) 213 get_doc_url(db, &krate)
214 .and_then(|url| url.join(&base).ok()) 214 .and_then(|url| url.join(&base).ok())
@@ -357,7 +357,7 @@ fn get_doc_url(db: &RootDatabase, krate: &Crate) -> Option<Url> {
357 // 357 //
358 // FIXME: clicking on the link should just open the file in the editor, 358 // FIXME: clicking on the link should just open the file in the editor,
359 // instead of falling back to external urls. 359 // instead of falling back to external urls.
360 Some(format!("https://docs.rs/{}/*/", krate.declaration_name(db)?)) 360 Some(format!("https://docs.rs/{}/*/", krate.display_name(db)?))
361 }) 361 })
362 .and_then(|s| Url::parse(&s).ok()) 362 .and_then(|s| Url::parse(&s).ok())
363} 363}
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 845333e2a..6466422c5 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -300,7 +300,7 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String>
300 300
301fn render_path(db: &RootDatabase, module: Module, item_name: Option<String>) -> String { 301fn render_path(db: &RootDatabase, module: Module, item_name: Option<String>) -> String {
302 let crate_name = 302 let crate_name =
303 db.crate_graph()[module.krate().into()].declaration_name.as_ref().map(ToString::to_string); 303 db.crate_graph()[module.krate().into()].display_name.as_ref().map(|it| it.to_string());
304 let module_path = module 304 let module_path = module
305 .path_to_root(db) 305 .path_to_root(db)
306 .into_iter() 306 .into_iter()
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index e2079bbcf..cccea129a 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -1,15 +1,14 @@
1use assists::utils::FamousDefs; 1use assists::utils::FamousDefs;
2use either::Either;
2use hir::{known, HirDisplay, Semantics}; 3use hir::{known, HirDisplay, Semantics};
3use ide_db::RootDatabase; 4use ide_db::RootDatabase;
4use stdx::to_lower_snake_case; 5use stdx::to_lower_snake_case;
5use syntax::{ 6use syntax::{
6 ast::{self, ArgListOwner, AstNode}, 7 ast::{self, ArgListOwner, AstNode, NameOwner},
7 match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, TextRange, T, 8 match_ast, Direction, NodeOrToken, SmolStr, SyntaxKind, TextRange, T,
8}; 9};
9 10
10use crate::FileId; 11use crate::FileId;
11use ast::NameOwner;
12use either::Either;
13 12
14#[derive(Clone, Debug, PartialEq, Eq)] 13#[derive(Clone, Debug, PartialEq, Eq)]
15pub struct InlayHintsConfig { 14pub struct InlayHintsConfig {
@@ -100,6 +99,9 @@ fn get_chaining_hints(
100 return None; 99 return None;
101 } 100 }
102 101
102 let krate = sema.scope(expr.syntax()).module().map(|it| it.krate());
103 let famous_defs = FamousDefs(&sema, krate);
104
103 let mut tokens = expr 105 let mut tokens = expr
104 .syntax() 106 .syntax()
105 .siblings_with_tokens(Direction::Next) 107 .siblings_with_tokens(Direction::Next)
@@ -129,7 +131,7 @@ fn get_chaining_hints(
129 acc.push(InlayHint { 131 acc.push(InlayHint {
130 range: expr.syntax().text_range(), 132 range: expr.syntax().text_range(),
131 kind: InlayKind::ChainingHint, 133 kind: InlayKind::ChainingHint,
132 label: hint_iterator(sema, config, &ty).unwrap_or_else(|| { 134 label: hint_iterator(sema, &famous_defs, config, &ty).unwrap_or_else(|| {
133 ty.display_truncated(sema.db, config.max_length).to_string().into() 135 ty.display_truncated(sema.db, config.max_length).to_string().into()
134 }), 136 }),
135 }); 137 });
@@ -189,6 +191,9 @@ fn get_bind_pat_hints(
189 return None; 191 return None;
190 } 192 }
191 193
194 let krate = sema.scope(pat.syntax()).module().map(|it| it.krate());
195 let famous_defs = FamousDefs(&sema, krate);
196
192 let ty = sema.type_of_pat(&pat.clone().into())?; 197 let ty = sema.type_of_pat(&pat.clone().into())?;
193 198
194 if should_not_display_type_hint(sema, &pat, &ty) { 199 if should_not_display_type_hint(sema, &pat, &ty) {
@@ -197,7 +202,7 @@ fn get_bind_pat_hints(
197 acc.push(InlayHint { 202 acc.push(InlayHint {
198 range: pat.syntax().text_range(), 203 range: pat.syntax().text_range(),
199 kind: InlayKind::TypeHint, 204 kind: InlayKind::TypeHint,
200 label: hint_iterator(sema, config, &ty) 205 label: hint_iterator(sema, &famous_defs, config, &ty)
201 .unwrap_or_else(|| ty.display_truncated(sema.db, config.max_length).to_string().into()), 206 .unwrap_or_else(|| ty.display_truncated(sema.db, config.max_length).to_string().into()),
202 }); 207 });
203 208
@@ -207,6 +212,7 @@ fn get_bind_pat_hints(
207/// Checks if the type is an Iterator from std::iter and replaces its hint with an `impl Iterator<Item = Ty>`. 212/// Checks if the type is an Iterator from std::iter and replaces its hint with an `impl Iterator<Item = Ty>`.
208fn hint_iterator( 213fn hint_iterator(
209 sema: &Semantics<RootDatabase>, 214 sema: &Semantics<RootDatabase>,
215 famous_defs: &FamousDefs,
210 config: &InlayHintsConfig, 216 config: &InlayHintsConfig,
211 ty: &hir::Type, 217 ty: &hir::Type,
212) -> Option<SmolStr> { 218) -> Option<SmolStr> {
@@ -215,11 +221,11 @@ fn hint_iterator(
215 .last() 221 .last()
216 .and_then(|strukt| strukt.as_adt())?; 222 .and_then(|strukt| strukt.as_adt())?;
217 let krate = strukt.krate(db)?; 223 let krate = strukt.krate(db)?;
218 if krate.declaration_name(db).as_deref() != Some("core") { 224 if krate != famous_defs.core()? {
219 return None; 225 return None;
220 } 226 }
221 let iter_trait = FamousDefs(sema, krate).core_iter_Iterator()?; 227 let iter_trait = famous_defs.core_iter_Iterator()?;
222 let iter_mod = FamousDefs(sema, krate).core_iter()?; 228 let iter_mod = famous_defs.core_iter()?;
223 // assert this struct comes from `core::iter` 229 // assert this struct comes from `core::iter`
224 iter_mod.visibility_of(db, &strukt.into()).filter(|&vis| vis == hir::Visibility::Public)?; 230 iter_mod.visibility_of(db, &strukt.into()).filter(|&vis| vis == hir::Visibility::Public)?;
225 if ty.impls_trait(db, iter_trait, &[]) { 231 if ty.impls_trait(db, iter_trait, &[]) {
@@ -231,7 +237,7 @@ fn hint_iterator(
231 const LABEL_START: &str = "impl Iterator<Item = "; 237 const LABEL_START: &str = "impl Iterator<Item = ";
232 const LABEL_END: &str = ">"; 238 const LABEL_END: &str = ">";
233 239
234 let ty_display = hint_iterator(sema, config, &ty) 240 let ty_display = hint_iterator(sema, famous_defs, config, &ty)
235 .map(|assoc_type_impl| assoc_type_impl.to_string()) 241 .map(|assoc_type_impl| assoc_type_impl.to_string())
236 .unwrap_or_else(|| { 242 .unwrap_or_else(|| {
237 ty.display_truncated( 243 ty.display_truncated(
diff --git a/crates/ide/src/prime_caches.rs b/crates/ide/src/prime_caches.rs
index 9687c2734..6944dbcd2 100644
--- a/crates/ide/src/prime_caches.rs
+++ b/crates/ide/src/prime_caches.rs
@@ -32,8 +32,7 @@ pub(crate) fn prime_caches(db: &RootDatabase, cb: &(dyn Fn(PrimeCachesProgress)
32 // Unfortunately rayon prevents panics from propagation out of a `scope`, which breaks 32 // Unfortunately rayon prevents panics from propagation out of a `scope`, which breaks
33 // cancellation, so we cannot use rayon. 33 // cancellation, so we cannot use rayon.
34 for (i, krate) in topo.iter().enumerate() { 34 for (i, krate) in topo.iter().enumerate() {
35 let crate_name = 35 let crate_name = graph[*krate].display_name.as_deref().unwrap_or_default().to_string();
36 graph[*krate].declaration_name.as_ref().map(ToString::to_string).unwrap_or_default();
37 36
38 cb(PrimeCachesProgress::StartedOnCrate { 37 cb(PrimeCachesProgress::StartedOnCrate {
39 on_crate: crate_name, 38 on_crate: crate_name,
diff --git a/crates/ide/src/status.rs b/crates/ide/src/status.rs
index f67f10491..0af84daa0 100644
--- a/crates/ide/src/status.rs
+++ b/crates/ide/src/status.rs
@@ -45,7 +45,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
45 match krate { 45 match krate {
46 Some(krate) => { 46 Some(krate) => {
47 let crate_graph = db.crate_graph(); 47 let crate_graph = db.crate_graph();
48 let display_crate = |krate: CrateId| match &crate_graph[krate].declaration_name { 48 let display_crate = |krate: CrateId| match &crate_graph[krate].display_name {
49 Some(it) => format!("{}({:?})", it, krate), 49 Some(it) => format!("{}({:?})", it, krate),
50 None => format!("{:?}", krate), 50 None => format!("{:?}", krate),
51 }; 51 };