aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src')
-rw-r--r--crates/ra_ide_api/src/diagnostics.rs123
1 files changed, 122 insertions, 1 deletions
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs
index b27cb690a..855a3ff0f 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide_api/src/diagnostics.rs
@@ -5,8 +5,9 @@ use hir::{source_binder, diagnostics::{Diagnostic as _, DiagnosticSink}};
5use ra_db::SourceDatabase; 5use ra_db::SourceDatabase;
6use ra_syntax::{ 6use ra_syntax::{
7 Location, SourceFile, SyntaxKind, TextRange, SyntaxNode, 7 Location, SourceFile, SyntaxKind, TextRange, SyntaxNode,
8 ast::{self, AstNode}, 8 ast::{self, AstNode, NamedFieldList, NamedField},
9}; 9};
10use ra_assists::ast_editor::{AstEditor, AstBuilder};
10use ra_text_edit::{TextEdit, TextEditBuilder}; 11use ra_text_edit::{TextEdit, TextEditBuilder};
11use ra_prof::profile; 12use ra_prof::profile;
12 13
@@ -48,6 +49,27 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
48 severity: Severity::Error, 49 severity: Severity::Error,
49 fix: Some(fix), 50 fix: Some(fix),
50 }) 51 })
52 })
53 .on::<hir::diagnostics::MissingFields, _>(|d| {
54 let file_id = d.file().original_file(db);
55 let source_file = db.parse(file_id);
56 let syntax_node = d.syntax_node_ptr();
57 let node = NamedFieldList::cast(syntax_node.to_node(&source_file)).unwrap();
58 let mut ast_editor = AstEditor::new(node);
59 for f in d.missed_fields.iter() {
60 ast_editor.append_field(&AstBuilder::<NamedField>::from_name(f));
61 }
62
63 let mut builder = TextEditBuilder::default();
64 ast_editor.into_text_edit(&mut builder);
65 let fix =
66 SourceChange::source_file_edit_from("fill struct fields", file_id, builder.finish());
67 res.borrow_mut().push(Diagnostic {
68 range: d.highlight_range(),
69 message: d.message(),
70 severity: Severity::Error,
71 fix: Some(fix),
72 })
51 }); 73 });
52 if let Some(m) = source_binder::module_from_file_id(db, file_id) { 74 if let Some(m) = source_binder::module_from_file_id(db, file_id) {
53 m.diagnostics(db, &mut sink); 75 m.diagnostics(db, &mut sink);
@@ -187,6 +209,105 @@ mod tests {
187 assert_eq_text!(after, &actual); 209 assert_eq_text!(after, &actual);
188 } 210 }
189 211
212 fn check_apply_diagnostic_fix(before: &str, after: &str) {
213 let (analysis, file_id) = single_file(before);
214 let diagnostic = analysis.diagnostics(file_id).unwrap().pop().unwrap();
215 let mut fix = diagnostic.fix.unwrap();
216 let edit = fix.source_file_edits.pop().unwrap().edit;
217 let actual = edit.apply(&before);
218 assert_eq_text!(after, &actual);
219 }
220
221 fn check_no_diagnostic(content: &str) {
222 let (analysis, file_id) = single_file(content);
223 let diagnostics = analysis.diagnostics(file_id).unwrap();
224 assert_eq!(diagnostics.len(), 0);
225 }
226
227 #[test]
228 fn test_fill_struct_fields_empty() {
229 let before = r"
230 struct TestStruct {
231 one: i32,
232 two: i64,
233 }
234
235 fn test_fn() {
236 let s = TestStruct{};
237 }
238 ";
239 let after = r"
240 struct TestStruct {
241 one: i32,
242 two: i64,
243 }
244
245 fn test_fn() {
246 let s = TestStruct{ one: (), two: ()};
247 }
248 ";
249 check_apply_diagnostic_fix(before, after);
250 }
251
252 #[test]
253 fn test_fill_struct_fields_partial() {
254 let before = r"
255 struct TestStruct {
256 one: i32,
257 two: i64,
258 }
259
260 fn test_fn() {
261 let s = TestStruct{ two: 2 };
262 }
263 ";
264 let after = r"
265 struct TestStruct {
266 one: i32,
267 two: i64,
268 }
269
270 fn test_fn() {
271 let s = TestStruct{ two: 2, one: () };
272 }
273 ";
274 check_apply_diagnostic_fix(before, after);
275 }
276
277 #[test]
278 fn test_fill_struct_fields_no_diagnostic() {
279 let content = r"
280 struct TestStruct {
281 one: i32,
282 two: i64,
283 }
284
285 fn test_fn() {
286 let one = 1;
287 let s = TestStruct{ one, two: 2 };
288 }
289 ";
290
291 check_no_diagnostic(content);
292 }
293
294 #[test]
295 fn test_fill_struct_fields_no_diagnostic_on_spread() {
296 let content = r"
297 struct TestStruct {
298 one: i32,
299 two: i64,
300 }
301
302 fn test_fn() {
303 let one = 1;
304 let s = TestStruct{ ..a };
305 }
306 ";
307
308 check_no_diagnostic(content);
309 }
310
190 #[test] 311 #[test]
191 fn test_unresolved_module_diagnostic() { 312 fn test_unresolved_module_diagnostic() {
192 let (analysis, file_id) = single_file("mod foo;"); 313 let (analysis, file_id) = single_file("mod foo;");