diff options
-rw-r--r-- | crates/ra_hir/src/diagnostics.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/semantics.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir_def/src/diagnostics.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/diagnostics.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/diagnostics.rs | 31 | ||||
-rw-r--r-- | crates/ra_ide/src/diagnostics.rs | 28 | ||||
-rw-r--r-- | crates/ra_ide/src/diagnostics/diagnostics_with_fix.rs | 46 |
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 |
2 | pub use hir_def::diagnostics::UnresolvedModule; | 2 | pub use hir_def::diagnostics::UnresolvedModule; |
3 | pub use hir_expand::diagnostics::{ | 3 | pub use hir_expand::diagnostics::{Diagnostic, DiagnosticSink, DiagnosticSinkBuilder}; |
4 | Diagnostic, DiagnosticSink, DiagnosticSinkBuilder, DiagnosticWithFix, | ||
5 | }; | ||
6 | pub use hir_ty::diagnostics::{ | 4 | pub 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 | }; |
11 | use hir_expand::{diagnostics::DiagnosticWithFix, hygiene::Hygiene, name::AsName, ExpansionInfo}; | 11 | use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo}; |
12 | use hir_ty::associated_type_shorthand_candidates; | 12 | use hir_ty::associated_type_shorthand_candidates; |
13 | use itertools::Itertools; | 13 | use itertools::Itertools; |
14 | use ra_db::{FileId, FileRange}; | 14 | use 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 | ||
3 | use std::any::Any; | 3 | use std::any::Any; |
4 | 4 | ||
5 | use hir_expand::diagnostics::{Diagnostic, DiagnosticWithFix}; | 5 | use hir_expand::diagnostics::Diagnostic; |
6 | use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; | 6 | use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; |
7 | 7 | ||
8 | use hir_expand::{HirFileId, InFile}; | 8 | use hir_expand::{HirFileId, InFile}; |
@@ -25,11 +25,3 @@ impl Diagnostic for UnresolvedModule { | |||
25 | self | 25 | self |
26 | } | 26 | } |
27 | } | 27 | } |
28 | |||
29 | impl 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 | ||
19 | use ra_syntax::SyntaxNodePtr; | 19 | use ra_syntax::SyntaxNodePtr; |
20 | 20 | ||
21 | use crate::{db::AstDatabase, InFile}; | 21 | use crate::InFile; |
22 | 22 | ||
23 | pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { | 23 | pub 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 | ||
32 | pub trait DiagnosticWithFix { | ||
33 | type AST; | ||
34 | fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST>; | ||
35 | } | ||
36 | |||
37 | pub struct DiagnosticSink<'a> { | 32 | pub 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; | |||
6 | use std::any::Any; | 6 | use std::any::Any; |
7 | 7 | ||
8 | use hir_def::DefWithBodyId; | 8 | use hir_def::DefWithBodyId; |
9 | use hir_expand::diagnostics::{Diagnostic, DiagnosticSink, DiagnosticWithFix}; | 9 | use hir_expand::diagnostics::{Diagnostic, DiagnosticSink}; |
10 | use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; | 10 | use hir_expand::{name::Name, HirFileId, InFile}; |
11 | use ra_prof::profile; | 11 | use ra_prof::profile; |
12 | use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; | 12 | use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; |
13 | use stdx::format_to; | 13 | use stdx::format_to; |
@@ -46,15 +46,6 @@ impl Diagnostic for NoSuchField { | |||
46 | } | 46 | } |
47 | } | 47 | } |
48 | 48 | ||
49 | impl 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)] |
59 | pub struct MissingFields { | 50 | pub struct MissingFields { |
60 | pub file: HirFileId, | 51 | pub file: HirFileId, |
@@ -88,15 +79,6 @@ impl Diagnostic for MissingFields { | |||
88 | } | 79 | } |
89 | } | 80 | } |
90 | 81 | ||
91 | impl 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)] |
101 | pub struct MissingPatFields { | 83 | pub struct MissingPatFields { |
102 | pub file: HirFileId, | 84 | pub file: HirFileId, |
@@ -163,15 +145,6 @@ impl Diagnostic for MissingOkInTailExpr { | |||
163 | } | 145 | } |
164 | } | 146 | } |
165 | 147 | ||
166 | impl 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)] |
176 | pub struct BreakOutsideOfLoop { | 149 | pub 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 @@ | |||
7 | use std::cell::RefCell; | 7 | use std::cell::RefCell; |
8 | 8 | ||
9 | use hir::{ | 9 | use 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 | }; |
13 | use itertools::Itertools; | 14 | use itertools::Itertools; |
14 | use ra_db::SourceDatabase; | 15 | use ra_db::{SourceDatabase, Upcast}; |
15 | use ra_ide_db::RootDatabase; | 16 | use ra_ide_db::RootDatabase; |
16 | use ra_prof::profile; | 17 | use ra_prof::profile; |
17 | use ra_syntax::{ | 18 | use ra_syntax::{ |
@@ -23,6 +24,9 @@ use ra_text_edit::{TextEdit, TextEditBuilder}; | |||
23 | 24 | ||
24 | use crate::{Diagnostic, FileId, FileSystemEdit, Fix, SourceFileEdit}; | 25 | use crate::{Diagnostic, FileId, FileSystemEdit, Fix, SourceFileEdit}; |
25 | 26 | ||
27 | mod diagnostics_with_fix; | ||
28 | use diagnostics_with_fix::DiagnosticWithFix; | ||
29 | |||
26 | #[derive(Debug, Copy, Clone)] | 30 | #[derive(Debug, Copy, Clone)] |
27 | pub enum Severity { | 31 | pub 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 | ||
171 | fn 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 | |||
167 | fn missing_struct_field_fix( | 181 | fn 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 @@ | |||
1 | use hir::{ | ||
2 | db::AstDatabase, | ||
3 | diagnostics::{MissingFields, MissingOkInTailExpr, NoSuchField, UnresolvedModule}, | ||
4 | }; | ||
5 | use ra_syntax::ast; | ||
6 | |||
7 | // TODO kb | ||
8 | pub trait DiagnosticWithFix { | ||
9 | type AST; | ||
10 | fn fix_source(&self, db: &dyn AstDatabase) -> Option<Self::AST>; | ||
11 | } | ||
12 | |||
13 | impl 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 | |||
21 | impl 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 | |||
30 | impl 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 | |||
39 | impl 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 | } | ||