aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/diagnostics.rs4
-rw-r--r--crates/ra_hir/src/semantics.rs12
-rw-r--r--crates/ra_hir_def/src/diagnostics.rs10
-rw-r--r--crates/ra_hir_expand/src/diagnostics.rs7
-rw-r--r--crates/ra_hir_ty/src/diagnostics.rs31
-rw-r--r--crates/ra_ide/src/diagnostics.rs28
-rw-r--r--crates/ra_ide/src/diagnostics/diagnostics_with_fix.rs46
7 files changed, 75 insertions, 63 deletions
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
index 564f6a5db..363164b9b 100644
--- a/crates/ra_hir/src/diagnostics.rs
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -1,8 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2pub use hir_def::diagnostics::UnresolvedModule; 2pub use hir_def::diagnostics::UnresolvedModule;
3pub use hir_expand::diagnostics::{ 3pub use hir_expand::diagnostics::{Diagnostic, DiagnosticSink, DiagnosticSinkBuilder};
4 Diagnostic, DiagnosticSink, DiagnosticSinkBuilder, DiagnosticWithFix,
5};
6pub use hir_ty::diagnostics::{ 4pub use hir_ty::diagnostics::{
7 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField, 5 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField,
8}; 6};
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index c5bc2baff..e9f7a033c 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -8,7 +8,7 @@ use hir_def::{
8 resolver::{self, HasResolver, Resolver}, 8 resolver::{self, HasResolver, Resolver},
9 AsMacroCall, FunctionId, TraitId, VariantId, 9 AsMacroCall, FunctionId, TraitId, VariantId,
10}; 10};
11use hir_expand::{diagnostics::DiagnosticWithFix, hygiene::Hygiene, name::AsName, ExpansionInfo}; 11use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo};
12use hir_ty::associated_type_shorthand_candidates; 12use hir_ty::associated_type_shorthand_candidates;
13use itertools::Itertools; 13use itertools::Itertools;
14use ra_db::{FileId, FileRange}; 14use ra_db::{FileId, FileRange};
@@ -109,14 +109,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
109 self.imp.parse(file_id) 109 self.imp.parse(file_id)
110 } 110 }
111 111
112 pub fn diagnostic_fix_source<T: DiagnosticWithFix + Diagnostic>( 112 pub fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) {
113 &self, 113 self.imp.cache(root_node, file_id)
114 d: &T,
115 ) -> Option<<T as DiagnosticWithFix>::AST> {
116 let file_id = d.presentation().file_id;
117 let root = self.db.parse_or_expand(file_id)?;
118 self.imp.cache(root, file_id);
119 d.fix_source(self.db.upcast())
120 } 114 }
121 115
122 pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { 116 pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
diff --git a/crates/ra_hir_def/src/diagnostics.rs b/crates/ra_hir_def/src/diagnostics.rs
index 033be683c..9435c7254 100644
--- a/crates/ra_hir_def/src/diagnostics.rs
+++ b/crates/ra_hir_def/src/diagnostics.rs
@@ -2,7 +2,7 @@
2 2
3use std::any::Any; 3use std::any::Any;
4 4
5use hir_expand::diagnostics::{Diagnostic, DiagnosticWithFix}; 5use hir_expand::diagnostics::Diagnostic;
6use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; 6use ra_syntax::{ast, AstPtr, SyntaxNodePtr};
7 7
8use hir_expand::{HirFileId, InFile}; 8use hir_expand::{HirFileId, InFile};
@@ -25,11 +25,3 @@ impl Diagnostic for UnresolvedModule {
25 self 25 self
26 } 26 }
27} 27}
28
29impl DiagnosticWithFix for UnresolvedModule {
30 type AST = ast::Module;
31 fn fix_source(&self, db: &dyn hir_expand::db::AstDatabase) -> Option<Self::AST> {
32 let root = db.parse_or_expand(self.file)?;
33 Some(self.decl.to_node(&root))
34 }
35}
diff --git a/crates/ra_hir_expand/src/diagnostics.rs b/crates/ra_hir_expand/src/diagnostics.rs
index 62a09a73a..8358c488b 100644
--- a/crates/ra_hir_expand/src/diagnostics.rs
+++ b/crates/ra_hir_expand/src/diagnostics.rs
@@ -18,7 +18,7 @@ use std::{any::Any, fmt};
18 18
19use ra_syntax::SyntaxNodePtr; 19use ra_syntax::SyntaxNodePtr;
20 20
21use crate::{db::AstDatabase, InFile}; 21use crate::InFile;
22 22
23pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { 23pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static {
24 fn message(&self) -> String; 24 fn message(&self) -> String;
@@ -29,11 +29,6 @@ pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static {
29 } 29 }
30} 30}
31 31
32pub trait DiagnosticWithFix {
33 type AST;
34 fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST>;
35}
36
37pub struct DiagnosticSink<'a> { 32pub struct DiagnosticSink<'a> {
38 callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>, 33 callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>,
39 filters: Vec<Box<dyn FnMut(&dyn Diagnostic) -> bool + 'a>>, 34 filters: Vec<Box<dyn FnMut(&dyn Diagnostic) -> bool + 'a>>,
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs
index b34ba5bfc..24435e8a7 100644
--- a/crates/ra_hir_ty/src/diagnostics.rs
+++ b/crates/ra_hir_ty/src/diagnostics.rs
@@ -6,8 +6,8 @@ mod unsafe_check;
6use std::any::Any; 6use std::any::Any;
7 7
8use hir_def::DefWithBodyId; 8use hir_def::DefWithBodyId;
9use hir_expand::diagnostics::{Diagnostic, DiagnosticSink, DiagnosticWithFix}; 9use hir_expand::diagnostics::{Diagnostic, DiagnosticSink};
10use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; 10use hir_expand::{name::Name, HirFileId, InFile};
11use ra_prof::profile; 11use ra_prof::profile;
12use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; 12use ra_syntax::{ast, AstPtr, SyntaxNodePtr};
13use stdx::format_to; 13use stdx::format_to;
@@ -46,15 +46,6 @@ impl Diagnostic for NoSuchField {
46 } 46 }
47} 47}
48 48
49impl DiagnosticWithFix for NoSuchField {
50 type AST = ast::RecordExprField;
51
52 fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST> {
53 let root = db.parse_or_expand(self.file)?;
54 Some(self.field.to_node(&root))
55 }
56}
57
58#[derive(Debug)] 49#[derive(Debug)]
59pub struct MissingFields { 50pub struct MissingFields {
60 pub file: HirFileId, 51 pub file: HirFileId,
@@ -88,15 +79,6 @@ impl Diagnostic for MissingFields {
88 } 79 }
89} 80}
90 81
91impl DiagnosticWithFix for MissingFields {
92 type AST = ast::RecordExpr;
93
94 fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST> {
95 let root = db.parse_or_expand(self.file)?;
96 Some(self.field_list_parent.to_node(&root))
97 }
98}
99
100#[derive(Debug)] 82#[derive(Debug)]
101pub struct MissingPatFields { 83pub struct MissingPatFields {
102 pub file: HirFileId, 84 pub file: HirFileId,
@@ -163,15 +145,6 @@ impl Diagnostic for MissingOkInTailExpr {
163 } 145 }
164} 146}
165 147
166impl DiagnosticWithFix for MissingOkInTailExpr {
167 type AST = ast::Expr;
168
169 fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST> {
170 let root = db.parse_or_expand(self.file)?;
171 Some(self.expr.to_node(&root))
172 }
173}
174
175#[derive(Debug)] 148#[derive(Debug)]
176pub struct BreakOutsideOfLoop { 149pub struct BreakOutsideOfLoop {
177 pub file: HirFileId, 150 pub file: HirFileId,
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs
index 043ce357b..ca1a7c1aa 100644
--- a/crates/ra_ide/src/diagnostics.rs
+++ b/crates/ra_ide/src/diagnostics.rs
@@ -7,11 +7,12 @@
7use std::cell::RefCell; 7use std::cell::RefCell;
8 8
9use hir::{ 9use hir::{
10 db::AstDatabase,
10 diagnostics::{Diagnostic as _, DiagnosticSinkBuilder}, 11 diagnostics::{Diagnostic as _, DiagnosticSinkBuilder},
11 HasSource, HirDisplay, Semantics, VariantDef, 12 HasSource, HirDisplay, Semantics, VariantDef,
12}; 13};
13use itertools::Itertools; 14use itertools::Itertools;
14use ra_db::SourceDatabase; 15use ra_db::{SourceDatabase, Upcast};
15use ra_ide_db::RootDatabase; 16use ra_ide_db::RootDatabase;
16use ra_prof::profile; 17use ra_prof::profile;
17use ra_syntax::{ 18use ra_syntax::{
@@ -23,6 +24,9 @@ use ra_text_edit::{TextEdit, TextEditBuilder};
23 24
24use crate::{Diagnostic, FileId, FileSystemEdit, Fix, SourceFileEdit}; 25use crate::{Diagnostic, FileId, FileSystemEdit, Fix, SourceFileEdit};
25 26
27mod diagnostics_with_fix;
28use diagnostics_with_fix::DiagnosticWithFix;
29
26#[derive(Debug, Copy, Clone)] 30#[derive(Debug, Copy, Clone)]
27pub enum Severity { 31pub enum Severity {
28 Error, 32 Error,
@@ -62,8 +66,7 @@ pub(crate) fn diagnostics(
62 } 66 }
63 .into(), 67 .into(),
64 ); 68 );
65 let fix = sema 69 let fix = diagnostic_fix_source(&sema, d)
66 .diagnostic_fix_source(d)
67 .map(|unresolved_module| unresolved_module.syntax().text_range()) 70 .map(|unresolved_module| unresolved_module.syntax().text_range())
68 .map(|fix_range| (fix, fix_range)); 71 .map(|fix_range| (fix, fix_range));
69 72
@@ -84,7 +87,7 @@ pub(crate) fn diagnostics(
84 let fix = if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) { 87 let fix = if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) {
85 None 88 None
86 } else { 89 } else {
87 sema.diagnostic_fix_source(d) 90 diagnostic_fix_source(&sema, d)
88 .and_then(|record_expr| record_expr.record_expr_field_list()) 91 .and_then(|record_expr| record_expr.record_expr_field_list())
89 .map(|old_field_list| { 92 .map(|old_field_list| {
90 let mut new_field_list = old_field_list.clone(); 93 let mut new_field_list = old_field_list.clone();
@@ -105,6 +108,7 @@ pub(crate) fn diagnostics(
105 ( 108 (
106 Fix::new("Fill struct fields", SourceFileEdit { file_id, edit }.into()), 109 Fix::new("Fill struct fields", SourceFileEdit { file_id, edit }.into()),
107 sema.original_range(&old_field_list.syntax()).range, 110 sema.original_range(&old_field_list.syntax()).range,
111 // old_field_list.syntax().text_range(),
108 ) 112 )
109 }) 113 })
110 }; 114 };
@@ -118,7 +122,7 @@ pub(crate) fn diagnostics(
118 Some(()) 122 Some(())
119 }) 123 })
120 .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| { 124 .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| {
121 let fix = sema.diagnostic_fix_source(d).map(|tail_expr| { 125 let fix = diagnostic_fix_source(&sema, d).map(|tail_expr| {
122 let tail_expr_range = tail_expr.syntax().text_range(); 126 let tail_expr_range = tail_expr.syntax().text_range();
123 let edit = 127 let edit =
124 TextEdit::replace(tail_expr_range, format!("Ok({})", tail_expr.syntax())); 128 TextEdit::replace(tail_expr_range, format!("Ok({})", tail_expr.syntax()));
@@ -140,7 +144,7 @@ pub(crate) fn diagnostics(
140 message: d.message(), 144 message: d.message(),
141 severity: Severity::Error, 145 severity: Severity::Error,
142 fix: missing_struct_field_fix(&sema, file_id, d).and_then(|fix| { 146 fix: missing_struct_field_fix(&sema, file_id, d).and_then(|fix| {
143 Some((fix, sema.diagnostic_fix_source(d)?.syntax().text_range())) 147 Some((fix, diagnostic_fix_source(&sema, d)?.syntax().text_range()))
144 }), 148 }),
145 }); 149 });
146 Some(()) 150 Some(())
@@ -164,12 +168,22 @@ pub(crate) fn diagnostics(
164 res.into_inner() 168 res.into_inner()
165} 169}
166 170
171fn diagnostic_fix_source<T: DiagnosticWithFix + hir::diagnostics::Diagnostic>(
172 sema: &Semantics<RootDatabase>,
173 d: &T,
174) -> Option<<T as DiagnosticWithFix>::AST> {
175 let file_id = d.presentation().file_id;
176 let root = sema.db.parse_or_expand(file_id)?;
177 sema.cache(root, file_id);
178 d.fix_source(sema.db.upcast())
179}
180
167fn missing_struct_field_fix( 181fn missing_struct_field_fix(
168 sema: &Semantics<RootDatabase>, 182 sema: &Semantics<RootDatabase>,
169 usage_file_id: FileId, 183 usage_file_id: FileId,
170 d: &hir::diagnostics::NoSuchField, 184 d: &hir::diagnostics::NoSuchField,
171) -> Option<Fix> { 185) -> Option<Fix> {
172 let record_expr_field = sema.diagnostic_fix_source(d)?; 186 let record_expr_field = diagnostic_fix_source(&sema, d)?;
173 187
174 let record_lit = ast::RecordExpr::cast(record_expr_field.syntax().parent()?.parent()?)?; 188 let record_lit = ast::RecordExpr::cast(record_expr_field.syntax().parent()?.parent()?)?;
175 let def_id = sema.resolve_variant(record_lit)?; 189 let def_id = sema.resolve_variant(record_lit)?;
diff --git a/crates/ra_ide/src/diagnostics/diagnostics_with_fix.rs b/crates/ra_ide/src/diagnostics/diagnostics_with_fix.rs
new file mode 100644
index 000000000..8578a90ec
--- /dev/null
+++ b/crates/ra_ide/src/diagnostics/diagnostics_with_fix.rs
@@ -0,0 +1,46 @@
1use hir::{
2 db::AstDatabase,
3 diagnostics::{MissingFields, MissingOkInTailExpr, NoSuchField, UnresolvedModule},
4};
5use ra_syntax::ast;
6
7// TODO kb
8pub trait DiagnosticWithFix {
9 type AST;
10 fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST>;
11}
12
13impl DiagnosticWithFix for UnresolvedModule {
14 type AST = ast::Module;
15 fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST> {
16 let root = db.parse_or_expand(self.file)?;
17 Some(self.decl.to_node(&root))
18 }
19}
20
21impl DiagnosticWithFix for NoSuchField {
22 type AST = ast::RecordExprField;
23
24 fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST> {
25 let root = db.parse_or_expand(self.file)?;
26 Some(self.field.to_node(&root))
27 }
28}
29
30impl DiagnosticWithFix for MissingFields {
31 type AST = ast::RecordExpr;
32
33 fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST> {
34 let root = db.parse_or_expand(self.file)?;
35 Some(self.field_list_parent.to_node(&root))
36 }
37}
38
39impl DiagnosticWithFix for MissingOkInTailExpr {
40 type AST = ast::Expr;
41
42 fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST> {
43 let root = db.parse_or_expand(self.file)?;
44 Some(self.expr.to_node(&root))
45 }
46}