aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_cargo_watch/src/conv.rs128
-rw-r--r--crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_clippy_pass_by_ref.snap172
-rw-r--r--crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_handles_macro_location.snap76
-rw-r--r--crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_macro_compiler_error.snap102
-rw-r--r--crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_multi_line_fix.snap114
-rw-r--r--crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_incompatible_type_for_trait.snap76
-rw-r--r--crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_mismatched_type.snap76
-rw-r--r--crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_unused_variable.snap148
-rw-r--r--crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_wrong_number_of_parameters.snap108
-rw-r--r--crates/ra_cargo_watch/src/conv/test.rs148
-rw-r--r--crates/ra_cargo_watch/src/lib.rs32
-rw-r--r--crates/ra_db/src/fixture.rs12
-rw-r--r--crates/ra_db/src/input.rs43
-rw-r--r--crates/ra_db/src/lib.rs18
-rw-r--r--crates/ra_hir_def/src/test_db.rs10
-rw-r--r--crates/ra_hir_expand/src/builtin_macro.rs228
-rw-r--r--crates/ra_hir_expand/src/name.rs1
-rw-r--r--crates/ra_hir_expand/src/quote.rs1
-rw-r--r--crates/ra_hir_expand/src/test_db.rs9
-rw-r--r--crates/ra_hir_ty/src/test_db.rs7
-rw-r--r--crates/ra_hir_ty/src/tests/macros.rs20
-rw-r--r--crates/ra_ide/src/completion.rs4
-rw-r--r--crates/ra_ide/src/completion/complete_dot.rs2
-rw-r--r--crates/ra_ide/src/completion/complete_fn_param.rs2
-rw-r--r--crates/ra_ide/src/completion/complete_keyword.rs2
-rw-r--r--crates/ra_ide/src/completion/complete_macro_in_item_position.rs3
-rw-r--r--crates/ra_ide/src/completion/complete_path.rs2
-rw-r--r--crates/ra_ide/src/completion/complete_pattern.rs2
-rw-r--r--crates/ra_ide/src/completion/complete_postfix.rs2
-rw-r--r--crates/ra_ide/src/completion/complete_record_literal.rs2
-rw-r--r--crates/ra_ide/src/completion/complete_record_pattern.rs2
-rw-r--r--crates/ra_ide/src/completion/complete_scope.rs6
-rw-r--r--crates/ra_ide/src/completion/complete_snippet.rs2
-rw-r--r--crates/ra_ide/src/completion/complete_trait_impl.rs2
-rw-r--r--crates/ra_ide/src/completion/completion_item.rs23
-rw-r--r--crates/ra_ide/src/completion/presentation.rs48
-rw-r--r--crates/ra_ide/src/completion/test_utils.rs29
-rw-r--r--crates/ra_ide/src/hover.rs27
-rw-r--r--crates/ra_ide/src/lib.rs1
-rw-r--r--crates/ra_ide/src/mock_analysis.rs2
-rw-r--r--crates/ra_ide/src/parent_module.rs1
-rw-r--r--crates/ra_ide/src/references/rename.rs208
-rw-r--r--crates/ra_ide/src/typing.rs160
-rw-r--r--crates/ra_ide/src/typing/on_enter.rs216
-rw-r--r--crates/ra_ide_db/src/lib.rs7
-rw-r--r--crates/ra_ide_db/src/search.rs28
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs10
-rw-r--r--crates/ra_project_model/src/lib.rs25
-rw-r--r--crates/ra_syntax/src/ast.rs2
-rw-r--r--crates/ra_syntax/src/ast/generated.rs635
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rs3
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.txt38
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs5
-rw-r--r--crates/rust-analyzer/src/config.rs4
-rw-r--r--crates/rust-analyzer/src/main_loop.rs1
-rw-r--r--crates/rust-analyzer/src/world.rs38
-rw-r--r--editors/code/package.json7
-rw-r--r--editors/code/src/client.ts1
-rw-r--r--editors/code/src/config.ts1
-rw-r--r--xtask/src/codegen/gen_syntax.rs12
60 files changed, 2339 insertions, 755 deletions
diff --git a/crates/ra_cargo_watch/src/conv.rs b/crates/ra_cargo_watch/src/conv.rs
index 0246adfb5..c6f8ca329 100644
--- a/crates/ra_cargo_watch/src/conv.rs
+++ b/crates/ra_cargo_watch/src/conv.rs
@@ -8,6 +8,7 @@ use lsp_types::{
8 Location, NumberOrString, Position, Range, TextEdit, Url, WorkspaceEdit, 8 Location, NumberOrString, Position, Range, TextEdit, Url, WorkspaceEdit,
9}; 9};
10use std::{ 10use std::{
11 collections::HashMap,
11 fmt::Write, 12 fmt::Write,
12 path::{Component, Path, PathBuf, Prefix}, 13 path::{Component, Path, PathBuf, Prefix},
13 str::FromStr, 14 str::FromStr,
@@ -126,44 +127,34 @@ fn map_rust_child_diagnostic(
126 rd: &RustDiagnostic, 127 rd: &RustDiagnostic,
127 workspace_root: &PathBuf, 128 workspace_root: &PathBuf,
128) -> MappedRustChildDiagnostic { 129) -> MappedRustChildDiagnostic {
129 let span: &DiagnosticSpan = match rd.spans.iter().find(|s| s.is_primary) { 130 let spans: Vec<&DiagnosticSpan> = rd.spans.iter().filter(|s| s.is_primary).collect();
130 Some(span) => span, 131 if spans.is_empty() {
131 None => { 132 // `rustc` uses these spanless children as a way to print multi-line
132 // `rustc` uses these spanless children as a way to print multi-line 133 // messages
133 // messages 134 return MappedRustChildDiagnostic::MessageLine(rd.message.clone());
134 return MappedRustChildDiagnostic::MessageLine(rd.message.clone()); 135 }
136
137 let mut edit_map: HashMap<Url, Vec<TextEdit>> = HashMap::new();
138 for &span in &spans {
139 if let Some(suggested_replacement) = &span.suggested_replacement {
140 let location = map_span_to_location(span, workspace_root);
141 let edit = TextEdit::new(location.range, suggested_replacement.clone());
142 edit_map.entry(location.uri).or_default().push(edit);
135 } 143 }
136 }; 144 }
137
138 // If we have a primary span use its location, otherwise use the parent
139 let location = map_span_to_location(&span, workspace_root);
140
141 if let Some(suggested_replacement) = &span.suggested_replacement {
142 // Include our replacement in the title unless it's empty
143 let title = if !suggested_replacement.is_empty() {
144 format!("{}: '{}'", rd.message, suggested_replacement)
145 } else {
146 rd.message.clone()
147 };
148
149 let edit = {
150 let edits = vec![TextEdit::new(location.range, suggested_replacement.clone())];
151 let mut edit_map = std::collections::HashMap::new();
152 edit_map.insert(location.uri, edits);
153 WorkspaceEdit::new(edit_map)
154 };
155 145
146 if !edit_map.is_empty() {
156 MappedRustChildDiagnostic::SuggestedFix(CodeAction { 147 MappedRustChildDiagnostic::SuggestedFix(CodeAction {
157 title, 148 title: rd.message.clone(),
158 kind: Some("quickfix".to_string()), 149 kind: Some("quickfix".to_string()),
159 diagnostics: None, 150 diagnostics: None,
160 edit: Some(edit), 151 edit: Some(WorkspaceEdit::new(edit_map)),
161 command: None, 152 command: None,
162 is_preferred: None, 153 is_preferred: None,
163 }) 154 })
164 } else { 155 } else {
165 MappedRustChildDiagnostic::Related(DiagnosticRelatedInformation { 156 MappedRustChildDiagnostic::Related(DiagnosticRelatedInformation {
166 location, 157 location: map_span_to_location(spans[0], workspace_root),
167 message: rd.message.clone(), 158 message: rd.message.clone(),
168 }) 159 })
169 } 160 }
@@ -189,13 +180,13 @@ pub(crate) struct MappedRustDiagnostic {
189pub(crate) fn map_rust_diagnostic_to_lsp( 180pub(crate) fn map_rust_diagnostic_to_lsp(
190 rd: &RustDiagnostic, 181 rd: &RustDiagnostic,
191 workspace_root: &PathBuf, 182 workspace_root: &PathBuf,
192) -> Option<MappedRustDiagnostic> { 183) -> Vec<MappedRustDiagnostic> {
193 let primary_span = rd.spans.iter().find(|s| s.is_primary)?; 184 let primary_spans: Vec<&DiagnosticSpan> = rd.spans.iter().filter(|s| s.is_primary).collect();
194 185 if primary_spans.is_empty() {
195 let location = map_span_to_location(&primary_span, workspace_root); 186 return vec![];
187 }
196 188
197 let severity = map_level_to_severity(rd.level); 189 let severity = map_level_to_severity(rd.level);
198 let mut primary_span_label = primary_span.label.as_ref();
199 190
200 let mut source = String::from("rustc"); 191 let mut source = String::from("rustc");
201 let mut code = rd.code.as_ref().map(|c| c.code.clone()); 192 let mut code = rd.code.as_ref().map(|c| c.code.clone());
@@ -208,19 +199,10 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
208 } 199 }
209 } 200 }
210 201
202 let mut needs_primary_span_label = true;
211 let mut related_information = vec![]; 203 let mut related_information = vec![];
212 let mut tags = vec![]; 204 let mut tags = vec![];
213 205
214 // If error occurs from macro expansion, add related info pointing to
215 // where the error originated
216 if !is_from_macro(&primary_span.file_name) && primary_span.expansion.is_some() {
217 let def_loc = map_span_to_location_naive(&primary_span, workspace_root);
218 related_information.push(DiagnosticRelatedInformation {
219 location: def_loc,
220 message: "Error originated from macro here".to_string(),
221 });
222 }
223
224 for secondary_span in rd.spans.iter().filter(|s| !s.is_primary) { 206 for secondary_span in rd.spans.iter().filter(|s| !s.is_primary) {
225 let related = map_secondary_span_to_related(secondary_span, workspace_root); 207 let related = map_secondary_span_to_related(secondary_span, workspace_root);
226 if let Some(related) = related { 208 if let Some(related) = related {
@@ -240,15 +222,11 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
240 222
241 // These secondary messages usually duplicate the content of the 223 // These secondary messages usually duplicate the content of the
242 // primary span label. 224 // primary span label.
243 primary_span_label = None; 225 needs_primary_span_label = false;
244 } 226 }
245 } 227 }
246 } 228 }
247 229
248 if let Some(primary_span_label) = primary_span_label {
249 write!(&mut message, "\n{}", primary_span_label).unwrap();
250 }
251
252 if is_unused_or_unnecessary(rd) { 230 if is_unused_or_unnecessary(rd) {
253 tags.push(DiagnosticTag::Unnecessary); 231 tags.push(DiagnosticTag::Unnecessary);
254 } 232 }
@@ -257,21 +235,45 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
257 tags.push(DiagnosticTag::Deprecated); 235 tags.push(DiagnosticTag::Deprecated);
258 } 236 }
259 237
260 let diagnostic = Diagnostic { 238 primary_spans
261 range: location.range, 239 .iter()
262 severity, 240 .map(|primary_span| {
263 code: code.map(NumberOrString::String), 241 let location = map_span_to_location(&primary_span, workspace_root);
264 source: Some(source), 242
265 message, 243 let mut message = message.clone();
266 related_information: if !related_information.is_empty() { 244 if needs_primary_span_label {
267 Some(related_information) 245 if let Some(primary_span_label) = &primary_span.label {
268 } else { 246 write!(&mut message, "\n{}", primary_span_label).unwrap();
269 None 247 }
270 }, 248 }
271 tags: if !tags.is_empty() { Some(tags) } else { None }, 249
272 }; 250 // If error occurs from macro expansion, add related info pointing to
273 251 // where the error originated
274 Some(MappedRustDiagnostic { location, diagnostic, fixes }) 252 if !is_from_macro(&primary_span.file_name) && primary_span.expansion.is_some() {
253 let def_loc = map_span_to_location_naive(&primary_span, workspace_root);
254 related_information.push(DiagnosticRelatedInformation {
255 location: def_loc,
256 message: "Error originated from macro here".to_string(),
257 });
258 }
259
260 let diagnostic = Diagnostic {
261 range: location.range,
262 severity,
263 code: code.clone().map(NumberOrString::String),
264 source: Some(source.clone()),
265 message,
266 related_information: if !related_information.is_empty() {
267 Some(related_information.clone())
268 } else {
269 None
270 },
271 tags: if !tags.is_empty() { Some(tags.clone()) } else { None },
272 };
273
274 MappedRustDiagnostic { location, diagnostic, fixes: fixes.clone() }
275 })
276 .collect()
275} 277}
276 278
277/// Returns a `Url` object from a given path, will lowercase drive letters if present. 279/// Returns a `Url` object from a given path, will lowercase drive letters if present.
diff --git a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_clippy_pass_by_ref.snap b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_clippy_pass_by_ref.snap
index 95ca163dc..9e8f4eff4 100644
--- a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_clippy_pass_by_ref.snap
+++ b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_clippy_pass_by_ref.snap
@@ -2,98 +2,100 @@
2source: crates/ra_cargo_watch/src/conv/test.rs 2source: crates/ra_cargo_watch/src/conv/test.rs
3expression: diag 3expression: diag
4--- 4---
5MappedRustDiagnostic { 5[
6 location: Location { 6 MappedRustDiagnostic {
7 uri: "file:///test/compiler/mir/tagset.rs", 7 location: Location {
8 range: Range { 8 uri: "file:///test/compiler/mir/tagset.rs",
9 start: Position { 9 range: Range {
10 line: 41, 10 start: Position {
11 character: 23, 11 line: 41,
12 }, 12 character: 23,
13 end: Position { 13 },
14 line: 41, 14 end: Position {
15 character: 28, 15 line: 41,
16 character: 28,
17 },
16 }, 18 },
17 }, 19 },
18 }, 20 diagnostic: Diagnostic {
19 diagnostic: Diagnostic { 21 range: Range {
20 range: Range { 22 start: Position {
21 start: Position { 23 line: 41,
22 line: 41, 24 character: 23,
23 character: 23, 25 },
24 }, 26 end: Position {
25 end: Position { 27 line: 41,
26 line: 41, 28 character: 28,
27 character: 28, 29 },
28 }, 30 },
29 }, 31 severity: Some(
30 severity: Some( 32 Warning,
31 Warning,
32 ),
33 code: Some(
34 String(
35 "trivially_copy_pass_by_ref",
36 ), 33 ),
37 ), 34 code: Some(
38 source: Some( 35 String(
39 "clippy", 36 "trivially_copy_pass_by_ref",
40 ), 37 ),
41 message: "this argument is passed by reference, but would be more efficient if passed by value\n#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref", 38 ),
42 related_information: Some( 39 source: Some(
43 [ 40 "clippy",
44 DiagnosticRelatedInformation { 41 ),
45 location: Location { 42 message: "this argument is passed by reference, but would be more efficient if passed by value\n#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref",
46 uri: "file:///test/compiler/lib.rs", 43 related_information: Some(
47 range: Range { 44 [
48 start: Position { 45 DiagnosticRelatedInformation {
49 line: 0, 46 location: Location {
50 character: 8, 47 uri: "file:///test/compiler/lib.rs",
51 }, 48 range: Range {
52 end: Position { 49 start: Position {
53 line: 0, 50 line: 0,
54 character: 19, 51 character: 8,
52 },
53 end: Position {
54 line: 0,
55 character: 19,
56 },
55 }, 57 },
56 }, 58 },
59 message: "lint level defined here",
57 }, 60 },
58 message: "lint level defined here", 61 ],
59 },
60 ],
61 ),
62 tags: None,
63 },
64 fixes: [
65 CodeAction {
66 title: "consider passing by value instead: \'self\'",
67 kind: Some(
68 "quickfix",
69 ), 62 ),
70 diagnostics: None, 63 tags: None,
71 edit: Some( 64 },
72 WorkspaceEdit { 65 fixes: [
73 changes: Some( 66 CodeAction {
74 { 67 title: "consider passing by value instead",
75 "file:///test/compiler/mir/tagset.rs": [ 68 kind: Some(
76 TextEdit { 69 "quickfix",
77 range: Range { 70 ),
78 start: Position { 71 diagnostics: None,
79 line: 41, 72 edit: Some(
80 character: 23, 73 WorkspaceEdit {
81 }, 74 changes: Some(
82 end: Position { 75 {
83 line: 41, 76 "file:///test/compiler/mir/tagset.rs": [
84 character: 28, 77 TextEdit {
78 range: Range {
79 start: Position {
80 line: 41,
81 character: 23,
82 },
83 end: Position {
84 line: 41,
85 character: 28,
86 },
85 }, 87 },
88 new_text: "self",
86 }, 89 },
87 new_text: "self", 90 ],
88 }, 91 },
89 ], 92 ),
90 }, 93 document_changes: None,
91 ), 94 },
92 document_changes: None, 95 ),
93 }, 96 command: None,
94 ), 97 is_preferred: None,
95 command: None, 98 },
96 is_preferred: None, 99 ],
97 }, 100 },
98 ], 101]
99}
diff --git a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_handles_macro_location.snap b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_handles_macro_location.snap
index 12eb32df4..61ae0c9ae 100644
--- a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_handles_macro_location.snap
+++ b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_handles_macro_location.snap
@@ -2,45 +2,47 @@
2source: crates/ra_cargo_watch/src/conv/test.rs 2source: crates/ra_cargo_watch/src/conv/test.rs
3expression: diag 3expression: diag
4--- 4---
5MappedRustDiagnostic { 5[
6 location: Location { 6 MappedRustDiagnostic {
7 uri: "file:///test/src/main.rs", 7 location: Location {
8 range: Range { 8 uri: "file:///test/src/main.rs",
9 start: Position { 9 range: Range {
10 line: 1, 10 start: Position {
11 character: 4, 11 line: 1,
12 }, 12 character: 4,
13 end: Position { 13 },
14 line: 1, 14 end: Position {
15 character: 26, 15 line: 1,
16 character: 26,
17 },
16 }, 18 },
17 }, 19 },
18 }, 20 diagnostic: Diagnostic {
19 diagnostic: Diagnostic { 21 range: Range {
20 range: Range { 22 start: Position {
21 start: Position { 23 line: 1,
22 line: 1, 24 character: 4,
23 character: 4, 25 },
26 end: Position {
27 line: 1,
28 character: 26,
29 },
24 }, 30 },
25 end: Position { 31 severity: Some(
26 line: 1, 32 Error,
27 character: 26,
28 },
29 },
30 severity: Some(
31 Error,
32 ),
33 code: Some(
34 String(
35 "E0277",
36 ), 33 ),
37 ), 34 code: Some(
38 source: Some( 35 String(
39 "rustc", 36 "E0277",
40 ), 37 ),
41 message: "can\'t compare `{integer}` with `&str`\nthe trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`", 38 ),
42 related_information: None, 39 source: Some(
43 tags: None, 40 "rustc",
41 ),
42 message: "can\'t compare `{integer}` with `&str`\nthe trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`",
43 related_information: None,
44 tags: None,
45 },
46 fixes: [],
44 }, 47 },
45 fixes: [], 48]
46}
diff --git a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_macro_compiler_error.snap b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_macro_compiler_error.snap
index 7b83a7cd0..641da1a58 100644
--- a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_macro_compiler_error.snap
+++ b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_macro_compiler_error.snap
@@ -2,60 +2,62 @@
2source: crates/ra_cargo_watch/src/conv/test.rs 2source: crates/ra_cargo_watch/src/conv/test.rs
3expression: diag 3expression: diag
4--- 4---
5MappedRustDiagnostic { 5[
6 location: Location { 6 MappedRustDiagnostic {
7 uri: "file:///test/crates/ra_hir_def/src/data.rs", 7 location: Location {
8 range: Range { 8 uri: "file:///test/crates/ra_hir_def/src/data.rs",
9 start: Position { 9 range: Range {
10 line: 79, 10 start: Position {
11 character: 15, 11 line: 79,
12 }, 12 character: 15,
13 end: Position { 13 },
14 line: 79, 14 end: Position {
15 character: 41, 15 line: 79,
16 character: 41,
17 },
16 }, 18 },
17 }, 19 },
18 }, 20 diagnostic: Diagnostic {
19 diagnostic: Diagnostic { 21 range: Range {
20 range: Range { 22 start: Position {
21 start: Position { 23 line: 79,
22 line: 79, 24 character: 15,
23 character: 15, 25 },
24 }, 26 end: Position {
25 end: Position { 27 line: 79,
26 line: 79, 28 character: 41,
27 character: 41, 29 },
28 }, 30 },
29 }, 31 severity: Some(
30 severity: Some( 32 Error,
31 Error, 33 ),
32 ), 34 code: None,
33 code: None, 35 source: Some(
34 source: Some( 36 "rustc",
35 "rustc", 37 ),
36 ), 38 message: "Please register your known path in the path module",
37 message: "Please register your known path in the path module", 39 related_information: Some(
38 related_information: Some( 40 [
39 [ 41 DiagnosticRelatedInformation {
40 DiagnosticRelatedInformation { 42 location: Location {
41 location: Location { 43 uri: "file:///test/crates/ra_hir_def/src/path.rs",
42 uri: "file:///test/crates/ra_hir_def/src/path.rs", 44 range: Range {
43 range: Range { 45 start: Position {
44 start: Position { 46 line: 264,
45 line: 264, 47 character: 8,
46 character: 8, 48 },
47 }, 49 end: Position {
48 end: Position { 50 line: 264,
49 line: 264, 51 character: 76,
50 character: 76, 52 },
51 }, 53 },
52 }, 54 },
55 message: "Error originated from macro here",
53 }, 56 },
54 message: "Error originated from macro here", 57 ],
55 }, 58 ),
56 ], 59 tags: None,
57 ), 60 },
58 tags: None, 61 fixes: [],
59 }, 62 },
60 fixes: [], 63]
61}
diff --git a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_multi_line_fix.snap b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_multi_line_fix.snap
new file mode 100644
index 000000000..0557a2e79
--- /dev/null
+++ b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_multi_line_fix.snap
@@ -0,0 +1,114 @@
1---
2source: crates/ra_cargo_watch/src/conv/test.rs
3expression: diag
4---
5[
6 MappedRustDiagnostic {
7 location: Location {
8 uri: "file:///test/src/main.rs",
9 range: Range {
10 start: Position {
11 line: 3,
12 character: 4,
13 },
14 end: Position {
15 line: 3,
16 character: 5,
17 },
18 },
19 },
20 diagnostic: Diagnostic {
21 range: Range {
22 start: Position {
23 line: 3,
24 character: 4,
25 },
26 end: Position {
27 line: 3,
28 character: 5,
29 },
30 },
31 severity: Some(
32 Warning,
33 ),
34 code: Some(
35 String(
36 "let_and_return",
37 ),
38 ),
39 source: Some(
40 "clippy",
41 ),
42 message: "returning the result of a let binding from a block\n`#[warn(clippy::let_and_return)]` on by default\nfor further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return",
43 related_information: Some(
44 [
45 DiagnosticRelatedInformation {
46 location: Location {
47 uri: "file:///test/src/main.rs",
48 range: Range {
49 start: Position {
50 line: 2,
51 character: 4,
52 },
53 end: Position {
54 line: 2,
55 character: 30,
56 },
57 },
58 },
59 message: "unnecessary let binding",
60 },
61 ],
62 ),
63 tags: None,
64 },
65 fixes: [
66 CodeAction {
67 title: "return the expression directly",
68 kind: Some(
69 "quickfix",
70 ),
71 diagnostics: None,
72 edit: Some(
73 WorkspaceEdit {
74 changes: Some(
75 {
76 "file:///test/src/main.rs": [
77 TextEdit {
78 range: Range {
79 start: Position {
80 line: 2,
81 character: 4,
82 },
83 end: Position {
84 line: 2,
85 character: 30,
86 },
87 },
88 new_text: "",
89 },
90 TextEdit {
91 range: Range {
92 start: Position {
93 line: 3,
94 character: 4,
95 },
96 end: Position {
97 line: 3,
98 character: 5,
99 },
100 },
101 new_text: "(0..10).collect()",
102 },
103 ],
104 },
105 ),
106 document_changes: None,
107 },
108 ),
109 command: None,
110 is_preferred: None,
111 },
112 ],
113 },
114]
diff --git a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_incompatible_type_for_trait.snap b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_incompatible_type_for_trait.snap
index 54679c5db..754bc33a4 100644
--- a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_incompatible_type_for_trait.snap
+++ b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_incompatible_type_for_trait.snap
@@ -2,45 +2,47 @@
2source: crates/ra_cargo_watch/src/conv/test.rs 2source: crates/ra_cargo_watch/src/conv/test.rs
3expression: diag 3expression: diag
4--- 4---
5MappedRustDiagnostic { 5[
6 location: Location { 6 MappedRustDiagnostic {
7 uri: "file:///test/compiler/ty/list_iter.rs", 7 location: Location {
8 range: Range { 8 uri: "file:///test/compiler/ty/list_iter.rs",
9 start: Position { 9 range: Range {
10 line: 51, 10 start: Position {
11 character: 4, 11 line: 51,
12 }, 12 character: 4,
13 end: Position { 13 },
14 line: 51, 14 end: Position {
15 character: 47, 15 line: 51,
16 character: 47,
17 },
16 }, 18 },
17 }, 19 },
18 }, 20 diagnostic: Diagnostic {
19 diagnostic: Diagnostic { 21 range: Range {
20 range: Range { 22 start: Position {
21 start: Position { 23 line: 51,
22 line: 51, 24 character: 4,
23 character: 4, 25 },
26 end: Position {
27 line: 51,
28 character: 47,
29 },
24 }, 30 },
25 end: Position { 31 severity: Some(
26 line: 51, 32 Error,
27 character: 47,
28 },
29 },
30 severity: Some(
31 Error,
32 ),
33 code: Some(
34 String(
35 "E0053",
36 ), 33 ),
37 ), 34 code: Some(
38 source: Some( 35 String(
39 "rustc", 36 "E0053",
40 ), 37 ),
41 message: "method `next` has an incompatible type for trait\nexpected type `fn(&mut ty::list_iter::ListIterator<\'list, M>) -> std::option::Option<&ty::Ref<M>>`\n found type `fn(&ty::list_iter::ListIterator<\'list, M>) -> std::option::Option<&\'list ty::Ref<M>>`", 38 ),
42 related_information: None, 39 source: Some(
43 tags: None, 40 "rustc",
41 ),
42 message: "method `next` has an incompatible type for trait\nexpected type `fn(&mut ty::list_iter::ListIterator<\'list, M>) -> std::option::Option<&ty::Ref<M>>`\n found type `fn(&ty::list_iter::ListIterator<\'list, M>) -> std::option::Option<&\'list ty::Ref<M>>`",
43 related_information: None,
44 tags: None,
45 },
46 fixes: [],
44 }, 47 },
45 fixes: [], 48]
46}
diff --git a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_mismatched_type.snap b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_mismatched_type.snap
index 57df4ceaf..78b7f7cc8 100644
--- a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_mismatched_type.snap
+++ b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_mismatched_type.snap
@@ -2,45 +2,47 @@
2source: crates/ra_cargo_watch/src/conv/test.rs 2source: crates/ra_cargo_watch/src/conv/test.rs
3expression: diag 3expression: diag
4--- 4---
5MappedRustDiagnostic { 5[
6 location: Location { 6 MappedRustDiagnostic {
7 uri: "file:///test/runtime/compiler_support.rs", 7 location: Location {
8 range: Range { 8 uri: "file:///test/runtime/compiler_support.rs",
9 start: Position { 9 range: Range {
10 line: 47, 10 start: Position {
11 character: 64, 11 line: 47,
12 }, 12 character: 64,
13 end: Position { 13 },
14 line: 47, 14 end: Position {
15 character: 69, 15 line: 47,
16 character: 69,
17 },
16 }, 18 },
17 }, 19 },
18 }, 20 diagnostic: Diagnostic {
19 diagnostic: Diagnostic { 21 range: Range {
20 range: Range { 22 start: Position {
21 start: Position { 23 line: 47,
22 line: 47, 24 character: 64,
23 character: 64, 25 },
26 end: Position {
27 line: 47,
28 character: 69,
29 },
24 }, 30 },
25 end: Position { 31 severity: Some(
26 line: 47, 32 Error,
27 character: 69,
28 },
29 },
30 severity: Some(
31 Error,
32 ),
33 code: Some(
34 String(
35 "E0308",
36 ), 33 ),
37 ), 34 code: Some(
38 source: Some( 35 String(
39 "rustc", 36 "E0308",
40 ), 37 ),
41 message: "mismatched types\nexpected usize, found u32", 38 ),
42 related_information: None, 39 source: Some(
43 tags: None, 40 "rustc",
41 ),
42 message: "mismatched types\nexpected usize, found u32",
43 related_information: None,
44 tags: None,
45 },
46 fixes: [],
44 }, 47 },
45 fixes: [], 48]
46}
diff --git a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_unused_variable.snap b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_unused_variable.snap
index 3e1fe736c..5989ed202 100644
--- a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_unused_variable.snap
+++ b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_unused_variable.snap
@@ -2,83 +2,85 @@
2source: crates/ra_cargo_watch/src/conv/test.rs 2source: crates/ra_cargo_watch/src/conv/test.rs
3expression: diag 3expression: diag
4--- 4---
5MappedRustDiagnostic { 5[
6 location: Location { 6 MappedRustDiagnostic {
7 uri: "file:///test/driver/subcommand/repl.rs", 7 location: Location {
8 range: Range { 8 uri: "file:///test/driver/subcommand/repl.rs",
9 start: Position { 9 range: Range {
10 line: 290, 10 start: Position {
11 character: 8, 11 line: 290,
12 }, 12 character: 8,
13 end: Position { 13 },
14 line: 290, 14 end: Position {
15 character: 11, 15 line: 290,
16 character: 11,
17 },
16 }, 18 },
17 }, 19 },
18 }, 20 diagnostic: Diagnostic {
19 diagnostic: Diagnostic { 21 range: Range {
20 range: Range { 22 start: Position {
21 start: Position { 23 line: 290,
22 line: 290, 24 character: 8,
23 character: 8, 25 },
24 }, 26 end: Position {
25 end: Position { 27 line: 290,
26 line: 290, 28 character: 11,
27 character: 11, 29 },
28 }, 30 },
29 }, 31 severity: Some(
30 severity: Some( 32 Warning,
31 Warning,
32 ),
33 code: Some(
34 String(
35 "unused_variables",
36 ), 33 ),
37 ), 34 code: Some(
38 source: Some( 35 String(
39 "rustc", 36 "unused_variables",
40 ), 37 ),
41 message: "unused variable: `foo`\n#[warn(unused_variables)] on by default",
42 related_information: None,
43 tags: Some(
44 [
45 Unnecessary,
46 ],
47 ),
48 },
49 fixes: [
50 CodeAction {
51 title: "consider prefixing with an underscore: \'_foo\'",
52 kind: Some(
53 "quickfix",
54 ), 38 ),
55 diagnostics: None, 39 source: Some(
56 edit: Some( 40 "rustc",
57 WorkspaceEdit { 41 ),
58 changes: Some( 42 message: "unused variable: `foo`\n#[warn(unused_variables)] on by default",
59 { 43 related_information: None,
60 "file:///test/driver/subcommand/repl.rs": [ 44 tags: Some(
61 TextEdit { 45 [
62 range: Range { 46 Unnecessary,
63 start: Position { 47 ],
64 line: 290,
65 character: 8,
66 },
67 end: Position {
68 line: 290,
69 character: 11,
70 },
71 },
72 new_text: "_foo",
73 },
74 ],
75 },
76 ),
77 document_changes: None,
78 },
79 ), 48 ),
80 command: None,
81 is_preferred: None,
82 }, 49 },
83 ], 50 fixes: [
84} 51 CodeAction {
52 title: "consider prefixing with an underscore",
53 kind: Some(
54 "quickfix",
55 ),
56 diagnostics: None,
57 edit: Some(
58 WorkspaceEdit {
59 changes: Some(
60 {
61 "file:///test/driver/subcommand/repl.rs": [
62 TextEdit {
63 range: Range {
64 start: Position {
65 line: 290,
66 character: 8,
67 },
68 end: Position {
69 line: 290,
70 character: 11,
71 },
72 },
73 new_text: "_foo",
74 },
75 ],
76 },
77 ),
78 document_changes: None,
79 },
80 ),
81 command: None,
82 is_preferred: None,
83 },
84 ],
85 },
86]
diff --git a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_wrong_number_of_parameters.snap b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_wrong_number_of_parameters.snap
index 69301078d..e34b546dc 100644
--- a/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_wrong_number_of_parameters.snap
+++ b/crates/ra_cargo_watch/src/conv/snapshots/ra_cargo_watch__conv__test__snap_rustc_wrong_number_of_parameters.snap
@@ -2,64 +2,66 @@
2source: crates/ra_cargo_watch/src/conv/test.rs 2source: crates/ra_cargo_watch/src/conv/test.rs
3expression: diag 3expression: diag
4--- 4---
5MappedRustDiagnostic { 5[
6 location: Location { 6 MappedRustDiagnostic {
7 uri: "file:///test/compiler/ty/select.rs", 7 location: Location {
8 range: Range { 8 uri: "file:///test/compiler/ty/select.rs",
9 start: Position { 9 range: Range {
10 line: 103, 10 start: Position {
11 character: 17, 11 line: 103,
12 }, 12 character: 17,
13 end: Position { 13 },
14 line: 103, 14 end: Position {
15 character: 29, 15 line: 103,
16 character: 29,
17 },
16 }, 18 },
17 }, 19 },
18 }, 20 diagnostic: Diagnostic {
19 diagnostic: Diagnostic { 21 range: Range {
20 range: Range { 22 start: Position {
21 start: Position { 23 line: 103,
22 line: 103, 24 character: 17,
23 character: 17, 25 },
24 }, 26 end: Position {
25 end: Position { 27 line: 103,
26 line: 103, 28 character: 29,
27 character: 29, 29 },
28 }, 30 },
29 }, 31 severity: Some(
30 severity: Some( 32 Error,
31 Error,
32 ),
33 code: Some(
34 String(
35 "E0061",
36 ), 33 ),
37 ), 34 code: Some(
38 source: Some( 35 String(
39 "rustc", 36 "E0061",
40 ), 37 ),
41 message: "this function takes 2 parameters but 3 parameters were supplied\nexpected 2 parameters", 38 ),
42 related_information: Some( 39 source: Some(
43 [ 40 "rustc",
44 DiagnosticRelatedInformation { 41 ),
45 location: Location { 42 message: "this function takes 2 parameters but 3 parameters were supplied\nexpected 2 parameters",
46 uri: "file:///test/compiler/ty/select.rs", 43 related_information: Some(
47 range: Range { 44 [
48 start: Position { 45 DiagnosticRelatedInformation {
49 line: 218, 46 location: Location {
50 character: 4, 47 uri: "file:///test/compiler/ty/select.rs",
51 }, 48 range: Range {
52 end: Position { 49 start: Position {
53 line: 230, 50 line: 218,
54 character: 5, 51 character: 4,
52 },
53 end: Position {
54 line: 230,
55 character: 5,
56 },
55 }, 57 },
56 }, 58 },
59 message: "defined here",
57 }, 60 },
58 message: "defined here", 61 ],
59 }, 62 ),
60 ], 63 tags: None,
61 ), 64 },
62 tags: None, 65 fixes: [],
63 }, 66 },
64 fixes: [], 67]
65}
diff --git a/crates/ra_cargo_watch/src/conv/test.rs b/crates/ra_cargo_watch/src/conv/test.rs
index 6b86525b8..4e81455ca 100644
--- a/crates/ra_cargo_watch/src/conv/test.rs
+++ b/crates/ra_cargo_watch/src/conv/test.rs
@@ -58,7 +58,7 @@ fn snap_rustc_incompatible_type_for_trait() {
58 ); 58 );
59 59
60 let workspace_root = PathBuf::from("/test/"); 60 let workspace_root = PathBuf::from("/test/");
61 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic"); 61 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
62 insta::assert_debug_snapshot!(diag); 62 insta::assert_debug_snapshot!(diag);
63} 63}
64 64
@@ -141,7 +141,7 @@ fn snap_rustc_unused_variable() {
141 ); 141 );
142 142
143 let workspace_root = PathBuf::from("/test/"); 143 let workspace_root = PathBuf::from("/test/");
144 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic"); 144 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
145 insta::assert_debug_snapshot!(diag); 145 insta::assert_debug_snapshot!(diag);
146} 146}
147 147
@@ -266,7 +266,7 @@ fn snap_rustc_wrong_number_of_parameters() {
266 ); 266 );
267 267
268 let workspace_root = PathBuf::from("/test/"); 268 let workspace_root = PathBuf::from("/test/");
269 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic"); 269 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
270 insta::assert_debug_snapshot!(diag); 270 insta::assert_debug_snapshot!(diag);
271} 271}
272 272
@@ -387,7 +387,7 @@ fn snap_clippy_pass_by_ref() {
387 ); 387 );
388 388
389 let workspace_root = PathBuf::from("/test/"); 389 let workspace_root = PathBuf::from("/test/");
390 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic"); 390 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
391 insta::assert_debug_snapshot!(diag); 391 insta::assert_debug_snapshot!(diag);
392} 392}
393 393
@@ -431,7 +431,7 @@ fn snap_rustc_mismatched_type() {
431 ); 431 );
432 432
433 let workspace_root = PathBuf::from("/test/"); 433 let workspace_root = PathBuf::from("/test/");
434 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic"); 434 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
435 insta::assert_debug_snapshot!(diag); 435 insta::assert_debug_snapshot!(diag);
436} 436}
437 437
@@ -703,7 +703,7 @@ fn snap_handles_macro_location() {
703 ); 703 );
704 704
705 let workspace_root = PathBuf::from("/test/"); 705 let workspace_root = PathBuf::from("/test/");
706 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic"); 706 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
707 insta::assert_debug_snapshot!(diag); 707 insta::assert_debug_snapshot!(diag);
708} 708}
709 709
@@ -933,6 +933,140 @@ fn snap_macro_compiler_error() {
933 ); 933 );
934 934
935 let workspace_root = PathBuf::from("/test/"); 935 let workspace_root = PathBuf::from("/test/");
936 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root).expect("couldn't map diagnostic"); 936 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
937 insta::assert_debug_snapshot!(diag);
938}
939
940#[test]
941#[cfg(not(windows))]
942fn snap_multi_line_fix() {
943 let diag = parse_diagnostic(
944 r##"{
945 "rendered": "warning: returning the result of a let binding from a block\n --> src/main.rs:4:5\n |\n3 | let a = (0..10).collect();\n | -------------------------- unnecessary let binding\n4 | a\n | ^\n |\n = note: `#[warn(clippy::let_and_return)]` on by default\n = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return\nhelp: return the expression directly\n |\n3 | \n4 | (0..10).collect()\n |\n\n",
946 "children": [
947 {
948 "children": [],
949 "code": null,
950 "level": "note",
951 "message": "`#[warn(clippy::let_and_return)]` on by default",
952 "rendered": null,
953 "spans": []
954 },
955 {
956 "children": [],
957 "code": null,
958 "level": "help",
959 "message": "for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#let_and_return",
960 "rendered": null,
961 "spans": []
962 },
963 {
964 "children": [],
965 "code": null,
966 "level": "help",
967 "message": "return the expression directly",
968 "rendered": null,
969 "spans": [
970 {
971 "byte_end": 55,
972 "byte_start": 29,
973 "column_end": 31,
974 "column_start": 5,
975 "expansion": null,
976 "file_name": "src/main.rs",
977 "is_primary": true,
978 "label": null,
979 "line_end": 3,
980 "line_start": 3,
981 "suggested_replacement": "",
982 "suggestion_applicability": "MachineApplicable",
983 "text": [
984 {
985 "highlight_end": 31,
986 "highlight_start": 5,
987 "text": " let a = (0..10).collect();"
988 }
989 ]
990 },
991 {
992 "byte_end": 61,
993 "byte_start": 60,
994 "column_end": 6,
995 "column_start": 5,
996 "expansion": null,
997 "file_name": "src/main.rs",
998 "is_primary": true,
999 "label": null,
1000 "line_end": 4,
1001 "line_start": 4,
1002 "suggested_replacement": "(0..10).collect()",
1003 "suggestion_applicability": "MachineApplicable",
1004 "text": [
1005 {
1006 "highlight_end": 6,
1007 "highlight_start": 5,
1008 "text": " a"
1009 }
1010 ]
1011 }
1012 ]
1013 }
1014 ],
1015 "code": {
1016 "code": "clippy::let_and_return",
1017 "explanation": null
1018 },
1019 "level": "warning",
1020 "message": "returning the result of a let binding from a block",
1021 "spans": [
1022 {
1023 "byte_end": 55,
1024 "byte_start": 29,
1025 "column_end": 31,
1026 "column_start": 5,
1027 "expansion": null,
1028 "file_name": "src/main.rs",
1029 "is_primary": false,
1030 "label": "unnecessary let binding",
1031 "line_end": 3,
1032 "line_start": 3,
1033 "suggested_replacement": null,
1034 "suggestion_applicability": null,
1035 "text": [
1036 {
1037 "highlight_end": 31,
1038 "highlight_start": 5,
1039 "text": " let a = (0..10).collect();"
1040 }
1041 ]
1042 },
1043 {
1044 "byte_end": 61,
1045 "byte_start": 60,
1046 "column_end": 6,
1047 "column_start": 5,
1048 "expansion": null,
1049 "file_name": "src/main.rs",
1050 "is_primary": true,
1051 "label": null,
1052 "line_end": 4,
1053 "line_start": 4,
1054 "suggested_replacement": null,
1055 "suggestion_applicability": null,
1056 "text": [
1057 {
1058 "highlight_end": 6,
1059 "highlight_start": 5,
1060 "text": " a"
1061 }
1062 ]
1063 }
1064 ]
1065 }
1066 "##,
1067 );
1068
1069 let workspace_root = PathBuf::from("/test/");
1070 let diag = map_rust_diagnostic_to_lsp(&diag, &workspace_root);
937 insta::assert_debug_snapshot!(diag); 1071 insta::assert_debug_snapshot!(diag);
938} 1072}
diff --git a/crates/ra_cargo_watch/src/lib.rs b/crates/ra_cargo_watch/src/lib.rs
index f07c34549..94b9c03d0 100644
--- a/crates/ra_cargo_watch/src/lib.rs
+++ b/crates/ra_cargo_watch/src/lib.rs
@@ -197,23 +197,23 @@ impl CheckWatcherThread {
197 } 197 }
198 198
199 CheckEvent::Msg(Message::CompilerMessage(msg)) => { 199 CheckEvent::Msg(Message::CompilerMessage(msg)) => {
200 let map_result = 200 let map_result = map_rust_diagnostic_to_lsp(&msg.message, &self.workspace_root);
201 match map_rust_diagnostic_to_lsp(&msg.message, &self.workspace_root) { 201 if map_result.is_empty() {
202 Some(map_result) => map_result, 202 return;
203 None => return, 203 }
204 };
205
206 let MappedRustDiagnostic { location, diagnostic, fixes } = map_result;
207 let fixes = fixes
208 .into_iter()
209 .map(|fix| {
210 CodeAction { diagnostics: Some(vec![diagnostic.clone()]), ..fix }.into()
211 })
212 .collect();
213 204
214 task_send 205 for MappedRustDiagnostic { location, diagnostic, fixes } in map_result {
215 .send(CheckTask::AddDiagnostic { url: location.uri, diagnostic, fixes }) 206 let fixes = fixes
216 .unwrap(); 207 .into_iter()
208 .map(|fix| {
209 CodeAction { diagnostics: Some(vec![diagnostic.clone()]), ..fix }.into()
210 })
211 .collect();
212
213 task_send
214 .send(CheckTask::AddDiagnostic { url: location.uri, diagnostic, fixes })
215 .unwrap();
216 }
217 } 217 }
218 218
219 CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {} 219 CheckEvent::Msg(Message::BuildScriptExecuted(_msg)) => {}
diff --git a/crates/ra_db/src/fixture.rs b/crates/ra_db/src/fixture.rs
index 7f43c2971..3dc86ca2d 100644
--- a/crates/ra_db/src/fixture.rs
+++ b/crates/ra_db/src/fixture.rs
@@ -61,7 +61,14 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId
61 }; 61 };
62 62
63 let mut crate_graph = CrateGraph::default(); 63 let mut crate_graph = CrateGraph::default();
64 crate_graph.add_crate_root(file_id, meta.edition, meta.krate, meta.cfg, meta.env); 64 crate_graph.add_crate_root(
65 file_id,
66 meta.edition,
67 meta.krate,
68 meta.cfg,
69 meta.env,
70 Default::default(),
71 );
65 crate_graph 72 crate_graph
66 } else { 73 } else {
67 let mut crate_graph = CrateGraph::default(); 74 let mut crate_graph = CrateGraph::default();
@@ -71,6 +78,7 @@ fn with_single_file(db: &mut dyn SourceDatabaseExt, ra_fixture: &str) -> FileId
71 None, 78 None,
72 CfgOptions::default(), 79 CfgOptions::default(),
73 Env::default(), 80 Env::default(),
81 Default::default(),
74 ); 82 );
75 crate_graph 83 crate_graph
76 }; 84 };
@@ -119,6 +127,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
119 Some(krate.clone()), 127 Some(krate.clone()),
120 meta.cfg, 128 meta.cfg,
121 meta.env, 129 meta.env,
130 Default::default(),
122 ); 131 );
123 let prev = crates.insert(krate.clone(), crate_id); 132 let prev = crates.insert(krate.clone(), crate_id);
124 assert!(prev.is_none()); 133 assert!(prev.is_none());
@@ -155,6 +164,7 @@ fn with_files(db: &mut dyn SourceDatabaseExt, fixture: &str) -> Option<FilePosit
155 None, 164 None,
156 CfgOptions::default(), 165 CfgOptions::default(),
157 Env::default(), 166 Env::default(),
167 Default::default(),
158 ); 168 );
159 } else { 169 } else {
160 for (from, to) in crate_deps { 170 for (from, to) in crate_deps {
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs
index 1a1c64202..06d40db96 100644
--- a/crates/ra_db/src/input.rs
+++ b/crates/ra_db/src/input.rs
@@ -113,6 +113,7 @@ pub struct CrateData {
113 pub display_name: Option<String>, 113 pub display_name: Option<String>,
114 pub cfg_options: CfgOptions, 114 pub cfg_options: CfgOptions,
115 pub env: Env, 115 pub env: Env,
116 pub extern_source: ExternSource,
116 pub dependencies: Vec<Dependency>, 117 pub dependencies: Vec<Dependency>,
117} 118}
118 119
@@ -122,11 +123,22 @@ pub enum Edition {
122 Edition2015, 123 Edition2015,
123} 124}
124 125
126#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
127pub struct ExternSourceId(pub u32);
128
125#[derive(Default, Debug, Clone, PartialEq, Eq)] 129#[derive(Default, Debug, Clone, PartialEq, Eq)]
126pub struct Env { 130pub struct Env {
127 entries: FxHashMap<String, String>, 131 entries: FxHashMap<String, String>,
128} 132}
129 133
134// FIXME: Redesign vfs for solve the following limitation ?
135// Note: Some env variables (e.g. OUT_DIR) are located outside of the
136// crate. We store a map to allow remap it to ExternSourceId
137#[derive(Default, Debug, Clone, PartialEq, Eq)]
138pub struct ExternSource {
139 extern_paths: FxHashMap<String, ExternSourceId>,
140}
141
130#[derive(Debug, Clone, PartialEq, Eq)] 142#[derive(Debug, Clone, PartialEq, Eq)]
131pub struct Dependency { 143pub struct Dependency {
132 pub crate_id: CrateId, 144 pub crate_id: CrateId,
@@ -141,6 +153,7 @@ impl CrateGraph {
141 display_name: Option<String>, 153 display_name: Option<String>,
142 cfg_options: CfgOptions, 154 cfg_options: CfgOptions,
143 env: Env, 155 env: Env,
156 extern_source: ExternSource,
144 ) -> CrateId { 157 ) -> CrateId {
145 let data = CrateData { 158 let data = CrateData {
146 root_file_id: file_id, 159 root_file_id: file_id,
@@ -148,6 +161,7 @@ impl CrateGraph {
148 display_name, 161 display_name,
149 cfg_options, 162 cfg_options,
150 env, 163 env,
164 extern_source,
151 dependencies: Vec::new(), 165 dependencies: Vec::new(),
152 }; 166 };
153 let crate_id = CrateId(self.arena.len() as u32); 167 let crate_id = CrateId(self.arena.len() as u32);
@@ -271,6 +285,27 @@ impl Env {
271 } 285 }
272} 286}
273 287
288impl ExternSource {
289 pub fn extern_path(&self, path: &str) -> Option<(ExternSourceId, RelativePathBuf)> {
290 self.extern_paths.iter().find_map(|(root_path, id)| {
291 if path.starts_with(root_path) {
292 let mut rel_path = &path[root_path.len()..];
293 if rel_path.starts_with("/") {
294 rel_path = &rel_path[1..];
295 }
296 let rel_path = RelativePathBuf::from_path(rel_path).ok()?;
297 Some((id.clone(), rel_path))
298 } else {
299 None
300 }
301 })
302 }
303
304 pub fn set_extern_path(&mut self, root_path: &str, root: ExternSourceId) {
305 self.extern_paths.insert(root_path.to_owned(), root);
306 }
307}
308
274#[derive(Debug)] 309#[derive(Debug)]
275pub struct ParseEditionError { 310pub struct ParseEditionError {
276 invalid_input: String, 311 invalid_input: String,
@@ -300,6 +335,7 @@ mod tests {
300 None, 335 None,
301 CfgOptions::default(), 336 CfgOptions::default(),
302 Env::default(), 337 Env::default(),
338 Default::default(),
303 ); 339 );
304 let crate2 = graph.add_crate_root( 340 let crate2 = graph.add_crate_root(
305 FileId(2u32), 341 FileId(2u32),
@@ -307,6 +343,7 @@ mod tests {
307 None, 343 None,
308 CfgOptions::default(), 344 CfgOptions::default(),
309 Env::default(), 345 Env::default(),
346 Default::default(),
310 ); 347 );
311 let crate3 = graph.add_crate_root( 348 let crate3 = graph.add_crate_root(
312 FileId(3u32), 349 FileId(3u32),
@@ -314,6 +351,7 @@ mod tests {
314 None, 351 None,
315 CfgOptions::default(), 352 CfgOptions::default(),
316 Env::default(), 353 Env::default(),
354 Default::default(),
317 ); 355 );
318 assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); 356 assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
319 assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); 357 assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok());
@@ -329,6 +367,7 @@ mod tests {
329 None, 367 None,
330 CfgOptions::default(), 368 CfgOptions::default(),
331 Env::default(), 369 Env::default(),
370 Default::default(),
332 ); 371 );
333 let crate2 = graph.add_crate_root( 372 let crate2 = graph.add_crate_root(
334 FileId(2u32), 373 FileId(2u32),
@@ -336,6 +375,7 @@ mod tests {
336 None, 375 None,
337 CfgOptions::default(), 376 CfgOptions::default(),
338 Env::default(), 377 Env::default(),
378 Default::default(),
339 ); 379 );
340 let crate3 = graph.add_crate_root( 380 let crate3 = graph.add_crate_root(
341 FileId(3u32), 381 FileId(3u32),
@@ -343,6 +383,7 @@ mod tests {
343 None, 383 None,
344 CfgOptions::default(), 384 CfgOptions::default(),
345 Env::default(), 385 Env::default(),
386 Default::default(),
346 ); 387 );
347 assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok()); 388 assert!(graph.add_dep(crate1, CrateName::new("crate2").unwrap(), crate2).is_ok());
348 assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok()); 389 assert!(graph.add_dep(crate2, CrateName::new("crate3").unwrap(), crate3).is_ok());
@@ -357,6 +398,7 @@ mod tests {
357 None, 398 None,
358 CfgOptions::default(), 399 CfgOptions::default(),
359 Env::default(), 400 Env::default(),
401 Default::default(),
360 ); 402 );
361 let crate2 = graph.add_crate_root( 403 let crate2 = graph.add_crate_root(
362 FileId(2u32), 404 FileId(2u32),
@@ -364,6 +406,7 @@ mod tests {
364 None, 406 None,
365 CfgOptions::default(), 407 CfgOptions::default(),
366 Env::default(), 408 Env::default(),
409 Default::default(),
367 ); 410 );
368 assert!(graph 411 assert!(graph
369 .add_dep(crate1, CrateName::normalize_dashes("crate-name-with-dashes"), crate2) 412 .add_dep(crate1, CrateName::normalize_dashes("crate-name-with-dashes"), crate2)
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index fb002d717..d500d5e85 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -11,7 +11,8 @@ use ra_syntax::{ast, Parse, SourceFile, TextRange, TextUnit};
11pub use crate::{ 11pub use crate::{
12 cancellation::Canceled, 12 cancellation::Canceled,
13 input::{ 13 input::{
14 CrateGraph, CrateId, CrateName, Dependency, Edition, Env, FileId, SourceRoot, SourceRootId, 14 CrateGraph, CrateId, CrateName, Dependency, Edition, Env, ExternSource, ExternSourceId,
15 FileId, SourceRoot, SourceRootId,
15 }, 16 },
16}; 17};
17pub use relative_path::{RelativePath, RelativePathBuf}; 18pub use relative_path::{RelativePath, RelativePathBuf};
@@ -87,6 +88,12 @@ pub trait FileLoader {
87 fn resolve_relative_path(&self, anchor: FileId, relative_path: &RelativePath) 88 fn resolve_relative_path(&self, anchor: FileId, relative_path: &RelativePath)
88 -> Option<FileId>; 89 -> Option<FileId>;
89 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>>; 90 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>>;
91
92 fn resolve_extern_path(
93 &self,
94 extern_id: ExternSourceId,
95 relative_path: &RelativePath,
96 ) -> Option<FileId>;
90} 97}
91 98
92/// Database which stores all significant input facts: source code and project 99/// Database which stores all significant input facts: source code and project
@@ -164,4 +171,13 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> {
164 let source_root = self.0.file_source_root(file_id); 171 let source_root = self.0.file_source_root(file_id);
165 self.0.source_root_crates(source_root) 172 self.0.source_root_crates(source_root)
166 } 173 }
174
175 fn resolve_extern_path(
176 &self,
177 extern_id: ExternSourceId,
178 relative_path: &RelativePath,
179 ) -> Option<FileId> {
180 let source_root = self.0.source_root(SourceRootId(extern_id.0));
181 source_root.file_by_relative_path(&relative_path)
182 }
167} 183}
diff --git a/crates/ra_hir_def/src/test_db.rs b/crates/ra_hir_def/src/test_db.rs
index 1568820e9..0756916a8 100644
--- a/crates/ra_hir_def/src/test_db.rs
+++ b/crates/ra_hir_def/src/test_db.rs
@@ -6,7 +6,7 @@ use std::{
6}; 6};
7 7
8use crate::db::DefDatabase; 8use crate::db::DefDatabase;
9use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath}; 9use ra_db::{salsa, CrateId, ExternSourceId, FileId, FileLoader, FileLoaderDelegate, RelativePath};
10 10
11#[salsa::database( 11#[salsa::database(
12 ra_db::SourceDatabaseExtStorage, 12 ra_db::SourceDatabaseExtStorage,
@@ -52,6 +52,14 @@ impl FileLoader for TestDB {
52 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { 52 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> {
53 FileLoaderDelegate(self).relevant_crates(file_id) 53 FileLoaderDelegate(self).relevant_crates(file_id)
54 } 54 }
55
56 fn resolve_extern_path(
57 &self,
58 extern_id: ExternSourceId,
59 relative_path: &RelativePath,
60 ) -> Option<FileId> {
61 FileLoaderDelegate(self).resolve_extern_path(extern_id, relative_path)
62 }
55} 63}
56 64
57impl TestDB { 65impl TestDB {
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs
index 3f60b1cca..f9d3787f6 100644
--- a/crates/ra_hir_expand/src/builtin_macro.rs
+++ b/crates/ra_hir_expand/src/builtin_macro.rs
@@ -88,17 +88,18 @@ register_builtin! {
88 (compile_error, CompileError) => compile_error_expand, 88 (compile_error, CompileError) => compile_error_expand,
89 (file, File) => file_expand, 89 (file, File) => file_expand,
90 (line, Line) => line_expand, 90 (line, Line) => line_expand,
91 (assert, Assert) => assert_expand,
91 (stringify, Stringify) => stringify_expand, 92 (stringify, Stringify) => stringify_expand,
92 (format_args, FormatArgs) => format_args_expand, 93 (format_args, FormatArgs) => format_args_expand,
93 (env, Env) => env_expand,
94 (option_env, OptionEnv) => option_env_expand,
95 // format_args_nl only differs in that it adds a newline in the end, 94 // format_args_nl only differs in that it adds a newline in the end,
96 // so we use the same stub expansion for now 95 // so we use the same stub expansion for now
97 (format_args_nl, FormatArgsNl) => format_args_expand, 96 (format_args_nl, FormatArgsNl) => format_args_expand,
98 97
99 EAGER: 98 EAGER:
100 (concat, Concat) => concat_expand, 99 (concat, Concat) => concat_expand,
101 (include, Include) => include_expand 100 (include, Include) => include_expand,
101 (env, Env) => env_expand,
102 (option_env, OptionEnv) => option_env_expand
102} 103}
103 104
104fn line_expand( 105fn line_expand(
@@ -137,42 +138,56 @@ fn stringify_expand(
137 Ok(expanded) 138 Ok(expanded)
138} 139}
139 140
140fn env_expand( 141fn column_expand(
141 _db: &dyn AstDatabase, 142 _db: &dyn AstDatabase,
142 _id: LazyMacroId, 143 _id: LazyMacroId,
143 _tt: &tt::Subtree, 144 _tt: &tt::Subtree,
144) -> Result<tt::Subtree, mbe::ExpandError> { 145) -> Result<tt::Subtree, mbe::ExpandError> {
145 // dummy implementation for type-checking purposes 146 // dummy implementation for type-checking purposes
146 // we cannot use an empty string here, because for 147 let col_num = 0;
147 // `include!(concat!(env!("OUT_DIR"), "/foo.rs"))` will become 148 let expanded = quote! {
148 // `include!("foo.rs"), which maybe infinite loop 149 #col_num
149 let expanded = quote! { "__RA_UNIMPLEMENTATED__" }; 150 };
150 151
151 Ok(expanded) 152 Ok(expanded)
152} 153}
153 154
154fn option_env_expand( 155fn assert_expand(
155 _db: &dyn AstDatabase, 156 _db: &dyn AstDatabase,
156 _id: LazyMacroId, 157 _id: LazyMacroId,
157 _tt: &tt::Subtree, 158 tt: &tt::Subtree,
158) -> Result<tt::Subtree, mbe::ExpandError> { 159) -> Result<tt::Subtree, mbe::ExpandError> {
159 // dummy implementation for type-checking purposes 160 // A hacky implementation for goto def and hover
160 let expanded = quote! { std::option::Option::None::<&str> }; 161 // We expand `assert!(cond, arg1, arg2)` to
162 // ```
163 // {(cond, &(arg1), &(arg2));}
164 // ```,
165 // which is wrong but useful.
161 166
162 Ok(expanded) 167 let mut args = Vec::new();
163} 168 let mut current = Vec::new();
169 for tt in tt.token_trees.iter().cloned() {
170 match tt {
171 tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => {
172 args.push(current);
173 current = Vec::new();
174 }
175 _ => {
176 current.push(tt);
177 }
178 }
179 }
180 if !current.is_empty() {
181 args.push(current);
182 }
183
184 let arg_tts = args.into_iter().flat_map(|arg| {
185 quote! { &(##arg), }
186 }.token_trees).collect::<Vec<_>>();
164 187
165fn column_expand(
166 _db: &dyn AstDatabase,
167 _id: LazyMacroId,
168 _tt: &tt::Subtree,
169) -> Result<tt::Subtree, mbe::ExpandError> {
170 // dummy implementation for type-checking purposes
171 let col_num = 0;
172 let expanded = quote! { 188 let expanded = quote! {
173 #col_num 189 { { (##arg_tts); } }
174 }; 190 };
175
176 Ok(expanded) 191 Ok(expanded)
177} 192}
178 193
@@ -278,30 +293,37 @@ fn concat_expand(
278 293
279fn relative_file(db: &dyn AstDatabase, call_id: MacroCallId, path: &str) -> Option<FileId> { 294fn relative_file(db: &dyn AstDatabase, call_id: MacroCallId, path: &str) -> Option<FileId> {
280 let call_site = call_id.as_file().original_file(db); 295 let call_site = call_id.as_file().original_file(db);
281 let path = RelativePath::new(&path);
282 296
283 let res = db.resolve_relative_path(call_site, &path)?; 297 // Handle trivial case
284 // Prevent include itself 298 if let Some(res) = db.resolve_relative_path(call_site, &RelativePath::new(&path)) {
285 if res == call_site { 299 // Prevent include itself
286 return None; 300 return if res == call_site { None } else { Some(res) };
287 } 301 }
288 Some(res) 302
303 // Extern paths ?
304 let krate = db.relevant_crates(call_site).get(0)?.clone();
305 let (extern_source_id, relative_file) =
306 db.crate_graph()[krate].extern_source.extern_path(path)?;
307
308 db.resolve_extern_path(extern_source_id, &relative_file)
289} 309}
290 310
291fn include_expand( 311fn parse_string(tt: &tt::Subtree) -> Result<String, mbe::ExpandError> {
292 db: &dyn AstDatabase, 312 tt.token_trees
293 arg_id: EagerMacroId,
294 tt: &tt::Subtree,
295) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> {
296 let path = tt
297 .token_trees
298 .get(0) 313 .get(0)
299 .and_then(|tt| match tt { 314 .and_then(|tt| match tt {
300 tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => unquote_str(&it), 315 tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => unquote_str(&it),
301 _ => None, 316 _ => None,
302 }) 317 })
303 .ok_or_else(|| mbe::ExpandError::ConversionError)?; 318 .ok_or_else(|| mbe::ExpandError::ConversionError)
319}
304 320
321fn include_expand(
322 db: &dyn AstDatabase,
323 arg_id: EagerMacroId,
324 tt: &tt::Subtree,
325) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> {
326 let path = parse_string(tt)?;
305 let file_id = 327 let file_id =
306 relative_file(db, arg_id.into(), &path).ok_or_else(|| mbe::ExpandError::ConversionError)?; 328 relative_file(db, arg_id.into(), &path).ok_or_else(|| mbe::ExpandError::ConversionError)?;
307 329
@@ -314,12 +336,58 @@ fn include_expand(
314 Ok((res, FragmentKind::Items)) 336 Ok((res, FragmentKind::Items))
315} 337}
316 338
339fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> {
340 let call_id: MacroCallId = arg_id.into();
341 let original_file = call_id.as_file().original_file(db);
342
343 let krate = db.relevant_crates(original_file).get(0)?.clone();
344 db.crate_graph()[krate].env.get(key)
345}
346
347fn env_expand(
348 db: &dyn AstDatabase,
349 arg_id: EagerMacroId,
350 tt: &tt::Subtree,
351) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> {
352 let key = parse_string(tt)?;
353
354 // FIXME:
355 // If the environment variable is not defined int rustc, then a compilation error will be emitted.
356 // We might do the same if we fully support all other stuffs.
357 // But for now on, we should return some dummy string for better type infer purpose.
358 // However, we cannot use an empty string here, because for
359 // `include!(concat!(env!("OUT_DIR"), "/foo.rs"))` will become
360 // `include!("foo.rs"), which might go to infinite loop
361 let s = get_env_inner(db, arg_id, &key).unwrap_or("__RA_UNIMPLEMENTATED__".to_string());
362 let expanded = quote! { #s };
363
364 Ok((expanded, FragmentKind::Expr))
365}
366
367fn option_env_expand(
368 db: &dyn AstDatabase,
369 arg_id: EagerMacroId,
370 tt: &tt::Subtree,
371) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> {
372 let key = parse_string(tt)?;
373 let expanded = match get_env_inner(db, arg_id, &key) {
374 None => quote! { std::option::Option::None::<&str> },
375 Some(s) => quote! { std::option::Some(#s) },
376 };
377
378 Ok((expanded, FragmentKind::Expr))
379}
380
317#[cfg(test)] 381#[cfg(test)]
318mod tests { 382mod tests {
319 use super::*; 383 use super::*;
320 use crate::{name::AsName, test_db::TestDB, AstNode, MacroCallId, MacroCallKind, MacroCallLoc}; 384 use crate::{
385 name::AsName, test_db::TestDB, AstNode, EagerCallLoc, MacroCallId, MacroCallKind,
386 MacroCallLoc,
387 };
321 use ra_db::{fixture::WithFixture, SourceDatabase}; 388 use ra_db::{fixture::WithFixture, SourceDatabase};
322 use ra_syntax::ast::NameOwner; 389 use ra_syntax::ast::NameOwner;
390 use std::sync::Arc;
323 391
324 fn expand_builtin_macro(ra_fixture: &str) -> String { 392 fn expand_builtin_macro(ra_fixture: &str) -> String {
325 let (db, file_id) = TestDB::with_single_file(&ra_fixture); 393 let (db, file_id) = TestDB::with_single_file(&ra_fixture);
@@ -330,27 +398,61 @@ mod tests {
330 let ast_id_map = db.ast_id_map(file_id.into()); 398 let ast_id_map = db.ast_id_map(file_id.into());
331 399
332 let expander = find_by_name(&macro_calls[0].name().unwrap().as_name()).unwrap(); 400 let expander = find_by_name(&macro_calls[0].name().unwrap().as_name()).unwrap();
333 let expander = expander.left().unwrap();
334 401
335 // the first one should be a macro_rules 402 let file_id = match expander {
336 let def = MacroDefId { 403 Either::Left(expander) => {
337 krate: Some(CrateId(0)), 404 // the first one should be a macro_rules
338 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))), 405 let def = MacroDefId {
339 kind: MacroDefKind::BuiltIn(expander), 406 krate: Some(CrateId(0)),
340 }; 407 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))),
408 kind: MacroDefKind::BuiltIn(expander),
409 };
341 410
342 let loc = MacroCallLoc { 411 let loc = MacroCallLoc {
343 def, 412 def,
344 kind: MacroCallKind::FnLike(AstId::new( 413 kind: MacroCallKind::FnLike(AstId::new(
345 file_id.into(), 414 file_id.into(),
346 ast_id_map.ast_id(&macro_calls[1]), 415 ast_id_map.ast_id(&macro_calls[1]),
347 )), 416 )),
348 }; 417 };
418
419 let id: MacroCallId = db.intern_macro(loc).into();
420 id.as_file()
421 }
422 Either::Right(expander) => {
423 // the first one should be a macro_rules
424 let def = MacroDefId {
425 krate: Some(CrateId(0)),
426 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))),
427 kind: MacroDefKind::BuiltInEager(expander),
428 };
349 429
350 let id: MacroCallId = db.intern_macro(loc).into(); 430 let args = macro_calls[1].token_tree().unwrap();
351 let parsed = db.parse_or_expand(id.as_file()).unwrap(); 431 let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0;
432
433 let arg_id = db.intern_eager_expansion({
434 EagerCallLoc {
435 def,
436 fragment: FragmentKind::Expr,
437 subtree: Arc::new(parsed_args.clone()),
438 file_id: file_id.into(),
439 }
440 });
441
442 let (subtree, fragment) = expander.expand(&db, arg_id, &parsed_args).unwrap();
443 let eager = EagerCallLoc {
444 def,
445 fragment,
446 subtree: Arc::new(subtree),
447 file_id: file_id.into(),
448 };
352 449
353 parsed.text().to_string() 450 let id: MacroCallId = db.intern_eager_expansion(eager.into()).into();
451 id.as_file()
452 }
453 };
454
455 db.parse_or_expand(file_id).unwrap().to_string()
354 } 456 }
355 457
356 #[test] 458 #[test]
@@ -432,6 +534,22 @@ mod tests {
432 } 534 }
433 535
434 #[test] 536 #[test]
537 fn test_assert_expand() {
538 let expanded = expand_builtin_macro(
539 r#"
540 #[rustc_builtin_macro]
541 macro_rules! assert {
542 ($cond:expr) => ({ /* compiler built-in */ });
543 ($cond:expr, $($args:tt)*) => ({ /* compiler built-in */ })
544 }
545 assert!(true, "{} {:?}", arg1(a, b, c), arg2);
546 "#,
547 );
548
549 assert_eq!(expanded, "{{(&(true), &(\"{} {:?}\"), &(arg1(a,b,c)), &(arg2),);}}");
550 }
551
552 #[test]
435 fn test_compile_error_expand() { 553 fn test_compile_error_expand() {
436 let expanded = expand_builtin_macro( 554 let expanded = expand_builtin_macro(
437 r#" 555 r#"
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs
index 6d201256f..25cc1e9fc 100644
--- a/crates/ra_hir_expand/src/name.rs
+++ b/crates/ra_hir_expand/src/name.rs
@@ -172,6 +172,7 @@ pub mod known {
172 column, 172 column,
173 compile_error, 173 compile_error,
174 line, 174 line,
175 assert,
175 stringify, 176 stringify,
176 concat, 177 concat,
177 include, 178 include,
diff --git a/crates/ra_hir_expand/src/quote.rs b/crates/ra_hir_expand/src/quote.rs
index 57e7eebf9..3fd4233da 100644
--- a/crates/ra_hir_expand/src/quote.rs
+++ b/crates/ra_hir_expand/src/quote.rs
@@ -99,6 +99,7 @@ macro_rules! __quote {
99 ( & ) => {$crate::__quote!(@PUNCT '&')}; 99 ( & ) => {$crate::__quote!(@PUNCT '&')};
100 ( , ) => {$crate::__quote!(@PUNCT ',')}; 100 ( , ) => {$crate::__quote!(@PUNCT ',')};
101 ( : ) => {$crate::__quote!(@PUNCT ':')}; 101 ( : ) => {$crate::__quote!(@PUNCT ':')};
102 ( ; ) => {$crate::__quote!(@PUNCT ';')};
102 ( :: ) => {$crate::__quote!(@PUNCT ':', ':')}; 103 ( :: ) => {$crate::__quote!(@PUNCT ':', ':')};
103 ( . ) => {$crate::__quote!(@PUNCT '.')}; 104 ( . ) => {$crate::__quote!(@PUNCT '.')};
104 ( < ) => {$crate::__quote!(@PUNCT '<')}; 105 ( < ) => {$crate::__quote!(@PUNCT '<')};
diff --git a/crates/ra_hir_expand/src/test_db.rs b/crates/ra_hir_expand/src/test_db.rs
index 918736e2a..c1fb762de 100644
--- a/crates/ra_hir_expand/src/test_db.rs
+++ b/crates/ra_hir_expand/src/test_db.rs
@@ -5,7 +5,7 @@ use std::{
5 sync::{Arc, Mutex}, 5 sync::{Arc, Mutex},
6}; 6};
7 7
8use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath}; 8use ra_db::{salsa, CrateId, ExternSourceId, FileId, FileLoader, FileLoaderDelegate, RelativePath};
9 9
10#[salsa::database( 10#[salsa::database(
11 ra_db::SourceDatabaseExtStorage, 11 ra_db::SourceDatabaseExtStorage,
@@ -51,4 +51,11 @@ impl FileLoader for TestDB {
51 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { 51 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> {
52 FileLoaderDelegate(self).relevant_crates(file_id) 52 FileLoaderDelegate(self).relevant_crates(file_id)
53 } 53 }
54 fn resolve_extern_path(
55 &self,
56 anchor: ExternSourceId,
57 relative_path: &RelativePath,
58 ) -> Option<FileId> {
59 FileLoaderDelegate(self).resolve_extern_path(anchor, relative_path)
60 }
54} 61}
diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs
index c794f7b84..0be2fea4b 100644
--- a/crates/ra_hir_ty/src/test_db.rs
+++ b/crates/ra_hir_ty/src/test_db.rs
@@ -67,6 +67,13 @@ impl FileLoader for TestDB {
67 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { 67 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> {
68 FileLoaderDelegate(self).relevant_crates(file_id) 68 FileLoaderDelegate(self).relevant_crates(file_id)
69 } 69 }
70 fn resolve_extern_path(
71 &self,
72 extern_id: ra_db::ExternSourceId,
73 relative_path: &RelativePath,
74 ) -> Option<FileId> {
75 FileLoaderDelegate(self).resolve_extern_path(extern_id, relative_path)
76 }
70} 77}
71 78
72impl TestDB { 79impl TestDB {
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs
index ffa78b046..32457bbf7 100644
--- a/crates/ra_hir_ty/src/tests/macros.rs
+++ b/crates/ra_hir_ty/src/tests/macros.rs
@@ -550,6 +550,26 @@ fn main() {
550} 550}
551 551
552#[test] 552#[test]
553fn infer_builtin_macros_env() {
554 assert_snapshot!(
555 infer(r#"
556//- /main.rs env:foo=bar
557#[rustc_builtin_macro]
558macro_rules! env {() => {}}
559
560fn main() {
561 let x = env!("foo");
562}
563"#),
564 @r###"
565 ![0; 5) '"bar"': &str
566 [88; 116) '{ ...o"); }': ()
567 [98; 99) 'x': &str
568 "###
569 );
570}
571
572#[test]
553fn infer_derive_clone_simple() { 573fn infer_derive_clone_simple() {
554 let (db, pos) = TestDB::with_position( 574 let (db, pos) = TestDB::with_position(
555 r#" 575 r#"
diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs
index a27e0fc15..93e53c921 100644
--- a/crates/ra_ide/src/completion.rs
+++ b/crates/ra_ide/src/completion.rs
@@ -16,11 +16,11 @@ mod complete_scope;
16mod complete_postfix; 16mod complete_postfix;
17mod complete_macro_in_item_position; 17mod complete_macro_in_item_position;
18mod complete_trait_impl; 18mod complete_trait_impl;
19#[cfg(test)]
20mod test_utils;
19 21
20use ra_ide_db::RootDatabase; 22use ra_ide_db::RootDatabase;
21 23
22#[cfg(test)]
23use crate::completion::completion_item::do_completion;
24use crate::{ 24use crate::{
25 completion::{ 25 completion::{
26 completion_context::CompletionContext, 26 completion_context::CompletionContext,
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs
index d8f6f0d9d..81e5037aa 100644
--- a/crates/ra_ide/src/completion/complete_dot.rs
+++ b/crates/ra_ide/src/completion/complete_dot.rs
@@ -70,7 +70,7 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T
70 70
71#[cfg(test)] 71#[cfg(test)]
72mod tests { 72mod tests {
73 use crate::completion::{do_completion, CompletionItem, CompletionKind}; 73 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
74 use insta::assert_debug_snapshot; 74 use insta::assert_debug_snapshot;
75 75
76 fn do_ref_completion(code: &str) -> Vec<CompletionItem> { 76 fn do_ref_completion(code: &str) -> Vec<CompletionItem> {
diff --git a/crates/ra_ide/src/completion/complete_fn_param.rs b/crates/ra_ide/src/completion/complete_fn_param.rs
index 502458706..9226ac055 100644
--- a/crates/ra_ide/src/completion/complete_fn_param.rs
+++ b/crates/ra_ide/src/completion/complete_fn_param.rs
@@ -52,7 +52,7 @@ pub(super) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
52 52
53#[cfg(test)] 53#[cfg(test)]
54mod tests { 54mod tests {
55 use crate::completion::{do_completion, CompletionItem, CompletionKind}; 55 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
56 use insta::assert_debug_snapshot; 56 use insta::assert_debug_snapshot;
57 57
58 fn do_magic_completion(code: &str) -> Vec<CompletionItem> { 58 fn do_magic_completion(code: &str) -> Vec<CompletionItem> {
diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs
index e1c0ffb1f..1e053ea4a 100644
--- a/crates/ra_ide/src/completion/complete_keyword.rs
+++ b/crates/ra_ide/src/completion/complete_keyword.rs
@@ -117,7 +117,7 @@ fn complete_return(
117 117
118#[cfg(test)] 118#[cfg(test)]
119mod tests { 119mod tests {
120 use crate::completion::{do_completion, CompletionItem, CompletionKind}; 120 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
121 use insta::assert_debug_snapshot; 121 use insta::assert_debug_snapshot;
122 122
123 fn do_keyword_completion(code: &str) -> Vec<CompletionItem> { 123 fn do_keyword_completion(code: &str) -> Vec<CompletionItem> {
diff --git a/crates/ra_ide/src/completion/complete_macro_in_item_position.rs b/crates/ra_ide/src/completion/complete_macro_in_item_position.rs
index 1866d9e6c..270e96df0 100644
--- a/crates/ra_ide/src/completion/complete_macro_in_item_position.rs
+++ b/crates/ra_ide/src/completion/complete_macro_in_item_position.rs
@@ -15,9 +15,10 @@ pub(super) fn complete_macro_in_item_position(acc: &mut Completions, ctx: &Compl
15 15
16#[cfg(test)] 16#[cfg(test)]
17mod tests { 17mod tests {
18 use crate::completion::{do_completion, CompletionItem, CompletionKind};
19 use insta::assert_debug_snapshot; 18 use insta::assert_debug_snapshot;
20 19
20 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
21
21 fn do_reference_completion(code: &str) -> Vec<CompletionItem> { 22 fn do_reference_completion(code: &str) -> Vec<CompletionItem> {
22 do_completion(code, CompletionKind::Reference) 23 do_completion(code, CompletionKind::Reference)
23 } 24 }
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs
index 3c4a70561..d588ee364 100644
--- a/crates/ra_ide/src/completion/complete_path.rs
+++ b/crates/ra_ide/src/completion/complete_path.rs
@@ -103,7 +103,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
103mod tests { 103mod tests {
104 use test_utils::covers; 104 use test_utils::covers;
105 105
106 use crate::completion::{do_completion, CompletionItem, CompletionKind}; 106 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
107 use insta::assert_debug_snapshot; 107 use insta::assert_debug_snapshot;
108 108
109 fn do_reference_completion(code: &str) -> Vec<CompletionItem> { 109 fn do_reference_completion(code: &str) -> Vec<CompletionItem> {
diff --git a/crates/ra_ide/src/completion/complete_pattern.rs b/crates/ra_ide/src/completion/complete_pattern.rs
index fa8aeceda..6a1a66ef1 100644
--- a/crates/ra_ide/src/completion/complete_pattern.rs
+++ b/crates/ra_ide/src/completion/complete_pattern.rs
@@ -27,7 +27,7 @@ pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
27 27
28#[cfg(test)] 28#[cfg(test)]
29mod tests { 29mod tests {
30 use crate::completion::{do_completion, CompletionItem, CompletionKind}; 30 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
31 use insta::assert_debug_snapshot; 31 use insta::assert_debug_snapshot;
32 32
33 fn complete(code: &str) -> Vec<CompletionItem> { 33 fn complete(code: &str) -> Vec<CompletionItem> {
diff --git a/crates/ra_ide/src/completion/complete_postfix.rs b/crates/ra_ide/src/completion/complete_postfix.rs
index 6d000548d..0ba382165 100644
--- a/crates/ra_ide/src/completion/complete_postfix.rs
+++ b/crates/ra_ide/src/completion/complete_postfix.rs
@@ -81,7 +81,7 @@ fn postfix_snippet(ctx: &CompletionContext, label: &str, detail: &str, snippet:
81mod tests { 81mod tests {
82 use insta::assert_debug_snapshot; 82 use insta::assert_debug_snapshot;
83 83
84 use crate::completion::{do_completion, CompletionItem, CompletionKind}; 84 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
85 85
86 fn do_postfix_completion(code: &str) -> Vec<CompletionItem> { 86 fn do_postfix_completion(code: &str) -> Vec<CompletionItem> {
87 do_completion(code, CompletionKind::Postfix) 87 do_completion(code, CompletionKind::Postfix)
diff --git a/crates/ra_ide/src/completion/complete_record_literal.rs b/crates/ra_ide/src/completion/complete_record_literal.rs
index be6e4194f..83ed1d52c 100644
--- a/crates/ra_ide/src/completion/complete_record_literal.rs
+++ b/crates/ra_ide/src/completion/complete_record_literal.rs
@@ -18,7 +18,7 @@ pub(super) fn complete_record_literal(acc: &mut Completions, ctx: &CompletionCon
18 18
19#[cfg(test)] 19#[cfg(test)]
20mod tests { 20mod tests {
21 use crate::completion::{do_completion, CompletionItem, CompletionKind}; 21 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
22 use insta::assert_debug_snapshot; 22 use insta::assert_debug_snapshot;
23 23
24 fn complete(code: &str) -> Vec<CompletionItem> { 24 fn complete(code: &str) -> Vec<CompletionItem> {
diff --git a/crates/ra_ide/src/completion/complete_record_pattern.rs b/crates/ra_ide/src/completion/complete_record_pattern.rs
index 687c57d3e..962376428 100644
--- a/crates/ra_ide/src/completion/complete_record_pattern.rs
+++ b/crates/ra_ide/src/completion/complete_record_pattern.rs
@@ -17,7 +17,7 @@ pub(super) fn complete_record_pattern(acc: &mut Completions, ctx: &CompletionCon
17 17
18#[cfg(test)] 18#[cfg(test)]
19mod tests { 19mod tests {
20 use crate::completion::{do_completion, CompletionItem, CompletionKind}; 20 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
21 use insta::assert_debug_snapshot; 21 use insta::assert_debug_snapshot;
22 22
23 fn complete(code: &str) -> Vec<CompletionItem> { 23 fn complete(code: &str) -> Vec<CompletionItem> {
diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs
index eb3c8cf1b..bd4adf23a 100644
--- a/crates/ra_ide/src/completion/complete_scope.rs
+++ b/crates/ra_ide/src/completion/complete_scope.rs
@@ -14,10 +14,10 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
14mod tests { 14mod tests {
15 use insta::assert_debug_snapshot; 15 use insta::assert_debug_snapshot;
16 16
17 use crate::completion::{do_completion, CompletionItem, CompletionKind}; 17 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
18 18
19 fn do_reference_completion(code: &str) -> Vec<CompletionItem> { 19 fn do_reference_completion(ra_fixture: &str) -> Vec<CompletionItem> {
20 do_completion(code, CompletionKind::Reference) 20 do_completion(ra_fixture, CompletionKind::Reference)
21 } 21 }
22 22
23 #[test] 23 #[test]
diff --git a/crates/ra_ide/src/completion/complete_snippet.rs b/crates/ra_ide/src/completion/complete_snippet.rs
index 731b4fd82..f731e9b9a 100644
--- a/crates/ra_ide/src/completion/complete_snippet.rs
+++ b/crates/ra_ide/src/completion/complete_snippet.rs
@@ -42,7 +42,7 @@ fn ${1:feature}() {
42 42
43#[cfg(test)] 43#[cfg(test)]
44mod tests { 44mod tests {
45 use crate::completion::{do_completion, CompletionItem, CompletionKind}; 45 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
46 use insta::assert_debug_snapshot; 46 use insta::assert_debug_snapshot;
47 47
48 fn do_snippet_completion(code: &str) -> Vec<CompletionItem> { 48 fn do_snippet_completion(code: &str) -> Vec<CompletionItem> {
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs
index 2bf654a57..7fefa2c7a 100644
--- a/crates/ra_ide/src/completion/complete_trait_impl.rs
+++ b/crates/ra_ide/src/completion/complete_trait_impl.rs
@@ -217,7 +217,7 @@ fn make_const_compl_syntax(const_: &ast::ConstDef) -> String {
217 217
218#[cfg(test)] 218#[cfg(test)]
219mod tests { 219mod tests {
220 use crate::completion::{do_completion, CompletionItem, CompletionKind}; 220 use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind};
221 use insta::assert_debug_snapshot; 221 use insta::assert_debug_snapshot;
222 222
223 fn complete(code: &str) -> Vec<CompletionItem> { 223 fn complete(code: &str) -> Vec<CompletionItem> {
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs
index 1d14e9636..ef0eb43b2 100644
--- a/crates/ra_ide/src/completion/completion_item.rs
+++ b/crates/ra_ide/src/completion/completion_item.rs
@@ -13,7 +13,7 @@ pub struct CompletionItem {
13 /// Used only internally in tests, to check only specific kind of 13 /// Used only internally in tests, to check only specific kind of
14 /// completion (postfix, keyword, reference, etc). 14 /// completion (postfix, keyword, reference, etc).
15 #[allow(unused)] 15 #[allow(unused)]
16 completion_kind: CompletionKind, 16 pub(crate) completion_kind: CompletionKind,
17 /// Label in the completion pop up which identifies completion. 17 /// Label in the completion pop up which identifies completion.
18 label: String, 18 label: String,
19 /// Range of identifier that is being completed. 19 /// Range of identifier that is being completed.
@@ -318,24 +318,3 @@ impl Into<Vec<CompletionItem>> for Completions {
318 self.buf 318 self.buf
319 } 319 }
320} 320}
321
322#[cfg(test)]
323pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
324 use crate::{
325 completion::{completions, CompletionOptions},
326 mock_analysis::{analysis_and_position, single_file_with_position},
327 };
328
329 let (analysis, position) = if code.contains("//-") {
330 analysis_and_position(code)
331 } else {
332 single_file_with_position(code)
333 };
334 let options = CompletionOptions::default();
335 let completions = completions(&analysis.db, position, &options).unwrap();
336 let completion_items: Vec<CompletionItem> = completions.into();
337 let mut kind_completions: Vec<CompletionItem> =
338 completion_items.into_iter().filter(|c| c.completion_kind == kind).collect();
339 kind_completions.sort_by_key(|c| c.label.clone());
340 kind_completions
341}
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 3dc56e4a3..5213def20 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -307,12 +307,22 @@ mod tests {
307 use insta::assert_debug_snapshot; 307 use insta::assert_debug_snapshot;
308 use test_utils::covers; 308 use test_utils::covers;
309 309
310 use crate::completion::{do_completion, CompletionItem, CompletionKind}; 310 use crate::completion::{
311 test_utils::{do_completion, do_completion_with_options},
312 CompletionItem, CompletionKind, CompletionOptions,
313 };
311 314
312 fn do_reference_completion(ra_fixture: &str) -> Vec<CompletionItem> { 315 fn do_reference_completion(ra_fixture: &str) -> Vec<CompletionItem> {
313 do_completion(ra_fixture, CompletionKind::Reference) 316 do_completion(ra_fixture, CompletionKind::Reference)
314 } 317 }
315 318
319 fn do_reference_completion_with_options(
320 ra_fixture: &str,
321 options: CompletionOptions,
322 ) -> Vec<CompletionItem> {
323 do_completion_with_options(ra_fixture, CompletionKind::Reference, &options)
324 }
325
316 #[test] 326 #[test]
317 fn enum_detail_includes_names_for_record() { 327 fn enum_detail_includes_names_for_record() {
318 assert_debug_snapshot!( 328 assert_debug_snapshot!(
@@ -533,7 +543,7 @@ mod tests {
533 } 543 }
534 544
535 #[test] 545 #[test]
536 fn parens_for_method_call() { 546 fn arg_snippets_for_method_call() {
537 assert_debug_snapshot!( 547 assert_debug_snapshot!(
538 do_reference_completion( 548 do_reference_completion(
539 r" 549 r"
@@ -563,6 +573,40 @@ mod tests {
563 } 573 }
564 574
565 #[test] 575 #[test]
576 fn no_arg_snippets_for_method_call() {
577 assert_debug_snapshot!(
578 do_reference_completion_with_options(
579 r"
580 struct S {}
581 impl S {
582 fn foo(&self, x: i32) {}
583 }
584 fn bar(s: &S) {
585 s.f<|>
586 }
587 ",
588 CompletionOptions {
589 add_call_argument_snippets: false,
590 .. Default::default()
591 }
592 ),
593 @r###"
594 [
595 CompletionItem {
596 label: "foo(…)",
597 source_range: [171; 172),
598 delete: [171; 172),
599 insert: "foo($0)",
600 kind: Method,
601 lookup: "foo",
602 detail: "fn foo(&self, x: i32)",
603 },
604 ]
605 "###
606 )
607 }
608
609 #[test]
566 fn dont_render_function_parens_in_use_item() { 610 fn dont_render_function_parens_in_use_item() {
567 assert_debug_snapshot!( 611 assert_debug_snapshot!(
568 do_reference_completion( 612 do_reference_completion(
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs
new file mode 100644
index 000000000..136857315
--- /dev/null
+++ b/crates/ra_ide/src/completion/test_utils.rs
@@ -0,0 +1,29 @@
1//! Runs completion for testing purposes.
2
3use crate::{
4 completion::{completion_item::CompletionKind, CompletionOptions},
5 mock_analysis::{analysis_and_position, single_file_with_position},
6 CompletionItem,
7};
8
9pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
10 do_completion_with_options(code, kind, &CompletionOptions::default())
11}
12
13pub(crate) fn do_completion_with_options(
14 code: &str,
15 kind: CompletionKind,
16 options: &CompletionOptions,
17) -> Vec<CompletionItem> {
18 let (analysis, position) = if code.contains("//-") {
19 analysis_and_position(code)
20 } else {
21 single_file_with_position(code)
22 };
23 let completions = analysis.completions(position, options).unwrap().unwrap();
24 let completion_items: Vec<CompletionItem> = completions.into();
25 let mut kind_completions: Vec<CompletionItem> =
26 completion_items.into_iter().filter(|c| c.completion_kind == kind).collect();
27 kind_completions.sort_by_key(|c| c.label().to_owned());
28 kind_completions
29}
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index 25e038a55..0bbba4855 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -833,19 +833,34 @@ fn func(foo: i32) { if true { <|>foo; }; }
833 } 833 }
834 834
835 #[test] 835 #[test]
836 fn test_hover_through_assert_macro() {
837 let hover_on = check_hover_result(
838 r#"
839 //- /lib.rs
840 #[rustc_builtin_macro]
841 macro_rules! assert {}
842
843 fn bar() -> bool { true }
844 fn foo() {
845 assert!(ba<|>r());
846 }
847 "#,
848 &["fn bar() -> bool"],
849 );
850
851 assert_eq!(hover_on, "bar");
852 }
853
854 #[test]
836 fn test_hover_through_literal_string_in_builtin_macro() { 855 fn test_hover_through_literal_string_in_builtin_macro() {
837 check_hover_no_result( 856 check_hover_no_result(
838 r#" 857 r#"
839 //- /lib.rs 858 //- /lib.rs
840 #[rustc_builtin_macro] 859 #[rustc_builtin_macro]
841 macro_rules! assert { 860 macro_rules! format {}
842 ($cond:expr) => {{ /* compiler built-in */ }};
843 ($cond:expr,) => {{ /* compiler built-in */ }};
844 ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }};
845 }
846 861
847 fn foo() { 862 fn foo() {
848 assert!("hel<|>lo"); 863 format!("hel<|>lo {}", 0);
849 } 864 }
850 "#, 865 "#,
851 ); 866 );
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index a3acfd225..922e4caa8 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -212,6 +212,7 @@ impl Analysis {
212 None, 212 None,
213 cfg_options, 213 cfg_options,
214 Env::default(), 214 Env::default(),
215 Default::default(),
215 ); 216 );
216 change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text)); 217 change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text));
217 change.set_crate_graph(crate_graph); 218 change.set_crate_graph(crate_graph);
diff --git a/crates/ra_ide/src/mock_analysis.rs b/crates/ra_ide/src/mock_analysis.rs
index 90f84b052..25816cf6f 100644
--- a/crates/ra_ide/src/mock_analysis.rs
+++ b/crates/ra_ide/src/mock_analysis.rs
@@ -102,6 +102,7 @@ impl MockAnalysis {
102 None, 102 None,
103 cfg_options, 103 cfg_options,
104 Env::default(), 104 Env::default(),
105 Default::default(),
105 )); 106 ));
106 } else if path.ends_with("/lib.rs") { 107 } else if path.ends_with("/lib.rs") {
107 let crate_name = path.parent().unwrap().file_name().unwrap(); 108 let crate_name = path.parent().unwrap().file_name().unwrap();
@@ -111,6 +112,7 @@ impl MockAnalysis {
111 Some(crate_name.to_owned()), 112 Some(crate_name.to_owned()),
112 cfg_options, 113 cfg_options,
113 Env::default(), 114 Env::default(),
115 Default::default(),
114 ); 116 );
115 if let Some(root_crate) = root_crate { 117 if let Some(root_crate) = root_crate {
116 crate_graph 118 crate_graph
diff --git a/crates/ra_ide/src/parent_module.rs b/crates/ra_ide/src/parent_module.rs
index b73cefd97..76d130b9b 100644
--- a/crates/ra_ide/src/parent_module.rs
+++ b/crates/ra_ide/src/parent_module.rs
@@ -136,6 +136,7 @@ mod tests {
136 None, 136 None,
137 CfgOptions::default(), 137 CfgOptions::default(),
138 Env::default(), 138 Env::default(),
139 Default::default(),
139 ); 140 );
140 let mut change = AnalysisChange::new(); 141 let mut change = AnalysisChange::new();
141 change.set_crate_graph(crate_graph); 142 change.set_crate_graph(crate_graph);
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs
index 5b4bcf434..7d1190af9 100644
--- a/crates/ra_ide/src/references/rename.rs
+++ b/crates/ra_ide/src/references/rename.rs
@@ -9,7 +9,8 @@ use ra_syntax::{
9use ra_text_edit::TextEdit; 9use ra_text_edit::TextEdit;
10 10
11use crate::{ 11use crate::{
12 FileId, FilePosition, FileSystemEdit, RangeInfo, SourceChange, SourceFileEdit, TextRange, 12 FilePosition, FileSystemEdit, RangeInfo, Reference, ReferenceKind, SourceChange,
13 SourceFileEdit, TextRange,
13}; 14};
14 15
15use super::find_all_refs; 16use super::find_all_refs;
@@ -46,12 +47,29 @@ fn find_name_and_module_at_offset(
46 Some((ast_name, ast_module)) 47 Some((ast_name, ast_module))
47} 48}
48 49
49fn source_edit_from_file_id_range( 50fn source_edit_from_reference(reference: Reference, new_name: &str) -> SourceFileEdit {
50 file_id: FileId, 51 let mut replacement_text = String::new();
51 range: TextRange, 52 let file_id = reference.file_range.file_id;
52 new_name: &str, 53 let range = match reference.kind {
53) -> SourceFileEdit { 54 ReferenceKind::StructFieldShorthandForField => {
54 SourceFileEdit { file_id, edit: TextEdit::replace(range, new_name.into()) } 55 replacement_text.push_str(new_name);
56 replacement_text.push_str(": ");
57 TextRange::from_to(
58 reference.file_range.range.start(),
59 reference.file_range.range.start(),
60 )
61 }
62 ReferenceKind::StructFieldShorthandForLocal => {
63 replacement_text.push_str(": ");
64 replacement_text.push_str(new_name);
65 TextRange::from_to(reference.file_range.range.end(), reference.file_range.range.end())
66 }
67 _ => {
68 replacement_text.push_str(new_name);
69 reference.file_range.range
70 }
71 };
72 SourceFileEdit { file_id, edit: TextEdit::replace(range, replacement_text) }
55} 73}
56 74
57fn rename_mod( 75fn rename_mod(
@@ -99,13 +117,10 @@ fn rename_mod(
99 source_file_edits.push(edit); 117 source_file_edits.push(edit);
100 118
101 if let Some(RangeInfo { range: _, info: refs }) = find_all_refs(sema.db, position, None) { 119 if let Some(RangeInfo { range: _, info: refs }) = find_all_refs(sema.db, position, None) {
102 let ref_edits = refs.references.into_iter().map(|reference| { 120 let ref_edits = refs
103 source_edit_from_file_id_range( 121 .references
104 reference.file_range.file_id, 122 .into_iter()
105 reference.file_range.range, 123 .map(|reference| source_edit_from_reference(reference, new_name));
106 new_name,
107 )
108 });
109 source_file_edits.extend(ref_edits); 124 source_file_edits.extend(ref_edits);
110 } 125 }
111 126
@@ -121,13 +136,7 @@ fn rename_reference(
121 136
122 let edit = refs 137 let edit = refs
123 .into_iter() 138 .into_iter()
124 .map(|reference| { 139 .map(|reference| source_edit_from_reference(reference, new_name))
125 source_edit_from_file_id_range(
126 reference.file_range.file_id,
127 reference.file_range.range,
128 new_name,
129 )
130 })
131 .collect::<Vec<_>>(); 140 .collect::<Vec<_>>();
132 141
133 if edit.is_empty() { 142 if edit.is_empty() {
@@ -286,6 +295,163 @@ mod tests {
286 } 295 }
287 296
288 #[test] 297 #[test]
298 fn test_rename_struct_field() {
299 test_rename(
300 r#"
301 struct Foo {
302 i<|>: i32,
303 }
304
305 impl Foo {
306 fn new(i: i32) -> Self {
307 Self { i: i }
308 }
309 }
310 "#,
311 "j",
312 r#"
313 struct Foo {
314 j: i32,
315 }
316
317 impl Foo {
318 fn new(i: i32) -> Self {
319 Self { j: i }
320 }
321 }
322 "#,
323 );
324 }
325
326 #[test]
327 fn test_rename_struct_field_for_shorthand() {
328 test_rename(
329 r#"
330 struct Foo {
331 i<|>: i32,
332 }
333
334 impl Foo {
335 fn new(i: i32) -> Self {
336 Self { i }
337 }
338 }
339 "#,
340 "j",
341 r#"
342 struct Foo {
343 j: i32,
344 }
345
346 impl Foo {
347 fn new(i: i32) -> Self {
348 Self { j: i }
349 }
350 }
351 "#,
352 );
353 }
354
355 #[test]
356 fn test_rename_local_for_field_shorthand() {
357 test_rename(
358 r#"
359 struct Foo {
360 i: i32,
361 }
362
363 impl Foo {
364 fn new(i<|>: i32) -> Self {
365 Self { i }
366 }
367 }
368 "#,
369 "j",
370 r#"
371 struct Foo {
372 i: i32,
373 }
374
375 impl Foo {
376 fn new(j: i32) -> Self {
377 Self { i: j }
378 }
379 }
380 "#,
381 );
382 }
383
384 #[test]
385 fn test_field_shorthand_correct_struct() {
386 test_rename(
387 r#"
388 struct Foo {
389 i<|>: i32,
390 }
391
392 struct Bar {
393 i: i32,
394 }
395
396 impl Bar {
397 fn new(i: i32) -> Self {
398 Self { i }
399 }
400 }
401 "#,
402 "j",
403 r#"
404 struct Foo {
405 j: i32,
406 }
407
408 struct Bar {
409 i: i32,
410 }
411
412 impl Bar {
413 fn new(i: i32) -> Self {
414 Self { i }
415 }
416 }
417 "#,
418 );
419 }
420
421 #[test]
422 fn test_shadow_local_for_struct_shorthand() {
423 test_rename(
424 r#"
425 struct Foo {
426 i: i32,
427 }
428
429 fn baz(i<|>: i32) -> Self {
430 let x = Foo { i };
431 {
432 let i = 0;
433 Foo { i }
434 }
435 }
436 "#,
437 "j",
438 r#"
439 struct Foo {
440 i: i32,
441 }
442
443 fn baz(j: i32) -> Self {
444 let x = Foo { i: j };
445 {
446 let i = 0;
447 Foo { i }
448 }
449 }
450 "#,
451 );
452 }
453
454 #[test]
289 fn test_rename_mod() { 455 fn test_rename_mod() {
290 let (analysis, position) = analysis_and_position( 456 let (analysis, position) = analysis_and_position(
291 " 457 "
diff --git a/crates/ra_ide/src/typing.rs b/crates/ra_ide/src/typing.rs
index 7f1b9150f..53c65f8bc 100644
--- a/crates/ra_ide/src/typing.rs
+++ b/crates/ra_ide/src/typing.rs
@@ -13,77 +13,21 @@
13//! Language server executes such typing assists synchronously. That is, they 13//! Language server executes such typing assists synchronously. That is, they
14//! block user's typing and should be pretty fast for this reason! 14//! block user's typing and should be pretty fast for this reason!
15 15
16mod on_enter;
17
16use ra_db::{FilePosition, SourceDatabase}; 18use ra_db::{FilePosition, SourceDatabase};
17use ra_fmt::leading_indent; 19use ra_fmt::leading_indent;
18use ra_ide_db::RootDatabase; 20use ra_ide_db::RootDatabase;
19use ra_syntax::{ 21use ra_syntax::{
20 algo::find_node_at_offset, 22 algo::find_node_at_offset,
21 ast::{self, AstToken}, 23 ast::{self, AstToken},
22 AstNode, SmolStr, SourceFile, 24 AstNode, SourceFile, TextRange, TextUnit,
23 SyntaxKind::*,
24 SyntaxToken, TextRange, TextUnit, TokenAtOffset,
25}; 25};
26use ra_text_edit::TextEdit; 26use ra_text_edit::TextEdit;
27 27
28use crate::{source_change::SingleFileChange, SourceChange, SourceFileEdit}; 28use crate::{source_change::SingleFileChange, SourceChange};
29
30pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<SourceChange> {
31 let parse = db.parse(position.file_id);
32 let file = parse.tree();
33 let comment = file
34 .syntax()
35 .token_at_offset(position.offset)
36 .left_biased()
37 .and_then(ast::Comment::cast)?;
38
39 if comment.kind().shape.is_block() {
40 return None;
41 }
42
43 let prefix = comment.prefix();
44 let comment_range = comment.syntax().text_range();
45 if position.offset < comment_range.start() + TextUnit::of_str(prefix) {
46 return None;
47 }
48
49 // Continuing non-doc line comments (like this one :) ) is annoying
50 if prefix == "//" && comment_range.end() == position.offset {
51 return None;
52 }
53
54 let indent = node_indent(&file, comment.syntax())?;
55 let inserted = format!("\n{}{} ", indent, prefix);
56 let cursor_position = position.offset + TextUnit::of_str(&inserted);
57 let edit = TextEdit::insert(position.offset, inserted);
58 29
59 Some( 30pub(crate) use on_enter::on_enter;
60 SourceChange::source_file_edit(
61 "on enter",
62 SourceFileEdit { edit, file_id: position.file_id },
63 )
64 .with_cursor(FilePosition { offset: cursor_position, file_id: position.file_id }),
65 )
66}
67
68fn node_indent(file: &SourceFile, token: &SyntaxToken) -> Option<SmolStr> {
69 let ws = match file.syntax().token_at_offset(token.text_range().start()) {
70 TokenAtOffset::Between(l, r) => {
71 assert!(r == *token);
72 l
73 }
74 TokenAtOffset::Single(n) => {
75 assert!(n == *token);
76 return Some("".into());
77 }
78 TokenAtOffset::None => unreachable!(),
79 };
80 if ws.kind() != WHITESPACE {
81 return None;
82 }
83 let text = ws.text();
84 let pos = text.rfind('\n').map(|it| it + 1).unwrap_or(0);
85 Some(text[pos..].into())
86}
87 31
88pub(crate) const TRIGGER_CHARS: &str = ".=>"; 32pub(crate) const TRIGGER_CHARS: &str = ".=>";
89 33
@@ -196,102 +140,10 @@ fn on_arrow_typed(file: &SourceFile, offset: TextUnit) -> Option<SingleFileChang
196 140
197#[cfg(test)] 141#[cfg(test)]
198mod tests { 142mod tests {
199 use test_utils::{add_cursor, assert_eq_text, extract_offset}; 143 use test_utils::{assert_eq_text, extract_offset};
200
201 use crate::mock_analysis::single_file;
202 144
203 use super::*; 145 use super::*;
204 146
205 #[test]
206 fn test_on_enter() {
207 fn apply_on_enter(before: &str) -> Option<String> {
208 let (offset, before) = extract_offset(before);
209 let (analysis, file_id) = single_file(&before);
210 let result = analysis.on_enter(FilePosition { offset, file_id }).unwrap()?;
211
212 assert_eq!(result.source_file_edits.len(), 1);
213 let actual = result.source_file_edits[0].edit.apply(&before);
214 let actual = add_cursor(&actual, result.cursor_position.unwrap().offset);
215 Some(actual)
216 }
217
218 fn do_check(before: &str, after: &str) {
219 let actual = apply_on_enter(before).unwrap();
220 assert_eq_text!(after, &actual);
221 }
222
223 fn do_check_noop(text: &str) {
224 assert!(apply_on_enter(text).is_none())
225 }
226
227 do_check(
228 r"
229/// Some docs<|>
230fn foo() {
231}
232",
233 r"
234/// Some docs
235/// <|>
236fn foo() {
237}
238",
239 );
240 do_check(
241 r"
242impl S {
243 /// Some<|> docs.
244 fn foo() {}
245}
246",
247 r"
248impl S {
249 /// Some
250 /// <|> docs.
251 fn foo() {}
252}
253",
254 );
255 do_check(
256 r"
257fn main() {
258 // Fix<|> me
259 let x = 1 + 1;
260}
261",
262 r"
263fn main() {
264 // Fix
265 // <|> me
266 let x = 1 + 1;
267}
268",
269 );
270 do_check(
271 r"
272///<|> Some docs
273fn foo() {
274}
275",
276 r"
277///
278/// <|> Some docs
279fn foo() {
280}
281",
282 );
283 do_check_noop(
284 r"
285fn main() {
286 // Fix me<|>
287 let x = 1 + 1;
288}
289",
290 );
291
292 do_check_noop(r"<|>//! docz");
293 }
294
295 fn do_type_char(char_typed: char, before: &str) -> Option<(String, SingleFileChange)> { 147 fn do_type_char(char_typed: char, before: &str) -> Option<(String, SingleFileChange)> {
296 let (offset, before) = extract_offset(before); 148 let (offset, before) = extract_offset(before);
297 let edit = TextEdit::insert(offset, char_typed.to_string()); 149 let edit = TextEdit::insert(offset, char_typed.to_string());
diff --git a/crates/ra_ide/src/typing/on_enter.rs b/crates/ra_ide/src/typing/on_enter.rs
new file mode 100644
index 000000000..6bcf2d72b
--- /dev/null
+++ b/crates/ra_ide/src/typing/on_enter.rs
@@ -0,0 +1,216 @@
1//! Handles the `Enter` key press. At the momently, this only continues
2//! comments, but should handle indent some time in the future as well.
3
4use ra_db::{FilePosition, SourceDatabase};
5use ra_ide_db::RootDatabase;
6use ra_syntax::{
7 ast::{self, AstToken},
8 AstNode, SmolStr, SourceFile,
9 SyntaxKind::*,
10 SyntaxToken, TextUnit, TokenAtOffset,
11};
12use ra_text_edit::TextEdit;
13
14use crate::{SourceChange, SourceFileEdit};
15
16pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<SourceChange> {
17 let parse = db.parse(position.file_id);
18 let file = parse.tree();
19 let comment = file
20 .syntax()
21 .token_at_offset(position.offset)
22 .left_biased()
23 .and_then(ast::Comment::cast)?;
24
25 if comment.kind().shape.is_block() {
26 return None;
27 }
28
29 let prefix = comment.prefix();
30 let comment_range = comment.syntax().text_range();
31 if position.offset < comment_range.start() + TextUnit::of_str(prefix) {
32 return None;
33 }
34
35 // Continuing single-line non-doc comments (like this one :) ) is annoying
36 if prefix == "//" && comment_range.end() == position.offset && !followed_by_comment(&comment) {
37 return None;
38 }
39
40 let indent = node_indent(&file, comment.syntax())?;
41 let inserted = format!("\n{}{} ", indent, prefix);
42 let cursor_position = position.offset + TextUnit::of_str(&inserted);
43 let edit = TextEdit::insert(position.offset, inserted);
44
45 Some(
46 SourceChange::source_file_edit(
47 "on enter",
48 SourceFileEdit { edit, file_id: position.file_id },
49 )
50 .with_cursor(FilePosition { offset: cursor_position, file_id: position.file_id }),
51 )
52}
53
54fn followed_by_comment(comment: &ast::Comment) -> bool {
55 let ws = match comment.syntax().next_token().and_then(ast::Whitespace::cast) {
56 Some(it) => it,
57 None => return false,
58 };
59 if ws.spans_multiple_lines() {
60 return false;
61 }
62 ws.syntax().next_token().and_then(ast::Comment::cast).is_some()
63}
64
65fn node_indent(file: &SourceFile, token: &SyntaxToken) -> Option<SmolStr> {
66 let ws = match file.syntax().token_at_offset(token.text_range().start()) {
67 TokenAtOffset::Between(l, r) => {
68 assert!(r == *token);
69 l
70 }
71 TokenAtOffset::Single(n) => {
72 assert!(n == *token);
73 return Some("".into());
74 }
75 TokenAtOffset::None => unreachable!(),
76 };
77 if ws.kind() != WHITESPACE {
78 return None;
79 }
80 let text = ws.text();
81 let pos = text.rfind('\n').map(|it| it + 1).unwrap_or(0);
82 Some(text[pos..].into())
83}
84
85#[cfg(test)]
86mod tests {
87 use test_utils::{add_cursor, assert_eq_text, extract_offset};
88
89 use crate::mock_analysis::single_file;
90
91 use super::*;
92
93 fn apply_on_enter(before: &str) -> Option<String> {
94 let (offset, before) = extract_offset(before);
95 let (analysis, file_id) = single_file(&before);
96 let result = analysis.on_enter(FilePosition { offset, file_id }).unwrap()?;
97
98 assert_eq!(result.source_file_edits.len(), 1);
99 let actual = result.source_file_edits[0].edit.apply(&before);
100 let actual = add_cursor(&actual, result.cursor_position.unwrap().offset);
101 Some(actual)
102 }
103
104 fn do_check(ra_fixture_before: &str, ra_fixture_after: &str) {
105 let actual = apply_on_enter(ra_fixture_before).unwrap();
106 assert_eq_text!(ra_fixture_after, &actual);
107 }
108
109 fn do_check_noop(ra_fixture_text: &str) {
110 assert!(apply_on_enter(ra_fixture_text).is_none())
111 }
112
113 #[test]
114 fn continues_doc_comment() {
115 do_check(
116 r"
117/// Some docs<|>
118fn foo() {
119}
120",
121 r"
122/// Some docs
123/// <|>
124fn foo() {
125}
126",
127 );
128
129 do_check(
130 r"
131impl S {
132 /// Some<|> docs.
133 fn foo() {}
134}
135",
136 r"
137impl S {
138 /// Some
139 /// <|> docs.
140 fn foo() {}
141}
142",
143 );
144
145 do_check(
146 r"
147///<|> Some docs
148fn foo() {
149}
150",
151 r"
152///
153/// <|> Some docs
154fn foo() {
155}
156",
157 );
158 }
159
160 #[test]
161 fn does_not_continue_before_doc_comment() {
162 do_check_noop(r"<|>//! docz");
163 }
164
165 #[test]
166 fn continues_code_comment_in_the_middle_of_line() {
167 do_check(
168 r"
169fn main() {
170 // Fix<|> me
171 let x = 1 + 1;
172}
173",
174 r"
175fn main() {
176 // Fix
177 // <|> me
178 let x = 1 + 1;
179}
180",
181 );
182 }
183
184 #[test]
185 fn continues_code_comment_in_the_middle_several_lines() {
186 do_check(
187 r"
188fn main() {
189 // Fix<|>
190 // me
191 let x = 1 + 1;
192}
193",
194 r"
195fn main() {
196 // Fix
197 // <|>
198 // me
199 let x = 1 + 1;
200}
201",
202 );
203 }
204
205 #[test]
206 fn does_not_continue_end_of_code_comment() {
207 do_check_noop(
208 r"
209fn main() {
210 // Fix me<|>
211 let x = 1 + 1;
212}
213",
214 );
215 }
216}
diff --git a/crates/ra_ide_db/src/lib.rs b/crates/ra_ide_db/src/lib.rs
index 6bcccc848..fc1b19def 100644
--- a/crates/ra_ide_db/src/lib.rs
+++ b/crates/ra_ide_db/src/lib.rs
@@ -55,6 +55,13 @@ impl FileLoader for RootDatabase {
55 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { 55 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> {
56 FileLoaderDelegate(self).relevant_crates(file_id) 56 FileLoaderDelegate(self).relevant_crates(file_id)
57 } 57 }
58 fn resolve_extern_path(
59 &self,
60 extern_id: ra_db::ExternSourceId,
61 relative_path: &RelativePath,
62 ) -> Option<FileId> {
63 FileLoaderDelegate(self).resolve_extern_path(extern_id, relative_path)
64 }
58} 65}
59 66
60impl salsa::Database for RootDatabase { 67impl salsa::Database for RootDatabase {
diff --git a/crates/ra_ide_db/src/search.rs b/crates/ra_ide_db/src/search.rs
index 6f198df04..cf78d3e41 100644
--- a/crates/ra_ide_db/src/search.rs
+++ b/crates/ra_ide_db/src/search.rs
@@ -17,7 +17,7 @@ use rustc_hash::FxHashMap;
17use test_utils::tested_by; 17use test_utils::tested_by;
18 18
19use crate::{ 19use crate::{
20 defs::{classify_name_ref, Definition}, 20 defs::{classify_name_ref, Definition, NameRefClass},
21 RootDatabase, 21 RootDatabase,
22}; 22};
23 23
@@ -30,6 +30,8 @@ pub struct Reference {
30 30
31#[derive(Debug, Clone, PartialEq)] 31#[derive(Debug, Clone, PartialEq)]
32pub enum ReferenceKind { 32pub enum ReferenceKind {
33 StructFieldShorthandForField,
34 StructFieldShorthandForLocal,
33 StructLiteral, 35 StructLiteral,
34 Other, 36 Other,
35} 37}
@@ -237,9 +239,8 @@ impl Definition {
237 // FIXME: reuse sb 239 // FIXME: reuse sb
238 // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098 240 // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098
239 241
240 if let Some(d) = classify_name_ref(&sema, &name_ref) { 242 match classify_name_ref(&sema, &name_ref) {
241 let d = d.definition(); 243 Some(NameRefClass::Definition(def)) if &def == self => {
242 if &d == self {
243 let kind = if is_record_lit_name_ref(&name_ref) 244 let kind = if is_record_lit_name_ref(&name_ref)
244 || is_call_expr_name_ref(&name_ref) 245 || is_call_expr_name_ref(&name_ref)
245 { 246 {
@@ -252,9 +253,26 @@ impl Definition {
252 refs.push(Reference { 253 refs.push(Reference {
253 file_range, 254 file_range,
254 kind, 255 kind,
255 access: reference_access(&d, &name_ref), 256 access: reference_access(&def, &name_ref),
256 }); 257 });
257 } 258 }
259 Some(NameRefClass::FieldShorthand { local, field }) => {
260 match self {
261 Definition::StructField(_) if &field == self => refs.push(Reference {
262 file_range: sema.original_range(name_ref.syntax()),
263 kind: ReferenceKind::StructFieldShorthandForField,
264 access: reference_access(&field, &name_ref),
265 }),
266 Definition::Local(l) if &local == l => refs.push(Reference {
267 file_range: sema.original_range(name_ref.syntax()),
268 kind: ReferenceKind::StructFieldShorthandForLocal,
269 access: reference_access(&Definition::Local(local), &name_ref),
270 }),
271
272 _ => {} // not a usage
273 };
274 }
275 _ => {} // not a usage
258 } 276 }
259 } 277 }
260 } 278 }
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 4163a2cf5..0c170ac5e 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -278,7 +278,7 @@ fn current_op(p: &Parser) -> (u8, SyntaxKind) {
278} 278}
279 279
280// Parses expression with binding power of at least bp. 280// Parses expression with binding power of at least bp.
281fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> (Option<CompletedMarker>, BlockLike) { 281fn expr_bp(p: &mut Parser, mut r: Restrictions, bp: u8) -> (Option<CompletedMarker>, BlockLike) {
282 let mut lhs = match lhs(p, r) { 282 let mut lhs = match lhs(p, r) {
283 Some((lhs, blocklike)) => { 283 Some((lhs, blocklike)) => {
284 // test stmt_bin_expr_ambiguity 284 // test stmt_bin_expr_ambiguity
@@ -311,6 +311,12 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> (Option<CompletedMarker>,
311 let m = lhs.precede(p); 311 let m = lhs.precede(p);
312 p.bump(op); 312 p.bump(op);
313 313
314 // test binop_resets_statementness
315 // fn foo() {
316 // v = {1}&2;
317 // }
318 r = Restrictions { prefer_stmt: false, ..r };
319
314 if is_range { 320 if is_range {
315 // test postfix_range 321 // test postfix_range
316 // fn foo() { 322 // fn foo() {
@@ -327,7 +333,7 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> (Option<CompletedMarker>,
327 } 333 }
328 } 334 }
329 335
330 expr_bp(p, r, op_bp + 1); 336 expr_bp(p, Restrictions { prefer_stmt: false, ..r }, op_bp + 1);
331 lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); 337 lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR });
332 } 338 }
333 (Some(lhs), BlockLike::NotBlock) 339 (Some(lhs), BlockLike::NotBlock)
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 37845ca56..a6274709d 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -14,7 +14,7 @@ use std::{
14 14
15use anyhow::{bail, Context, Result}; 15use anyhow::{bail, Context, Result};
16use ra_cfg::CfgOptions; 16use ra_cfg::CfgOptions;
17use ra_db::{CrateGraph, CrateName, Edition, Env, FileId}; 17use ra_db::{CrateGraph, CrateName, Edition, Env, ExternSource, ExternSourceId, FileId};
18use rustc_hash::FxHashMap; 18use rustc_hash::FxHashMap;
19use serde_json::from_reader; 19use serde_json::from_reader;
20 20
@@ -162,6 +162,7 @@ impl ProjectWorkspace {
162 pub fn to_crate_graph( 162 pub fn to_crate_graph(
163 &self, 163 &self,
164 default_cfg_options: &CfgOptions, 164 default_cfg_options: &CfgOptions,
165 outdirs: &FxHashMap<String, (ExternSourceId, String)>,
165 load: &mut dyn FnMut(&Path) -> Option<FileId>, 166 load: &mut dyn FnMut(&Path) -> Option<FileId>,
166 ) -> CrateGraph { 167 ) -> CrateGraph {
167 let mut crate_graph = CrateGraph::default(); 168 let mut crate_graph = CrateGraph::default();
@@ -185,6 +186,8 @@ impl ProjectWorkspace {
185 } 186 }
186 opts 187 opts
187 }; 188 };
189
190 // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env
188 crates.insert( 191 crates.insert(
189 crate_id, 192 crate_id,
190 crate_graph.add_crate_root( 193 crate_graph.add_crate_root(
@@ -194,6 +197,7 @@ impl ProjectWorkspace {
194 None, 197 None,
195 cfg_options, 198 cfg_options,
196 Env::default(), 199 Env::default(),
200 Default::default(),
197 ), 201 ),
198 ); 202 );
199 } 203 }
@@ -231,12 +235,20 @@ impl ProjectWorkspace {
231 opts 235 opts
232 }; 236 };
233 237
238 let mut env = Env::default();
239 let mut extern_source = ExternSource::default();
240 if let Some((id, path)) = outdirs.get(krate.name(&sysroot)) {
241 env.set("OUT_DIR", path.clone());
242 extern_source.set_extern_path(&path, *id);
243 }
244
234 let crate_id = crate_graph.add_crate_root( 245 let crate_id = crate_graph.add_crate_root(
235 file_id, 246 file_id,
236 Edition::Edition2018, 247 Edition::Edition2018,
237 Some(krate.name(&sysroot).to_string()), 248 Some(krate.name(&sysroot).to_string()),
238 cfg_options, 249 cfg_options,
239 Env::default(), 250 env,
251 extern_source,
240 ); 252 );
241 sysroot_crates.insert(krate, crate_id); 253 sysroot_crates.insert(krate, crate_id);
242 } 254 }
@@ -275,12 +287,19 @@ impl ProjectWorkspace {
275 opts.insert_features(pkg.features(&cargo).iter().map(Into::into)); 287 opts.insert_features(pkg.features(&cargo).iter().map(Into::into));
276 opts 288 opts
277 }; 289 };
290 let mut env = Env::default();
291 let mut extern_source = ExternSource::default();
292 if let Some((id, path)) = outdirs.get(pkg.name(&cargo)) {
293 env.set("OUT_DIR", path.clone());
294 extern_source.set_extern_path(&path, *id);
295 }
278 let crate_id = crate_graph.add_crate_root( 296 let crate_id = crate_graph.add_crate_root(
279 file_id, 297 file_id,
280 edition, 298 edition,
281 Some(pkg.name(&cargo).to_string()), 299 Some(pkg.name(&cargo).to_string()),
282 cfg_options, 300 cfg_options,
283 Env::default(), 301 env,
302 extern_source,
284 ); 303 );
285 if tgt.kind(&cargo) == TargetKind::Lib { 304 if tgt.kind(&cargo) == TargetKind::Lib {
286 lib_tgt = Some(crate_id); 305 lib_tgt = Some(crate_id);
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 4a70c712f..26fafb469 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -30,7 +30,7 @@ pub use self::{
30/// conversion itself has zero runtime cost: ast and syntax nodes have exactly 30/// conversion itself has zero runtime cost: ast and syntax nodes have exactly
31/// the same representation: a pointer to the tree root and a pointer to the 31/// the same representation: a pointer to the tree root and a pointer to the
32/// node itself. 32/// node itself.
33pub trait AstNode { 33pub trait AstNode: std::fmt::Display {
34 fn can_cast(kind: SyntaxKind) -> bool 34 fn can_cast(kind: SyntaxKind) -> bool
35 where 35 where
36 Self: Sized; 36 Self: Sized;
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 150893e39..002f453cd 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -9,6 +9,11 @@ use crate::{
9pub struct SourceFile { 9pub struct SourceFile {
10 pub(crate) syntax: SyntaxNode, 10 pub(crate) syntax: SyntaxNode,
11} 11}
12impl std::fmt::Display for SourceFile {
13 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
14 std::fmt::Display::fmt(self.syntax(), f)
15 }
16}
12impl AstNode for SourceFile { 17impl AstNode for SourceFile {
13 fn can_cast(kind: SyntaxKind) -> bool { 18 fn can_cast(kind: SyntaxKind) -> bool {
14 match kind { 19 match kind {
@@ -38,6 +43,11 @@ impl SourceFile {
38pub struct FnDef { 43pub struct FnDef {
39 pub(crate) syntax: SyntaxNode, 44 pub(crate) syntax: SyntaxNode,
40} 45}
46impl std::fmt::Display for FnDef {
47 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
48 std::fmt::Display::fmt(self.syntax(), f)
49 }
50}
41impl AstNode for FnDef { 51impl AstNode for FnDef {
42 fn can_cast(kind: SyntaxKind) -> bool { 52 fn can_cast(kind: SyntaxKind) -> bool {
43 match kind { 53 match kind {
@@ -76,6 +86,11 @@ impl FnDef {
76pub struct RetType { 86pub struct RetType {
77 pub(crate) syntax: SyntaxNode, 87 pub(crate) syntax: SyntaxNode,
78} 88}
89impl std::fmt::Display for RetType {
90 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
91 std::fmt::Display::fmt(self.syntax(), f)
92 }
93}
79impl AstNode for RetType { 94impl AstNode for RetType {
80 fn can_cast(kind: SyntaxKind) -> bool { 95 fn can_cast(kind: SyntaxKind) -> bool {
81 match kind { 96 match kind {
@@ -103,6 +118,11 @@ impl RetType {
103pub struct StructDef { 118pub struct StructDef {
104 pub(crate) syntax: SyntaxNode, 119 pub(crate) syntax: SyntaxNode,
105} 120}
121impl std::fmt::Display for StructDef {
122 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
123 std::fmt::Display::fmt(self.syntax(), f)
124 }
125}
106impl AstNode for StructDef { 126impl AstNode for StructDef {
107 fn can_cast(kind: SyntaxKind) -> bool { 127 fn can_cast(kind: SyntaxKind) -> bool {
108 match kind { 128 match kind {
@@ -131,6 +151,11 @@ impl StructDef {}
131pub struct UnionDef { 151pub struct UnionDef {
132 pub(crate) syntax: SyntaxNode, 152 pub(crate) syntax: SyntaxNode,
133} 153}
154impl std::fmt::Display for UnionDef {
155 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
156 std::fmt::Display::fmt(self.syntax(), f)
157 }
158}
134impl AstNode for UnionDef { 159impl AstNode for UnionDef {
135 fn can_cast(kind: SyntaxKind) -> bool { 160 fn can_cast(kind: SyntaxKind) -> bool {
136 match kind { 161 match kind {
@@ -163,6 +188,11 @@ impl UnionDef {
163pub struct RecordFieldDefList { 188pub struct RecordFieldDefList {
164 pub(crate) syntax: SyntaxNode, 189 pub(crate) syntax: SyntaxNode,
165} 190}
191impl std::fmt::Display for RecordFieldDefList {
192 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
193 std::fmt::Display::fmt(self.syntax(), f)
194 }
195}
166impl AstNode for RecordFieldDefList { 196impl AstNode for RecordFieldDefList {
167 fn can_cast(kind: SyntaxKind) -> bool { 197 fn can_cast(kind: SyntaxKind) -> bool {
168 match kind { 198 match kind {
@@ -190,6 +220,11 @@ impl RecordFieldDefList {
190pub struct RecordFieldDef { 220pub struct RecordFieldDef {
191 pub(crate) syntax: SyntaxNode, 221 pub(crate) syntax: SyntaxNode,
192} 222}
223impl std::fmt::Display for RecordFieldDef {
224 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
225 std::fmt::Display::fmt(self.syntax(), f)
226 }
227}
193impl AstNode for RecordFieldDef { 228impl AstNode for RecordFieldDef {
194 fn can_cast(kind: SyntaxKind) -> bool { 229 fn can_cast(kind: SyntaxKind) -> bool {
195 match kind { 230 match kind {
@@ -218,6 +253,11 @@ impl RecordFieldDef {}
218pub struct TupleFieldDefList { 253pub struct TupleFieldDefList {
219 pub(crate) syntax: SyntaxNode, 254 pub(crate) syntax: SyntaxNode,
220} 255}
256impl std::fmt::Display for TupleFieldDefList {
257 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
258 std::fmt::Display::fmt(self.syntax(), f)
259 }
260}
221impl AstNode for TupleFieldDefList { 261impl AstNode for TupleFieldDefList {
222 fn can_cast(kind: SyntaxKind) -> bool { 262 fn can_cast(kind: SyntaxKind) -> bool {
223 match kind { 263 match kind {
@@ -245,6 +285,11 @@ impl TupleFieldDefList {
245pub struct TupleFieldDef { 285pub struct TupleFieldDef {
246 pub(crate) syntax: SyntaxNode, 286 pub(crate) syntax: SyntaxNode,
247} 287}
288impl std::fmt::Display for TupleFieldDef {
289 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
290 std::fmt::Display::fmt(self.syntax(), f)
291 }
292}
248impl AstNode for TupleFieldDef { 293impl AstNode for TupleFieldDef {
249 fn can_cast(kind: SyntaxKind) -> bool { 294 fn can_cast(kind: SyntaxKind) -> bool {
250 match kind { 295 match kind {
@@ -274,6 +319,11 @@ impl TupleFieldDef {
274pub struct EnumDef { 319pub struct EnumDef {
275 pub(crate) syntax: SyntaxNode, 320 pub(crate) syntax: SyntaxNode,
276} 321}
322impl std::fmt::Display for EnumDef {
323 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
324 std::fmt::Display::fmt(self.syntax(), f)
325 }
326}
277impl AstNode for EnumDef { 327impl AstNode for EnumDef {
278 fn can_cast(kind: SyntaxKind) -> bool { 328 fn can_cast(kind: SyntaxKind) -> bool {
279 match kind { 329 match kind {
@@ -306,6 +356,11 @@ impl EnumDef {
306pub struct EnumVariantList { 356pub struct EnumVariantList {
307 pub(crate) syntax: SyntaxNode, 357 pub(crate) syntax: SyntaxNode,
308} 358}
359impl std::fmt::Display for EnumVariantList {
360 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
361 std::fmt::Display::fmt(self.syntax(), f)
362 }
363}
309impl AstNode for EnumVariantList { 364impl AstNode for EnumVariantList {
310 fn can_cast(kind: SyntaxKind) -> bool { 365 fn can_cast(kind: SyntaxKind) -> bool {
311 match kind { 366 match kind {
@@ -333,6 +388,11 @@ impl EnumVariantList {
333pub struct EnumVariant { 388pub struct EnumVariant {
334 pub(crate) syntax: SyntaxNode, 389 pub(crate) syntax: SyntaxNode,
335} 390}
391impl std::fmt::Display for EnumVariant {
392 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
393 std::fmt::Display::fmt(self.syntax(), f)
394 }
395}
336impl AstNode for EnumVariant { 396impl AstNode for EnumVariant {
337 fn can_cast(kind: SyntaxKind) -> bool { 397 fn can_cast(kind: SyntaxKind) -> bool {
338 match kind { 398 match kind {
@@ -363,6 +423,11 @@ impl EnumVariant {
363pub struct TraitDef { 423pub struct TraitDef {
364 pub(crate) syntax: SyntaxNode, 424 pub(crate) syntax: SyntaxNode,
365} 425}
426impl std::fmt::Display for TraitDef {
427 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
428 std::fmt::Display::fmt(self.syntax(), f)
429 }
430}
366impl AstNode for TraitDef { 431impl AstNode for TraitDef {
367 fn can_cast(kind: SyntaxKind) -> bool { 432 fn can_cast(kind: SyntaxKind) -> bool {
368 match kind { 433 match kind {
@@ -396,6 +461,11 @@ impl TraitDef {
396pub struct Module { 461pub struct Module {
397 pub(crate) syntax: SyntaxNode, 462 pub(crate) syntax: SyntaxNode,
398} 463}
464impl std::fmt::Display for Module {
465 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
466 std::fmt::Display::fmt(self.syntax(), f)
467 }
468}
399impl AstNode for Module { 469impl AstNode for Module {
400 fn can_cast(kind: SyntaxKind) -> bool { 470 fn can_cast(kind: SyntaxKind) -> bool {
401 match kind { 471 match kind {
@@ -427,6 +497,11 @@ impl Module {
427pub struct ItemList { 497pub struct ItemList {
428 pub(crate) syntax: SyntaxNode, 498 pub(crate) syntax: SyntaxNode,
429} 499}
500impl std::fmt::Display for ItemList {
501 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
502 std::fmt::Display::fmt(self.syntax(), f)
503 }
504}
430impl AstNode for ItemList { 505impl AstNode for ItemList {
431 fn can_cast(kind: SyntaxKind) -> bool { 506 fn can_cast(kind: SyntaxKind) -> bool {
432 match kind { 507 match kind {
@@ -456,6 +531,11 @@ impl ItemList {
456pub struct ConstDef { 531pub struct ConstDef {
457 pub(crate) syntax: SyntaxNode, 532 pub(crate) syntax: SyntaxNode,
458} 533}
534impl std::fmt::Display for ConstDef {
535 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
536 std::fmt::Display::fmt(self.syntax(), f)
537 }
538}
459impl AstNode for ConstDef { 539impl AstNode for ConstDef {
460 fn can_cast(kind: SyntaxKind) -> bool { 540 fn can_cast(kind: SyntaxKind) -> bool {
461 match kind { 541 match kind {
@@ -489,6 +569,11 @@ impl ConstDef {
489pub struct StaticDef { 569pub struct StaticDef {
490 pub(crate) syntax: SyntaxNode, 570 pub(crate) syntax: SyntaxNode,
491} 571}
572impl std::fmt::Display for StaticDef {
573 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
574 std::fmt::Display::fmt(self.syntax(), f)
575 }
576}
492impl AstNode for StaticDef { 577impl AstNode for StaticDef {
493 fn can_cast(kind: SyntaxKind) -> bool { 578 fn can_cast(kind: SyntaxKind) -> bool {
494 match kind { 579 match kind {
@@ -522,6 +607,11 @@ impl StaticDef {
522pub struct TypeAliasDef { 607pub struct TypeAliasDef {
523 pub(crate) syntax: SyntaxNode, 608 pub(crate) syntax: SyntaxNode,
524} 609}
610impl std::fmt::Display for TypeAliasDef {
611 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
612 std::fmt::Display::fmt(self.syntax(), f)
613 }
614}
525impl AstNode for TypeAliasDef { 615impl AstNode for TypeAliasDef {
526 fn can_cast(kind: SyntaxKind) -> bool { 616 fn can_cast(kind: SyntaxKind) -> bool {
527 match kind { 617 match kind {
@@ -555,6 +645,11 @@ impl TypeAliasDef {
555pub struct ImplDef { 645pub struct ImplDef {
556 pub(crate) syntax: SyntaxNode, 646 pub(crate) syntax: SyntaxNode,
557} 647}
648impl std::fmt::Display for ImplDef {
649 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
650 std::fmt::Display::fmt(self.syntax(), f)
651 }
652}
558impl AstNode for ImplDef { 653impl AstNode for ImplDef {
559 fn can_cast(kind: SyntaxKind) -> bool { 654 fn can_cast(kind: SyntaxKind) -> bool {
560 match kind { 655 match kind {
@@ -584,6 +679,11 @@ impl ImplDef {
584pub struct ParenType { 679pub struct ParenType {
585 pub(crate) syntax: SyntaxNode, 680 pub(crate) syntax: SyntaxNode,
586} 681}
682impl std::fmt::Display for ParenType {
683 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
684 std::fmt::Display::fmt(self.syntax(), f)
685 }
686}
587impl AstNode for ParenType { 687impl AstNode for ParenType {
588 fn can_cast(kind: SyntaxKind) -> bool { 688 fn can_cast(kind: SyntaxKind) -> bool {
589 match kind { 689 match kind {
@@ -611,6 +711,11 @@ impl ParenType {
611pub struct TupleType { 711pub struct TupleType {
612 pub(crate) syntax: SyntaxNode, 712 pub(crate) syntax: SyntaxNode,
613} 713}
714impl std::fmt::Display for TupleType {
715 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
716 std::fmt::Display::fmt(self.syntax(), f)
717 }
718}
614impl AstNode for TupleType { 719impl AstNode for TupleType {
615 fn can_cast(kind: SyntaxKind) -> bool { 720 fn can_cast(kind: SyntaxKind) -> bool {
616 match kind { 721 match kind {
@@ -638,6 +743,11 @@ impl TupleType {
638pub struct NeverType { 743pub struct NeverType {
639 pub(crate) syntax: SyntaxNode, 744 pub(crate) syntax: SyntaxNode,
640} 745}
746impl std::fmt::Display for NeverType {
747 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
748 std::fmt::Display::fmt(self.syntax(), f)
749 }
750}
641impl AstNode for NeverType { 751impl AstNode for NeverType {
642 fn can_cast(kind: SyntaxKind) -> bool { 752 fn can_cast(kind: SyntaxKind) -> bool {
643 match kind { 753 match kind {
@@ -661,6 +771,11 @@ impl NeverType {}
661pub struct PathType { 771pub struct PathType {
662 pub(crate) syntax: SyntaxNode, 772 pub(crate) syntax: SyntaxNode,
663} 773}
774impl std::fmt::Display for PathType {
775 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
776 std::fmt::Display::fmt(self.syntax(), f)
777 }
778}
664impl AstNode for PathType { 779impl AstNode for PathType {
665 fn can_cast(kind: SyntaxKind) -> bool { 780 fn can_cast(kind: SyntaxKind) -> bool {
666 match kind { 781 match kind {
@@ -688,6 +803,11 @@ impl PathType {
688pub struct PointerType { 803pub struct PointerType {
689 pub(crate) syntax: SyntaxNode, 804 pub(crate) syntax: SyntaxNode,
690} 805}
806impl std::fmt::Display for PointerType {
807 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
808 std::fmt::Display::fmt(self.syntax(), f)
809 }
810}
691impl AstNode for PointerType { 811impl AstNode for PointerType {
692 fn can_cast(kind: SyntaxKind) -> bool { 812 fn can_cast(kind: SyntaxKind) -> bool {
693 match kind { 813 match kind {
@@ -715,6 +835,11 @@ impl PointerType {
715pub struct ArrayType { 835pub struct ArrayType {
716 pub(crate) syntax: SyntaxNode, 836 pub(crate) syntax: SyntaxNode,
717} 837}
838impl std::fmt::Display for ArrayType {
839 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
840 std::fmt::Display::fmt(self.syntax(), f)
841 }
842}
718impl AstNode for ArrayType { 843impl AstNode for ArrayType {
719 fn can_cast(kind: SyntaxKind) -> bool { 844 fn can_cast(kind: SyntaxKind) -> bool {
720 match kind { 845 match kind {
@@ -745,6 +870,11 @@ impl ArrayType {
745pub struct SliceType { 870pub struct SliceType {
746 pub(crate) syntax: SyntaxNode, 871 pub(crate) syntax: SyntaxNode,
747} 872}
873impl std::fmt::Display for SliceType {
874 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
875 std::fmt::Display::fmt(self.syntax(), f)
876 }
877}
748impl AstNode for SliceType { 878impl AstNode for SliceType {
749 fn can_cast(kind: SyntaxKind) -> bool { 879 fn can_cast(kind: SyntaxKind) -> bool {
750 match kind { 880 match kind {
@@ -772,6 +902,11 @@ impl SliceType {
772pub struct ReferenceType { 902pub struct ReferenceType {
773 pub(crate) syntax: SyntaxNode, 903 pub(crate) syntax: SyntaxNode,
774} 904}
905impl std::fmt::Display for ReferenceType {
906 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
907 std::fmt::Display::fmt(self.syntax(), f)
908 }
909}
775impl AstNode for ReferenceType { 910impl AstNode for ReferenceType {
776 fn can_cast(kind: SyntaxKind) -> bool { 911 fn can_cast(kind: SyntaxKind) -> bool {
777 match kind { 912 match kind {
@@ -799,6 +934,11 @@ impl ReferenceType {
799pub struct PlaceholderType { 934pub struct PlaceholderType {
800 pub(crate) syntax: SyntaxNode, 935 pub(crate) syntax: SyntaxNode,
801} 936}
937impl std::fmt::Display for PlaceholderType {
938 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
939 std::fmt::Display::fmt(self.syntax(), f)
940 }
941}
802impl AstNode for PlaceholderType { 942impl AstNode for PlaceholderType {
803 fn can_cast(kind: SyntaxKind) -> bool { 943 fn can_cast(kind: SyntaxKind) -> bool {
804 match kind { 944 match kind {
@@ -822,6 +962,11 @@ impl PlaceholderType {}
822pub struct FnPointerType { 962pub struct FnPointerType {
823 pub(crate) syntax: SyntaxNode, 963 pub(crate) syntax: SyntaxNode,
824} 964}
965impl std::fmt::Display for FnPointerType {
966 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
967 std::fmt::Display::fmt(self.syntax(), f)
968 }
969}
825impl AstNode for FnPointerType { 970impl AstNode for FnPointerType {
826 fn can_cast(kind: SyntaxKind) -> bool { 971 fn can_cast(kind: SyntaxKind) -> bool {
827 match kind { 972 match kind {
@@ -852,6 +997,11 @@ impl FnPointerType {
852pub struct ForType { 997pub struct ForType {
853 pub(crate) syntax: SyntaxNode, 998 pub(crate) syntax: SyntaxNode,
854} 999}
1000impl std::fmt::Display for ForType {
1001 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1002 std::fmt::Display::fmt(self.syntax(), f)
1003 }
1004}
855impl AstNode for ForType { 1005impl AstNode for ForType {
856 fn can_cast(kind: SyntaxKind) -> bool { 1006 fn can_cast(kind: SyntaxKind) -> bool {
857 match kind { 1007 match kind {
@@ -879,6 +1029,11 @@ impl ForType {
879pub struct ImplTraitType { 1029pub struct ImplTraitType {
880 pub(crate) syntax: SyntaxNode, 1030 pub(crate) syntax: SyntaxNode,
881} 1031}
1032impl std::fmt::Display for ImplTraitType {
1033 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1034 std::fmt::Display::fmt(self.syntax(), f)
1035 }
1036}
882impl AstNode for ImplTraitType { 1037impl AstNode for ImplTraitType {
883 fn can_cast(kind: SyntaxKind) -> bool { 1038 fn can_cast(kind: SyntaxKind) -> bool {
884 match kind { 1039 match kind {
@@ -903,6 +1058,11 @@ impl ImplTraitType {}
903pub struct DynTraitType { 1058pub struct DynTraitType {
904 pub(crate) syntax: SyntaxNode, 1059 pub(crate) syntax: SyntaxNode,
905} 1060}
1061impl std::fmt::Display for DynTraitType {
1062 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1063 std::fmt::Display::fmt(self.syntax(), f)
1064 }
1065}
906impl AstNode for DynTraitType { 1066impl AstNode for DynTraitType {
907 fn can_cast(kind: SyntaxKind) -> bool { 1067 fn can_cast(kind: SyntaxKind) -> bool {
908 match kind { 1068 match kind {
@@ -927,6 +1087,11 @@ impl DynTraitType {}
927pub struct TupleExpr { 1087pub struct TupleExpr {
928 pub(crate) syntax: SyntaxNode, 1088 pub(crate) syntax: SyntaxNode,
929} 1089}
1090impl std::fmt::Display for TupleExpr {
1091 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1092 std::fmt::Display::fmt(self.syntax(), f)
1093 }
1094}
930impl AstNode for TupleExpr { 1095impl AstNode for TupleExpr {
931 fn can_cast(kind: SyntaxKind) -> bool { 1096 fn can_cast(kind: SyntaxKind) -> bool {
932 match kind { 1097 match kind {
@@ -954,6 +1119,11 @@ impl TupleExpr {
954pub struct ArrayExpr { 1119pub struct ArrayExpr {
955 pub(crate) syntax: SyntaxNode, 1120 pub(crate) syntax: SyntaxNode,
956} 1121}
1122impl std::fmt::Display for ArrayExpr {
1123 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1124 std::fmt::Display::fmt(self.syntax(), f)
1125 }
1126}
957impl AstNode for ArrayExpr { 1127impl AstNode for ArrayExpr {
958 fn can_cast(kind: SyntaxKind) -> bool { 1128 fn can_cast(kind: SyntaxKind) -> bool {
959 match kind { 1129 match kind {
@@ -981,6 +1151,11 @@ impl ArrayExpr {
981pub struct ParenExpr { 1151pub struct ParenExpr {
982 pub(crate) syntax: SyntaxNode, 1152 pub(crate) syntax: SyntaxNode,
983} 1153}
1154impl std::fmt::Display for ParenExpr {
1155 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1156 std::fmt::Display::fmt(self.syntax(), f)
1157 }
1158}
984impl AstNode for ParenExpr { 1159impl AstNode for ParenExpr {
985 fn can_cast(kind: SyntaxKind) -> bool { 1160 fn can_cast(kind: SyntaxKind) -> bool {
986 match kind { 1161 match kind {
@@ -1008,6 +1183,11 @@ impl ParenExpr {
1008pub struct PathExpr { 1183pub struct PathExpr {
1009 pub(crate) syntax: SyntaxNode, 1184 pub(crate) syntax: SyntaxNode,
1010} 1185}
1186impl std::fmt::Display for PathExpr {
1187 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1188 std::fmt::Display::fmt(self.syntax(), f)
1189 }
1190}
1011impl AstNode for PathExpr { 1191impl AstNode for PathExpr {
1012 fn can_cast(kind: SyntaxKind) -> bool { 1192 fn can_cast(kind: SyntaxKind) -> bool {
1013 match kind { 1193 match kind {
@@ -1035,6 +1215,11 @@ impl PathExpr {
1035pub struct LambdaExpr { 1215pub struct LambdaExpr {
1036 pub(crate) syntax: SyntaxNode, 1216 pub(crate) syntax: SyntaxNode,
1037} 1217}
1218impl std::fmt::Display for LambdaExpr {
1219 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1220 std::fmt::Display::fmt(self.syntax(), f)
1221 }
1222}
1038impl AstNode for LambdaExpr { 1223impl AstNode for LambdaExpr {
1039 fn can_cast(kind: SyntaxKind) -> bool { 1224 fn can_cast(kind: SyntaxKind) -> bool {
1040 match kind { 1225 match kind {
@@ -1068,6 +1253,11 @@ impl LambdaExpr {
1068pub struct IfExpr { 1253pub struct IfExpr {
1069 pub(crate) syntax: SyntaxNode, 1254 pub(crate) syntax: SyntaxNode,
1070} 1255}
1256impl std::fmt::Display for IfExpr {
1257 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1258 std::fmt::Display::fmt(self.syntax(), f)
1259 }
1260}
1071impl AstNode for IfExpr { 1261impl AstNode for IfExpr {
1072 fn can_cast(kind: SyntaxKind) -> bool { 1262 fn can_cast(kind: SyntaxKind) -> bool {
1073 match kind { 1263 match kind {
@@ -1095,6 +1285,11 @@ impl IfExpr {
1095pub struct LoopExpr { 1285pub struct LoopExpr {
1096 pub(crate) syntax: SyntaxNode, 1286 pub(crate) syntax: SyntaxNode,
1097} 1287}
1288impl std::fmt::Display for LoopExpr {
1289 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1290 std::fmt::Display::fmt(self.syntax(), f)
1291 }
1292}
1098impl AstNode for LoopExpr { 1293impl AstNode for LoopExpr {
1099 fn can_cast(kind: SyntaxKind) -> bool { 1294 fn can_cast(kind: SyntaxKind) -> bool {
1100 match kind { 1295 match kind {
@@ -1119,6 +1314,11 @@ impl LoopExpr {}
1119pub struct TryBlockExpr { 1314pub struct TryBlockExpr {
1120 pub(crate) syntax: SyntaxNode, 1315 pub(crate) syntax: SyntaxNode,
1121} 1316}
1317impl std::fmt::Display for TryBlockExpr {
1318 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1319 std::fmt::Display::fmt(self.syntax(), f)
1320 }
1321}
1122impl AstNode for TryBlockExpr { 1322impl AstNode for TryBlockExpr {
1123 fn can_cast(kind: SyntaxKind) -> bool { 1323 fn can_cast(kind: SyntaxKind) -> bool {
1124 match kind { 1324 match kind {
@@ -1146,6 +1346,11 @@ impl TryBlockExpr {
1146pub struct ForExpr { 1346pub struct ForExpr {
1147 pub(crate) syntax: SyntaxNode, 1347 pub(crate) syntax: SyntaxNode,
1148} 1348}
1349impl std::fmt::Display for ForExpr {
1350 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1351 std::fmt::Display::fmt(self.syntax(), f)
1352 }
1353}
1149impl AstNode for ForExpr { 1354impl AstNode for ForExpr {
1150 fn can_cast(kind: SyntaxKind) -> bool { 1355 fn can_cast(kind: SyntaxKind) -> bool {
1151 match kind { 1356 match kind {
@@ -1177,6 +1382,11 @@ impl ForExpr {
1177pub struct WhileExpr { 1382pub struct WhileExpr {
1178 pub(crate) syntax: SyntaxNode, 1383 pub(crate) syntax: SyntaxNode,
1179} 1384}
1385impl std::fmt::Display for WhileExpr {
1386 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1387 std::fmt::Display::fmt(self.syntax(), f)
1388 }
1389}
1180impl AstNode for WhileExpr { 1390impl AstNode for WhileExpr {
1181 fn can_cast(kind: SyntaxKind) -> bool { 1391 fn can_cast(kind: SyntaxKind) -> bool {
1182 match kind { 1392 match kind {
@@ -1205,6 +1415,11 @@ impl WhileExpr {
1205pub struct ContinueExpr { 1415pub struct ContinueExpr {
1206 pub(crate) syntax: SyntaxNode, 1416 pub(crate) syntax: SyntaxNode,
1207} 1417}
1418impl std::fmt::Display for ContinueExpr {
1419 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1420 std::fmt::Display::fmt(self.syntax(), f)
1421 }
1422}
1208impl AstNode for ContinueExpr { 1423impl AstNode for ContinueExpr {
1209 fn can_cast(kind: SyntaxKind) -> bool { 1424 fn can_cast(kind: SyntaxKind) -> bool {
1210 match kind { 1425 match kind {
@@ -1228,6 +1443,11 @@ impl ContinueExpr {}
1228pub struct BreakExpr { 1443pub struct BreakExpr {
1229 pub(crate) syntax: SyntaxNode, 1444 pub(crate) syntax: SyntaxNode,
1230} 1445}
1446impl std::fmt::Display for BreakExpr {
1447 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1448 std::fmt::Display::fmt(self.syntax(), f)
1449 }
1450}
1231impl AstNode for BreakExpr { 1451impl AstNode for BreakExpr {
1232 fn can_cast(kind: SyntaxKind) -> bool { 1452 fn can_cast(kind: SyntaxKind) -> bool {
1233 match kind { 1453 match kind {
@@ -1255,6 +1475,11 @@ impl BreakExpr {
1255pub struct Label { 1475pub struct Label {
1256 pub(crate) syntax: SyntaxNode, 1476 pub(crate) syntax: SyntaxNode,
1257} 1477}
1478impl std::fmt::Display for Label {
1479 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1480 std::fmt::Display::fmt(self.syntax(), f)
1481 }
1482}
1258impl AstNode for Label { 1483impl AstNode for Label {
1259 fn can_cast(kind: SyntaxKind) -> bool { 1484 fn can_cast(kind: SyntaxKind) -> bool {
1260 match kind { 1485 match kind {
@@ -1278,6 +1503,11 @@ impl Label {}
1278pub struct BlockExpr { 1503pub struct BlockExpr {
1279 pub(crate) syntax: SyntaxNode, 1504 pub(crate) syntax: SyntaxNode,
1280} 1505}
1506impl std::fmt::Display for BlockExpr {
1507 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1508 std::fmt::Display::fmt(self.syntax(), f)
1509 }
1510}
1281impl AstNode for BlockExpr { 1511impl AstNode for BlockExpr {
1282 fn can_cast(kind: SyntaxKind) -> bool { 1512 fn can_cast(kind: SyntaxKind) -> bool {
1283 match kind { 1513 match kind {
@@ -1305,6 +1535,11 @@ impl BlockExpr {
1305pub struct ReturnExpr { 1535pub struct ReturnExpr {
1306 pub(crate) syntax: SyntaxNode, 1536 pub(crate) syntax: SyntaxNode,
1307} 1537}
1538impl std::fmt::Display for ReturnExpr {
1539 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1540 std::fmt::Display::fmt(self.syntax(), f)
1541 }
1542}
1308impl AstNode for ReturnExpr { 1543impl AstNode for ReturnExpr {
1309 fn can_cast(kind: SyntaxKind) -> bool { 1544 fn can_cast(kind: SyntaxKind) -> bool {
1310 match kind { 1545 match kind {
@@ -1332,6 +1567,11 @@ impl ReturnExpr {
1332pub struct CallExpr { 1567pub struct CallExpr {
1333 pub(crate) syntax: SyntaxNode, 1568 pub(crate) syntax: SyntaxNode,
1334} 1569}
1570impl std::fmt::Display for CallExpr {
1571 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1572 std::fmt::Display::fmt(self.syntax(), f)
1573 }
1574}
1335impl AstNode for CallExpr { 1575impl AstNode for CallExpr {
1336 fn can_cast(kind: SyntaxKind) -> bool { 1576 fn can_cast(kind: SyntaxKind) -> bool {
1337 match kind { 1577 match kind {
@@ -1360,6 +1600,11 @@ impl CallExpr {
1360pub struct MethodCallExpr { 1600pub struct MethodCallExpr {
1361 pub(crate) syntax: SyntaxNode, 1601 pub(crate) syntax: SyntaxNode,
1362} 1602}
1603impl std::fmt::Display for MethodCallExpr {
1604 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1605 std::fmt::Display::fmt(self.syntax(), f)
1606 }
1607}
1363impl AstNode for MethodCallExpr { 1608impl AstNode for MethodCallExpr {
1364 fn can_cast(kind: SyntaxKind) -> bool { 1609 fn can_cast(kind: SyntaxKind) -> bool {
1365 match kind { 1610 match kind {
@@ -1394,6 +1639,11 @@ impl MethodCallExpr {
1394pub struct IndexExpr { 1639pub struct IndexExpr {
1395 pub(crate) syntax: SyntaxNode, 1640 pub(crate) syntax: SyntaxNode,
1396} 1641}
1642impl std::fmt::Display for IndexExpr {
1643 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1644 std::fmt::Display::fmt(self.syntax(), f)
1645 }
1646}
1397impl AstNode for IndexExpr { 1647impl AstNode for IndexExpr {
1398 fn can_cast(kind: SyntaxKind) -> bool { 1648 fn can_cast(kind: SyntaxKind) -> bool {
1399 match kind { 1649 match kind {
@@ -1417,6 +1667,11 @@ impl IndexExpr {}
1417pub struct FieldExpr { 1667pub struct FieldExpr {
1418 pub(crate) syntax: SyntaxNode, 1668 pub(crate) syntax: SyntaxNode,
1419} 1669}
1670impl std::fmt::Display for FieldExpr {
1671 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1672 std::fmt::Display::fmt(self.syntax(), f)
1673 }
1674}
1420impl AstNode for FieldExpr { 1675impl AstNode for FieldExpr {
1421 fn can_cast(kind: SyntaxKind) -> bool { 1676 fn can_cast(kind: SyntaxKind) -> bool {
1422 match kind { 1677 match kind {
@@ -1447,6 +1702,11 @@ impl FieldExpr {
1447pub struct AwaitExpr { 1702pub struct AwaitExpr {
1448 pub(crate) syntax: SyntaxNode, 1703 pub(crate) syntax: SyntaxNode,
1449} 1704}
1705impl std::fmt::Display for AwaitExpr {
1706 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1707 std::fmt::Display::fmt(self.syntax(), f)
1708 }
1709}
1450impl AstNode for AwaitExpr { 1710impl AstNode for AwaitExpr {
1451 fn can_cast(kind: SyntaxKind) -> bool { 1711 fn can_cast(kind: SyntaxKind) -> bool {
1452 match kind { 1712 match kind {
@@ -1474,6 +1734,11 @@ impl AwaitExpr {
1474pub struct TryExpr { 1734pub struct TryExpr {
1475 pub(crate) syntax: SyntaxNode, 1735 pub(crate) syntax: SyntaxNode,
1476} 1736}
1737impl std::fmt::Display for TryExpr {
1738 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1739 std::fmt::Display::fmt(self.syntax(), f)
1740 }
1741}
1477impl AstNode for TryExpr { 1742impl AstNode for TryExpr {
1478 fn can_cast(kind: SyntaxKind) -> bool { 1743 fn can_cast(kind: SyntaxKind) -> bool {
1479 match kind { 1744 match kind {
@@ -1501,6 +1766,11 @@ impl TryExpr {
1501pub struct CastExpr { 1766pub struct CastExpr {
1502 pub(crate) syntax: SyntaxNode, 1767 pub(crate) syntax: SyntaxNode,
1503} 1768}
1769impl std::fmt::Display for CastExpr {
1770 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1771 std::fmt::Display::fmt(self.syntax(), f)
1772 }
1773}
1504impl AstNode for CastExpr { 1774impl AstNode for CastExpr {
1505 fn can_cast(kind: SyntaxKind) -> bool { 1775 fn can_cast(kind: SyntaxKind) -> bool {
1506 match kind { 1776 match kind {
@@ -1531,6 +1801,11 @@ impl CastExpr {
1531pub struct RefExpr { 1801pub struct RefExpr {
1532 pub(crate) syntax: SyntaxNode, 1802 pub(crate) syntax: SyntaxNode,
1533} 1803}
1804impl std::fmt::Display for RefExpr {
1805 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1806 std::fmt::Display::fmt(self.syntax(), f)
1807 }
1808}
1534impl AstNode for RefExpr { 1809impl AstNode for RefExpr {
1535 fn can_cast(kind: SyntaxKind) -> bool { 1810 fn can_cast(kind: SyntaxKind) -> bool {
1536 match kind { 1811 match kind {
@@ -1558,6 +1833,11 @@ impl RefExpr {
1558pub struct PrefixExpr { 1833pub struct PrefixExpr {
1559 pub(crate) syntax: SyntaxNode, 1834 pub(crate) syntax: SyntaxNode,
1560} 1835}
1836impl std::fmt::Display for PrefixExpr {
1837 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1838 std::fmt::Display::fmt(self.syntax(), f)
1839 }
1840}
1561impl AstNode for PrefixExpr { 1841impl AstNode for PrefixExpr {
1562 fn can_cast(kind: SyntaxKind) -> bool { 1842 fn can_cast(kind: SyntaxKind) -> bool {
1563 match kind { 1843 match kind {
@@ -1585,6 +1865,11 @@ impl PrefixExpr {
1585pub struct BoxExpr { 1865pub struct BoxExpr {
1586 pub(crate) syntax: SyntaxNode, 1866 pub(crate) syntax: SyntaxNode,
1587} 1867}
1868impl std::fmt::Display for BoxExpr {
1869 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1870 std::fmt::Display::fmt(self.syntax(), f)
1871 }
1872}
1588impl AstNode for BoxExpr { 1873impl AstNode for BoxExpr {
1589 fn can_cast(kind: SyntaxKind) -> bool { 1874 fn can_cast(kind: SyntaxKind) -> bool {
1590 match kind { 1875 match kind {
@@ -1612,6 +1897,11 @@ impl BoxExpr {
1612pub struct RangeExpr { 1897pub struct RangeExpr {
1613 pub(crate) syntax: SyntaxNode, 1898 pub(crate) syntax: SyntaxNode,
1614} 1899}
1900impl std::fmt::Display for RangeExpr {
1901 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1902 std::fmt::Display::fmt(self.syntax(), f)
1903 }
1904}
1615impl AstNode for RangeExpr { 1905impl AstNode for RangeExpr {
1616 fn can_cast(kind: SyntaxKind) -> bool { 1906 fn can_cast(kind: SyntaxKind) -> bool {
1617 match kind { 1907 match kind {
@@ -1635,6 +1925,11 @@ impl RangeExpr {}
1635pub struct BinExpr { 1925pub struct BinExpr {
1636 pub(crate) syntax: SyntaxNode, 1926 pub(crate) syntax: SyntaxNode,
1637} 1927}
1928impl std::fmt::Display for BinExpr {
1929 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1930 std::fmt::Display::fmt(self.syntax(), f)
1931 }
1932}
1638impl AstNode for BinExpr { 1933impl AstNode for BinExpr {
1639 fn can_cast(kind: SyntaxKind) -> bool { 1934 fn can_cast(kind: SyntaxKind) -> bool {
1640 match kind { 1935 match kind {
@@ -1658,6 +1953,11 @@ impl BinExpr {}
1658pub struct Literal { 1953pub struct Literal {
1659 pub(crate) syntax: SyntaxNode, 1954 pub(crate) syntax: SyntaxNode,
1660} 1955}
1956impl std::fmt::Display for Literal {
1957 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1958 std::fmt::Display::fmt(self.syntax(), f)
1959 }
1960}
1661impl AstNode for Literal { 1961impl AstNode for Literal {
1662 fn can_cast(kind: SyntaxKind) -> bool { 1962 fn can_cast(kind: SyntaxKind) -> bool {
1663 match kind { 1963 match kind {
@@ -1681,6 +1981,11 @@ impl Literal {}
1681pub struct MatchExpr { 1981pub struct MatchExpr {
1682 pub(crate) syntax: SyntaxNode, 1982 pub(crate) syntax: SyntaxNode,
1683} 1983}
1984impl std::fmt::Display for MatchExpr {
1985 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1986 std::fmt::Display::fmt(self.syntax(), f)
1987 }
1988}
1684impl AstNode for MatchExpr { 1989impl AstNode for MatchExpr {
1685 fn can_cast(kind: SyntaxKind) -> bool { 1990 fn can_cast(kind: SyntaxKind) -> bool {
1686 match kind { 1991 match kind {
@@ -1711,6 +2016,11 @@ impl MatchExpr {
1711pub struct MatchArmList { 2016pub struct MatchArmList {
1712 pub(crate) syntax: SyntaxNode, 2017 pub(crate) syntax: SyntaxNode,
1713} 2018}
2019impl std::fmt::Display for MatchArmList {
2020 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2021 std::fmt::Display::fmt(self.syntax(), f)
2022 }
2023}
1714impl AstNode for MatchArmList { 2024impl AstNode for MatchArmList {
1715 fn can_cast(kind: SyntaxKind) -> bool { 2025 fn can_cast(kind: SyntaxKind) -> bool {
1716 match kind { 2026 match kind {
@@ -1739,6 +2049,11 @@ impl MatchArmList {
1739pub struct MatchArm { 2049pub struct MatchArm {
1740 pub(crate) syntax: SyntaxNode, 2050 pub(crate) syntax: SyntaxNode,
1741} 2051}
2052impl std::fmt::Display for MatchArm {
2053 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2054 std::fmt::Display::fmt(self.syntax(), f)
2055 }
2056}
1742impl AstNode for MatchArm { 2057impl AstNode for MatchArm {
1743 fn can_cast(kind: SyntaxKind) -> bool { 2058 fn can_cast(kind: SyntaxKind) -> bool {
1744 match kind { 2059 match kind {
@@ -1773,6 +2088,11 @@ impl MatchArm {
1773pub struct MatchGuard { 2088pub struct MatchGuard {
1774 pub(crate) syntax: SyntaxNode, 2089 pub(crate) syntax: SyntaxNode,
1775} 2090}
2091impl std::fmt::Display for MatchGuard {
2092 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2093 std::fmt::Display::fmt(self.syntax(), f)
2094 }
2095}
1776impl AstNode for MatchGuard { 2096impl AstNode for MatchGuard {
1777 fn can_cast(kind: SyntaxKind) -> bool { 2097 fn can_cast(kind: SyntaxKind) -> bool {
1778 match kind { 2098 match kind {
@@ -1800,6 +2120,11 @@ impl MatchGuard {
1800pub struct RecordLit { 2120pub struct RecordLit {
1801 pub(crate) syntax: SyntaxNode, 2121 pub(crate) syntax: SyntaxNode,
1802} 2122}
2123impl std::fmt::Display for RecordLit {
2124 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2125 std::fmt::Display::fmt(self.syntax(), f)
2126 }
2127}
1803impl AstNode for RecordLit { 2128impl AstNode for RecordLit {
1804 fn can_cast(kind: SyntaxKind) -> bool { 2129 fn can_cast(kind: SyntaxKind) -> bool {
1805 match kind { 2130 match kind {
@@ -1830,6 +2155,11 @@ impl RecordLit {
1830pub struct RecordFieldList { 2155pub struct RecordFieldList {
1831 pub(crate) syntax: SyntaxNode, 2156 pub(crate) syntax: SyntaxNode,
1832} 2157}
2158impl std::fmt::Display for RecordFieldList {
2159 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2160 std::fmt::Display::fmt(self.syntax(), f)
2161 }
2162}
1833impl AstNode for RecordFieldList { 2163impl AstNode for RecordFieldList {
1834 fn can_cast(kind: SyntaxKind) -> bool { 2164 fn can_cast(kind: SyntaxKind) -> bool {
1835 match kind { 2165 match kind {
@@ -1860,6 +2190,11 @@ impl RecordFieldList {
1860pub struct RecordField { 2190pub struct RecordField {
1861 pub(crate) syntax: SyntaxNode, 2191 pub(crate) syntax: SyntaxNode,
1862} 2192}
2193impl std::fmt::Display for RecordField {
2194 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2195 std::fmt::Display::fmt(self.syntax(), f)
2196 }
2197}
1863impl AstNode for RecordField { 2198impl AstNode for RecordField {
1864 fn can_cast(kind: SyntaxKind) -> bool { 2199 fn can_cast(kind: SyntaxKind) -> bool {
1865 match kind { 2200 match kind {
@@ -1890,6 +2225,11 @@ impl RecordField {
1890pub struct OrPat { 2225pub struct OrPat {
1891 pub(crate) syntax: SyntaxNode, 2226 pub(crate) syntax: SyntaxNode,
1892} 2227}
2228impl std::fmt::Display for OrPat {
2229 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2230 std::fmt::Display::fmt(self.syntax(), f)
2231 }
2232}
1893impl AstNode for OrPat { 2233impl AstNode for OrPat {
1894 fn can_cast(kind: SyntaxKind) -> bool { 2234 fn can_cast(kind: SyntaxKind) -> bool {
1895 match kind { 2235 match kind {
@@ -1917,6 +2257,11 @@ impl OrPat {
1917pub struct ParenPat { 2257pub struct ParenPat {
1918 pub(crate) syntax: SyntaxNode, 2258 pub(crate) syntax: SyntaxNode,
1919} 2259}
2260impl std::fmt::Display for ParenPat {
2261 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2262 std::fmt::Display::fmt(self.syntax(), f)
2263 }
2264}
1920impl AstNode for ParenPat { 2265impl AstNode for ParenPat {
1921 fn can_cast(kind: SyntaxKind) -> bool { 2266 fn can_cast(kind: SyntaxKind) -> bool {
1922 match kind { 2267 match kind {
@@ -1944,6 +2289,11 @@ impl ParenPat {
1944pub struct RefPat { 2289pub struct RefPat {
1945 pub(crate) syntax: SyntaxNode, 2290 pub(crate) syntax: SyntaxNode,
1946} 2291}
2292impl std::fmt::Display for RefPat {
2293 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2294 std::fmt::Display::fmt(self.syntax(), f)
2295 }
2296}
1947impl AstNode for RefPat { 2297impl AstNode for RefPat {
1948 fn can_cast(kind: SyntaxKind) -> bool { 2298 fn can_cast(kind: SyntaxKind) -> bool {
1949 match kind { 2299 match kind {
@@ -1971,6 +2321,11 @@ impl RefPat {
1971pub struct BoxPat { 2321pub struct BoxPat {
1972 pub(crate) syntax: SyntaxNode, 2322 pub(crate) syntax: SyntaxNode,
1973} 2323}
2324impl std::fmt::Display for BoxPat {
2325 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2326 std::fmt::Display::fmt(self.syntax(), f)
2327 }
2328}
1974impl AstNode for BoxPat { 2329impl AstNode for BoxPat {
1975 fn can_cast(kind: SyntaxKind) -> bool { 2330 fn can_cast(kind: SyntaxKind) -> bool {
1976 match kind { 2331 match kind {
@@ -1998,6 +2353,11 @@ impl BoxPat {
1998pub struct BindPat { 2353pub struct BindPat {
1999 pub(crate) syntax: SyntaxNode, 2354 pub(crate) syntax: SyntaxNode,
2000} 2355}
2356impl std::fmt::Display for BindPat {
2357 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2358 std::fmt::Display::fmt(self.syntax(), f)
2359 }
2360}
2001impl AstNode for BindPat { 2361impl AstNode for BindPat {
2002 fn can_cast(kind: SyntaxKind) -> bool { 2362 fn can_cast(kind: SyntaxKind) -> bool {
2003 match kind { 2363 match kind {
@@ -2026,6 +2386,11 @@ impl BindPat {
2026pub struct PlaceholderPat { 2386pub struct PlaceholderPat {
2027 pub(crate) syntax: SyntaxNode, 2387 pub(crate) syntax: SyntaxNode,
2028} 2388}
2389impl std::fmt::Display for PlaceholderPat {
2390 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2391 std::fmt::Display::fmt(self.syntax(), f)
2392 }
2393}
2029impl AstNode for PlaceholderPat { 2394impl AstNode for PlaceholderPat {
2030 fn can_cast(kind: SyntaxKind) -> bool { 2395 fn can_cast(kind: SyntaxKind) -> bool {
2031 match kind { 2396 match kind {
@@ -2049,6 +2414,11 @@ impl PlaceholderPat {}
2049pub struct DotDotPat { 2414pub struct DotDotPat {
2050 pub(crate) syntax: SyntaxNode, 2415 pub(crate) syntax: SyntaxNode,
2051} 2416}
2417impl std::fmt::Display for DotDotPat {
2418 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2419 std::fmt::Display::fmt(self.syntax(), f)
2420 }
2421}
2052impl AstNode for DotDotPat { 2422impl AstNode for DotDotPat {
2053 fn can_cast(kind: SyntaxKind) -> bool { 2423 fn can_cast(kind: SyntaxKind) -> bool {
2054 match kind { 2424 match kind {
@@ -2072,6 +2442,11 @@ impl DotDotPat {}
2072pub struct PathPat { 2442pub struct PathPat {
2073 pub(crate) syntax: SyntaxNode, 2443 pub(crate) syntax: SyntaxNode,
2074} 2444}
2445impl std::fmt::Display for PathPat {
2446 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2447 std::fmt::Display::fmt(self.syntax(), f)
2448 }
2449}
2075impl AstNode for PathPat { 2450impl AstNode for PathPat {
2076 fn can_cast(kind: SyntaxKind) -> bool { 2451 fn can_cast(kind: SyntaxKind) -> bool {
2077 match kind { 2452 match kind {
@@ -2099,6 +2474,11 @@ impl PathPat {
2099pub struct SlicePat { 2474pub struct SlicePat {
2100 pub(crate) syntax: SyntaxNode, 2475 pub(crate) syntax: SyntaxNode,
2101} 2476}
2477impl std::fmt::Display for SlicePat {
2478 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2479 std::fmt::Display::fmt(self.syntax(), f)
2480 }
2481}
2102impl AstNode for SlicePat { 2482impl AstNode for SlicePat {
2103 fn can_cast(kind: SyntaxKind) -> bool { 2483 fn can_cast(kind: SyntaxKind) -> bool {
2104 match kind { 2484 match kind {
@@ -2126,6 +2506,11 @@ impl SlicePat {
2126pub struct RangePat { 2506pub struct RangePat {
2127 pub(crate) syntax: SyntaxNode, 2507 pub(crate) syntax: SyntaxNode,
2128} 2508}
2509impl std::fmt::Display for RangePat {
2510 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2511 std::fmt::Display::fmt(self.syntax(), f)
2512 }
2513}
2129impl AstNode for RangePat { 2514impl AstNode for RangePat {
2130 fn can_cast(kind: SyntaxKind) -> bool { 2515 fn can_cast(kind: SyntaxKind) -> bool {
2131 match kind { 2516 match kind {
@@ -2149,6 +2534,11 @@ impl RangePat {}
2149pub struct LiteralPat { 2534pub struct LiteralPat {
2150 pub(crate) syntax: SyntaxNode, 2535 pub(crate) syntax: SyntaxNode,
2151} 2536}
2537impl std::fmt::Display for LiteralPat {
2538 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2539 std::fmt::Display::fmt(self.syntax(), f)
2540 }
2541}
2152impl AstNode for LiteralPat { 2542impl AstNode for LiteralPat {
2153 fn can_cast(kind: SyntaxKind) -> bool { 2543 fn can_cast(kind: SyntaxKind) -> bool {
2154 match kind { 2544 match kind {
@@ -2176,6 +2566,11 @@ impl LiteralPat {
2176pub struct RecordPat { 2566pub struct RecordPat {
2177 pub(crate) syntax: SyntaxNode, 2567 pub(crate) syntax: SyntaxNode,
2178} 2568}
2569impl std::fmt::Display for RecordPat {
2570 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2571 std::fmt::Display::fmt(self.syntax(), f)
2572 }
2573}
2179impl AstNode for RecordPat { 2574impl AstNode for RecordPat {
2180 fn can_cast(kind: SyntaxKind) -> bool { 2575 fn can_cast(kind: SyntaxKind) -> bool {
2181 match kind { 2576 match kind {
@@ -2206,6 +2601,11 @@ impl RecordPat {
2206pub struct RecordFieldPatList { 2601pub struct RecordFieldPatList {
2207 pub(crate) syntax: SyntaxNode, 2602 pub(crate) syntax: SyntaxNode,
2208} 2603}
2604impl std::fmt::Display for RecordFieldPatList {
2605 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2606 std::fmt::Display::fmt(self.syntax(), f)
2607 }
2608}
2209impl AstNode for RecordFieldPatList { 2609impl AstNode for RecordFieldPatList {
2210 fn can_cast(kind: SyntaxKind) -> bool { 2610 fn can_cast(kind: SyntaxKind) -> bool {
2211 match kind { 2611 match kind {
@@ -2236,6 +2636,11 @@ impl RecordFieldPatList {
2236pub struct RecordFieldPat { 2636pub struct RecordFieldPat {
2237 pub(crate) syntax: SyntaxNode, 2637 pub(crate) syntax: SyntaxNode,
2238} 2638}
2639impl std::fmt::Display for RecordFieldPat {
2640 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2641 std::fmt::Display::fmt(self.syntax(), f)
2642 }
2643}
2239impl AstNode for RecordFieldPat { 2644impl AstNode for RecordFieldPat {
2240 fn can_cast(kind: SyntaxKind) -> bool { 2645 fn can_cast(kind: SyntaxKind) -> bool {
2241 match kind { 2646 match kind {
@@ -2264,6 +2669,11 @@ impl RecordFieldPat {
2264pub struct TupleStructPat { 2669pub struct TupleStructPat {
2265 pub(crate) syntax: SyntaxNode, 2670 pub(crate) syntax: SyntaxNode,
2266} 2671}
2672impl std::fmt::Display for TupleStructPat {
2673 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2674 std::fmt::Display::fmt(self.syntax(), f)
2675 }
2676}
2267impl AstNode for TupleStructPat { 2677impl AstNode for TupleStructPat {
2268 fn can_cast(kind: SyntaxKind) -> bool { 2678 fn can_cast(kind: SyntaxKind) -> bool {
2269 match kind { 2679 match kind {
@@ -2294,6 +2704,11 @@ impl TupleStructPat {
2294pub struct TuplePat { 2704pub struct TuplePat {
2295 pub(crate) syntax: SyntaxNode, 2705 pub(crate) syntax: SyntaxNode,
2296} 2706}
2707impl std::fmt::Display for TuplePat {
2708 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2709 std::fmt::Display::fmt(self.syntax(), f)
2710 }
2711}
2297impl AstNode for TuplePat { 2712impl AstNode for TuplePat {
2298 fn can_cast(kind: SyntaxKind) -> bool { 2713 fn can_cast(kind: SyntaxKind) -> bool {
2299 match kind { 2714 match kind {
@@ -2321,6 +2736,11 @@ impl TuplePat {
2321pub struct Visibility { 2736pub struct Visibility {
2322 pub(crate) syntax: SyntaxNode, 2737 pub(crate) syntax: SyntaxNode,
2323} 2738}
2739impl std::fmt::Display for Visibility {
2740 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2741 std::fmt::Display::fmt(self.syntax(), f)
2742 }
2743}
2324impl AstNode for Visibility { 2744impl AstNode for Visibility {
2325 fn can_cast(kind: SyntaxKind) -> bool { 2745 fn can_cast(kind: SyntaxKind) -> bool {
2326 match kind { 2746 match kind {
@@ -2344,6 +2764,11 @@ impl Visibility {}
2344pub struct Name { 2764pub struct Name {
2345 pub(crate) syntax: SyntaxNode, 2765 pub(crate) syntax: SyntaxNode,
2346} 2766}
2767impl std::fmt::Display for Name {
2768 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2769 std::fmt::Display::fmt(self.syntax(), f)
2770 }
2771}
2347impl AstNode for Name { 2772impl AstNode for Name {
2348 fn can_cast(kind: SyntaxKind) -> bool { 2773 fn can_cast(kind: SyntaxKind) -> bool {
2349 match kind { 2774 match kind {
@@ -2367,6 +2792,11 @@ impl Name {}
2367pub struct NameRef { 2792pub struct NameRef {
2368 pub(crate) syntax: SyntaxNode, 2793 pub(crate) syntax: SyntaxNode,
2369} 2794}
2795impl std::fmt::Display for NameRef {
2796 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2797 std::fmt::Display::fmt(self.syntax(), f)
2798 }
2799}
2370impl AstNode for NameRef { 2800impl AstNode for NameRef {
2371 fn can_cast(kind: SyntaxKind) -> bool { 2801 fn can_cast(kind: SyntaxKind) -> bool {
2372 match kind { 2802 match kind {
@@ -2390,6 +2820,11 @@ impl NameRef {}
2390pub struct MacroCall { 2820pub struct MacroCall {
2391 pub(crate) syntax: SyntaxNode, 2821 pub(crate) syntax: SyntaxNode,
2392} 2822}
2823impl std::fmt::Display for MacroCall {
2824 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2825 std::fmt::Display::fmt(self.syntax(), f)
2826 }
2827}
2393impl AstNode for MacroCall { 2828impl AstNode for MacroCall {
2394 fn can_cast(kind: SyntaxKind) -> bool { 2829 fn can_cast(kind: SyntaxKind) -> bool {
2395 match kind { 2830 match kind {
@@ -2423,6 +2858,11 @@ impl MacroCall {
2423pub struct Attr { 2858pub struct Attr {
2424 pub(crate) syntax: SyntaxNode, 2859 pub(crate) syntax: SyntaxNode,
2425} 2860}
2861impl std::fmt::Display for Attr {
2862 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2863 std::fmt::Display::fmt(self.syntax(), f)
2864 }
2865}
2426impl AstNode for Attr { 2866impl AstNode for Attr {
2427 fn can_cast(kind: SyntaxKind) -> bool { 2867 fn can_cast(kind: SyntaxKind) -> bool {
2428 match kind { 2868 match kind {
@@ -2453,6 +2893,11 @@ impl Attr {
2453pub struct TokenTree { 2893pub struct TokenTree {
2454 pub(crate) syntax: SyntaxNode, 2894 pub(crate) syntax: SyntaxNode,
2455} 2895}
2896impl std::fmt::Display for TokenTree {
2897 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2898 std::fmt::Display::fmt(self.syntax(), f)
2899 }
2900}
2456impl AstNode for TokenTree { 2901impl AstNode for TokenTree {
2457 fn can_cast(kind: SyntaxKind) -> bool { 2902 fn can_cast(kind: SyntaxKind) -> bool {
2458 match kind { 2903 match kind {
@@ -2476,6 +2921,11 @@ impl TokenTree {}
2476pub struct TypeParamList { 2921pub struct TypeParamList {
2477 pub(crate) syntax: SyntaxNode, 2922 pub(crate) syntax: SyntaxNode,
2478} 2923}
2924impl std::fmt::Display for TypeParamList {
2925 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2926 std::fmt::Display::fmt(self.syntax(), f)
2927 }
2928}
2479impl AstNode for TypeParamList { 2929impl AstNode for TypeParamList {
2480 fn can_cast(kind: SyntaxKind) -> bool { 2930 fn can_cast(kind: SyntaxKind) -> bool {
2481 match kind { 2931 match kind {
@@ -2506,6 +2956,11 @@ impl TypeParamList {
2506pub struct TypeParam { 2956pub struct TypeParam {
2507 pub(crate) syntax: SyntaxNode, 2957 pub(crate) syntax: SyntaxNode,
2508} 2958}
2959impl std::fmt::Display for TypeParam {
2960 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2961 std::fmt::Display::fmt(self.syntax(), f)
2962 }
2963}
2509impl AstNode for TypeParam { 2964impl AstNode for TypeParam {
2510 fn can_cast(kind: SyntaxKind) -> bool { 2965 fn can_cast(kind: SyntaxKind) -> bool {
2511 match kind { 2966 match kind {
@@ -2536,6 +2991,11 @@ impl TypeParam {
2536pub struct ConstParam { 2991pub struct ConstParam {
2537 pub(crate) syntax: SyntaxNode, 2992 pub(crate) syntax: SyntaxNode,
2538} 2993}
2994impl std::fmt::Display for ConstParam {
2995 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2996 std::fmt::Display::fmt(self.syntax(), f)
2997 }
2998}
2539impl AstNode for ConstParam { 2999impl AstNode for ConstParam {
2540 fn can_cast(kind: SyntaxKind) -> bool { 3000 fn can_cast(kind: SyntaxKind) -> bool {
2541 match kind { 3001 match kind {
@@ -2566,6 +3026,11 @@ impl ConstParam {
2566pub struct LifetimeParam { 3026pub struct LifetimeParam {
2567 pub(crate) syntax: SyntaxNode, 3027 pub(crate) syntax: SyntaxNode,
2568} 3028}
3029impl std::fmt::Display for LifetimeParam {
3030 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3031 std::fmt::Display::fmt(self.syntax(), f)
3032 }
3033}
2569impl AstNode for LifetimeParam { 3034impl AstNode for LifetimeParam {
2570 fn can_cast(kind: SyntaxKind) -> bool { 3035 fn can_cast(kind: SyntaxKind) -> bool {
2571 match kind { 3036 match kind {
@@ -2590,6 +3055,11 @@ impl LifetimeParam {}
2590pub struct TypeBound { 3055pub struct TypeBound {
2591 pub(crate) syntax: SyntaxNode, 3056 pub(crate) syntax: SyntaxNode,
2592} 3057}
3058impl std::fmt::Display for TypeBound {
3059 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3060 std::fmt::Display::fmt(self.syntax(), f)
3061 }
3062}
2593impl AstNode for TypeBound { 3063impl AstNode for TypeBound {
2594 fn can_cast(kind: SyntaxKind) -> bool { 3064 fn can_cast(kind: SyntaxKind) -> bool {
2595 match kind { 3065 match kind {
@@ -2617,6 +3087,11 @@ impl TypeBound {
2617pub struct TypeBoundList { 3087pub struct TypeBoundList {
2618 pub(crate) syntax: SyntaxNode, 3088 pub(crate) syntax: SyntaxNode,
2619} 3089}
3090impl std::fmt::Display for TypeBoundList {
3091 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3092 std::fmt::Display::fmt(self.syntax(), f)
3093 }
3094}
2620impl AstNode for TypeBoundList { 3095impl AstNode for TypeBoundList {
2621 fn can_cast(kind: SyntaxKind) -> bool { 3096 fn can_cast(kind: SyntaxKind) -> bool {
2622 match kind { 3097 match kind {
@@ -2644,6 +3119,11 @@ impl TypeBoundList {
2644pub struct WherePred { 3119pub struct WherePred {
2645 pub(crate) syntax: SyntaxNode, 3120 pub(crate) syntax: SyntaxNode,
2646} 3121}
3122impl std::fmt::Display for WherePred {
3123 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3124 std::fmt::Display::fmt(self.syntax(), f)
3125 }
3126}
2647impl AstNode for WherePred { 3127impl AstNode for WherePred {
2648 fn can_cast(kind: SyntaxKind) -> bool { 3128 fn can_cast(kind: SyntaxKind) -> bool {
2649 match kind { 3129 match kind {
@@ -2672,6 +3152,11 @@ impl WherePred {
2672pub struct WhereClause { 3152pub struct WhereClause {
2673 pub(crate) syntax: SyntaxNode, 3153 pub(crate) syntax: SyntaxNode,
2674} 3154}
3155impl std::fmt::Display for WhereClause {
3156 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3157 std::fmt::Display::fmt(self.syntax(), f)
3158 }
3159}
2675impl AstNode for WhereClause { 3160impl AstNode for WhereClause {
2676 fn can_cast(kind: SyntaxKind) -> bool { 3161 fn can_cast(kind: SyntaxKind) -> bool {
2677 match kind { 3162 match kind {
@@ -2699,6 +3184,11 @@ impl WhereClause {
2699pub struct ExprStmt { 3184pub struct ExprStmt {
2700 pub(crate) syntax: SyntaxNode, 3185 pub(crate) syntax: SyntaxNode,
2701} 3186}
3187impl std::fmt::Display for ExprStmt {
3188 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3189 std::fmt::Display::fmt(self.syntax(), f)
3190 }
3191}
2702impl AstNode for ExprStmt { 3192impl AstNode for ExprStmt {
2703 fn can_cast(kind: SyntaxKind) -> bool { 3193 fn can_cast(kind: SyntaxKind) -> bool {
2704 match kind { 3194 match kind {
@@ -2726,6 +3216,11 @@ impl ExprStmt {
2726pub struct LetStmt { 3216pub struct LetStmt {
2727 pub(crate) syntax: SyntaxNode, 3217 pub(crate) syntax: SyntaxNode,
2728} 3218}
3219impl std::fmt::Display for LetStmt {
3220 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3221 std::fmt::Display::fmt(self.syntax(), f)
3222 }
3223}
2729impl AstNode for LetStmt { 3224impl AstNode for LetStmt {
2730 fn can_cast(kind: SyntaxKind) -> bool { 3225 fn can_cast(kind: SyntaxKind) -> bool {
2731 match kind { 3226 match kind {
@@ -2757,6 +3252,11 @@ impl LetStmt {
2757pub struct Condition { 3252pub struct Condition {
2758 pub(crate) syntax: SyntaxNode, 3253 pub(crate) syntax: SyntaxNode,
2759} 3254}
3255impl std::fmt::Display for Condition {
3256 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3257 std::fmt::Display::fmt(self.syntax(), f)
3258 }
3259}
2760impl AstNode for Condition { 3260impl AstNode for Condition {
2761 fn can_cast(kind: SyntaxKind) -> bool { 3261 fn can_cast(kind: SyntaxKind) -> bool {
2762 match kind { 3262 match kind {
@@ -2787,6 +3287,11 @@ impl Condition {
2787pub struct Block { 3287pub struct Block {
2788 pub(crate) syntax: SyntaxNode, 3288 pub(crate) syntax: SyntaxNode,
2789} 3289}
3290impl std::fmt::Display for Block {
3291 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3292 std::fmt::Display::fmt(self.syntax(), f)
3293 }
3294}
2790impl AstNode for Block { 3295impl AstNode for Block {
2791 fn can_cast(kind: SyntaxKind) -> bool { 3296 fn can_cast(kind: SyntaxKind) -> bool {
2792 match kind { 3297 match kind {
@@ -2819,6 +3324,11 @@ impl Block {
2819pub struct ParamList { 3324pub struct ParamList {
2820 pub(crate) syntax: SyntaxNode, 3325 pub(crate) syntax: SyntaxNode,
2821} 3326}
3327impl std::fmt::Display for ParamList {
3328 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3329 std::fmt::Display::fmt(self.syntax(), f)
3330 }
3331}
2822impl AstNode for ParamList { 3332impl AstNode for ParamList {
2823 fn can_cast(kind: SyntaxKind) -> bool { 3333 fn can_cast(kind: SyntaxKind) -> bool {
2824 match kind { 3334 match kind {
@@ -2849,6 +3359,11 @@ impl ParamList {
2849pub struct SelfParam { 3359pub struct SelfParam {
2850 pub(crate) syntax: SyntaxNode, 3360 pub(crate) syntax: SyntaxNode,
2851} 3361}
3362impl std::fmt::Display for SelfParam {
3363 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3364 std::fmt::Display::fmt(self.syntax(), f)
3365 }
3366}
2852impl AstNode for SelfParam { 3367impl AstNode for SelfParam {
2853 fn can_cast(kind: SyntaxKind) -> bool { 3368 fn can_cast(kind: SyntaxKind) -> bool {
2854 match kind { 3369 match kind {
@@ -2874,6 +3389,11 @@ impl SelfParam {}
2874pub struct Param { 3389pub struct Param {
2875 pub(crate) syntax: SyntaxNode, 3390 pub(crate) syntax: SyntaxNode,
2876} 3391}
3392impl std::fmt::Display for Param {
3393 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3394 std::fmt::Display::fmt(self.syntax(), f)
3395 }
3396}
2877impl AstNode for Param { 3397impl AstNode for Param {
2878 fn can_cast(kind: SyntaxKind) -> bool { 3398 fn can_cast(kind: SyntaxKind) -> bool {
2879 match kind { 3399 match kind {
@@ -2903,6 +3423,11 @@ impl Param {
2903pub struct UseItem { 3423pub struct UseItem {
2904 pub(crate) syntax: SyntaxNode, 3424 pub(crate) syntax: SyntaxNode,
2905} 3425}
3426impl std::fmt::Display for UseItem {
3427 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3428 std::fmt::Display::fmt(self.syntax(), f)
3429 }
3430}
2906impl AstNode for UseItem { 3431impl AstNode for UseItem {
2907 fn can_cast(kind: SyntaxKind) -> bool { 3432 fn can_cast(kind: SyntaxKind) -> bool {
2908 match kind { 3433 match kind {
@@ -2932,6 +3457,11 @@ impl UseItem {
2932pub struct UseTree { 3457pub struct UseTree {
2933 pub(crate) syntax: SyntaxNode, 3458 pub(crate) syntax: SyntaxNode,
2934} 3459}
3460impl std::fmt::Display for UseTree {
3461 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3462 std::fmt::Display::fmt(self.syntax(), f)
3463 }
3464}
2935impl AstNode for UseTree { 3465impl AstNode for UseTree {
2936 fn can_cast(kind: SyntaxKind) -> bool { 3466 fn can_cast(kind: SyntaxKind) -> bool {
2937 match kind { 3467 match kind {
@@ -2965,6 +3495,11 @@ impl UseTree {
2965pub struct Alias { 3495pub struct Alias {
2966 pub(crate) syntax: SyntaxNode, 3496 pub(crate) syntax: SyntaxNode,
2967} 3497}
3498impl std::fmt::Display for Alias {
3499 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3500 std::fmt::Display::fmt(self.syntax(), f)
3501 }
3502}
2968impl AstNode for Alias { 3503impl AstNode for Alias {
2969 fn can_cast(kind: SyntaxKind) -> bool { 3504 fn can_cast(kind: SyntaxKind) -> bool {
2970 match kind { 3505 match kind {
@@ -2989,6 +3524,11 @@ impl Alias {}
2989pub struct UseTreeList { 3524pub struct UseTreeList {
2990 pub(crate) syntax: SyntaxNode, 3525 pub(crate) syntax: SyntaxNode,
2991} 3526}
3527impl std::fmt::Display for UseTreeList {
3528 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3529 std::fmt::Display::fmt(self.syntax(), f)
3530 }
3531}
2992impl AstNode for UseTreeList { 3532impl AstNode for UseTreeList {
2993 fn can_cast(kind: SyntaxKind) -> bool { 3533 fn can_cast(kind: SyntaxKind) -> bool {
2994 match kind { 3534 match kind {
@@ -3016,6 +3556,11 @@ impl UseTreeList {
3016pub struct ExternCrateItem { 3556pub struct ExternCrateItem {
3017 pub(crate) syntax: SyntaxNode, 3557 pub(crate) syntax: SyntaxNode,
3018} 3558}
3559impl std::fmt::Display for ExternCrateItem {
3560 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3561 std::fmt::Display::fmt(self.syntax(), f)
3562 }
3563}
3019impl AstNode for ExternCrateItem { 3564impl AstNode for ExternCrateItem {
3020 fn can_cast(kind: SyntaxKind) -> bool { 3565 fn can_cast(kind: SyntaxKind) -> bool {
3021 match kind { 3566 match kind {
@@ -3048,6 +3593,11 @@ impl ExternCrateItem {
3048pub struct ArgList { 3593pub struct ArgList {
3049 pub(crate) syntax: SyntaxNode, 3594 pub(crate) syntax: SyntaxNode,
3050} 3595}
3596impl std::fmt::Display for ArgList {
3597 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3598 std::fmt::Display::fmt(self.syntax(), f)
3599 }
3600}
3051impl AstNode for ArgList { 3601impl AstNode for ArgList {
3052 fn can_cast(kind: SyntaxKind) -> bool { 3602 fn can_cast(kind: SyntaxKind) -> bool {
3053 match kind { 3603 match kind {
@@ -3075,6 +3625,11 @@ impl ArgList {
3075pub struct Path { 3625pub struct Path {
3076 pub(crate) syntax: SyntaxNode, 3626 pub(crate) syntax: SyntaxNode,
3077} 3627}
3628impl std::fmt::Display for Path {
3629 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3630 std::fmt::Display::fmt(self.syntax(), f)
3631 }
3632}
3078impl AstNode for Path { 3633impl AstNode for Path {
3079 fn can_cast(kind: SyntaxKind) -> bool { 3634 fn can_cast(kind: SyntaxKind) -> bool {
3080 match kind { 3635 match kind {
@@ -3105,6 +3660,11 @@ impl Path {
3105pub struct PathSegment { 3660pub struct PathSegment {
3106 pub(crate) syntax: SyntaxNode, 3661 pub(crate) syntax: SyntaxNode,
3107} 3662}
3663impl std::fmt::Display for PathSegment {
3664 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3665 std::fmt::Display::fmt(self.syntax(), f)
3666 }
3667}
3108impl AstNode for PathSegment { 3668impl AstNode for PathSegment {
3109 fn can_cast(kind: SyntaxKind) -> bool { 3669 fn can_cast(kind: SyntaxKind) -> bool {
3110 match kind { 3670 match kind {
@@ -3144,6 +3704,11 @@ impl PathSegment {
3144pub struct TypeArgList { 3704pub struct TypeArgList {
3145 pub(crate) syntax: SyntaxNode, 3705 pub(crate) syntax: SyntaxNode,
3146} 3706}
3707impl std::fmt::Display for TypeArgList {
3708 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3709 std::fmt::Display::fmt(self.syntax(), f)
3710 }
3711}
3147impl AstNode for TypeArgList { 3712impl AstNode for TypeArgList {
3148 fn can_cast(kind: SyntaxKind) -> bool { 3713 fn can_cast(kind: SyntaxKind) -> bool {
3149 match kind { 3714 match kind {
@@ -3180,6 +3745,11 @@ impl TypeArgList {
3180pub struct TypeArg { 3745pub struct TypeArg {
3181 pub(crate) syntax: SyntaxNode, 3746 pub(crate) syntax: SyntaxNode,
3182} 3747}
3748impl std::fmt::Display for TypeArg {
3749 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3750 std::fmt::Display::fmt(self.syntax(), f)
3751 }
3752}
3183impl AstNode for TypeArg { 3753impl AstNode for TypeArg {
3184 fn can_cast(kind: SyntaxKind) -> bool { 3754 fn can_cast(kind: SyntaxKind) -> bool {
3185 match kind { 3755 match kind {
@@ -3207,6 +3777,11 @@ impl TypeArg {
3207pub struct AssocTypeArg { 3777pub struct AssocTypeArg {
3208 pub(crate) syntax: SyntaxNode, 3778 pub(crate) syntax: SyntaxNode,
3209} 3779}
3780impl std::fmt::Display for AssocTypeArg {
3781 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3782 std::fmt::Display::fmt(self.syntax(), f)
3783 }
3784}
3210impl AstNode for AssocTypeArg { 3785impl AstNode for AssocTypeArg {
3211 fn can_cast(kind: SyntaxKind) -> bool { 3786 fn can_cast(kind: SyntaxKind) -> bool {
3212 match kind { 3787 match kind {
@@ -3237,6 +3812,11 @@ impl AssocTypeArg {
3237pub struct LifetimeArg { 3812pub struct LifetimeArg {
3238 pub(crate) syntax: SyntaxNode, 3813 pub(crate) syntax: SyntaxNode,
3239} 3814}
3815impl std::fmt::Display for LifetimeArg {
3816 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3817 std::fmt::Display::fmt(self.syntax(), f)
3818 }
3819}
3240impl AstNode for LifetimeArg { 3820impl AstNode for LifetimeArg {
3241 fn can_cast(kind: SyntaxKind) -> bool { 3821 fn can_cast(kind: SyntaxKind) -> bool {
3242 match kind { 3822 match kind {
@@ -3260,6 +3840,11 @@ impl LifetimeArg {}
3260pub struct ConstArg { 3840pub struct ConstArg {
3261 pub(crate) syntax: SyntaxNode, 3841 pub(crate) syntax: SyntaxNode,
3262} 3842}
3843impl std::fmt::Display for ConstArg {
3844 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3845 std::fmt::Display::fmt(self.syntax(), f)
3846 }
3847}
3263impl AstNode for ConstArg { 3848impl AstNode for ConstArg {
3264 fn can_cast(kind: SyntaxKind) -> bool { 3849 fn can_cast(kind: SyntaxKind) -> bool {
3265 match kind { 3850 match kind {
@@ -3290,6 +3875,11 @@ impl ConstArg {
3290pub struct MacroItems { 3875pub struct MacroItems {
3291 pub(crate) syntax: SyntaxNode, 3876 pub(crate) syntax: SyntaxNode,
3292} 3877}
3878impl std::fmt::Display for MacroItems {
3879 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3880 std::fmt::Display::fmt(self.syntax(), f)
3881 }
3882}
3293impl AstNode for MacroItems { 3883impl AstNode for MacroItems {
3294 fn can_cast(kind: SyntaxKind) -> bool { 3884 fn can_cast(kind: SyntaxKind) -> bool {
3295 match kind { 3885 match kind {
@@ -3315,6 +3905,11 @@ impl MacroItems {}
3315pub struct MacroStmts { 3905pub struct MacroStmts {
3316 pub(crate) syntax: SyntaxNode, 3906 pub(crate) syntax: SyntaxNode,
3317} 3907}
3908impl std::fmt::Display for MacroStmts {
3909 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3910 std::fmt::Display::fmt(self.syntax(), f)
3911 }
3912}
3318impl AstNode for MacroStmts { 3913impl AstNode for MacroStmts {
3319 fn can_cast(kind: SyntaxKind) -> bool { 3914 fn can_cast(kind: SyntaxKind) -> bool {
3320 match kind { 3915 match kind {
@@ -3362,6 +3957,11 @@ impl From<UnionDef> for NominalDef {
3362 NominalDef::UnionDef(node) 3957 NominalDef::UnionDef(node)
3363 } 3958 }
3364} 3959}
3960impl std::fmt::Display for NominalDef {
3961 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3962 std::fmt::Display::fmt(self.syntax(), f)
3963 }
3964}
3365impl AstNode for NominalDef { 3965impl AstNode for NominalDef {
3366 fn can_cast(kind: SyntaxKind) -> bool { 3966 fn can_cast(kind: SyntaxKind) -> bool {
3367 match kind { 3967 match kind {
@@ -3470,6 +4070,11 @@ impl From<DynTraitType> for TypeRef {
3470 TypeRef::DynTraitType(node) 4070 TypeRef::DynTraitType(node)
3471 } 4071 }
3472} 4072}
4073impl std::fmt::Display for TypeRef {
4074 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4075 std::fmt::Display::fmt(self.syntax(), f)
4076 }
4077}
3473impl AstNode for TypeRef { 4078impl AstNode for TypeRef {
3474 fn can_cast(kind: SyntaxKind) -> bool { 4079 fn can_cast(kind: SyntaxKind) -> bool {
3475 match kind { 4080 match kind {
@@ -3591,6 +4196,11 @@ impl From<Module> for ModuleItem {
3591 ModuleItem::Module(node) 4196 ModuleItem::Module(node)
3592 } 4197 }
3593} 4198}
4199impl std::fmt::Display for ModuleItem {
4200 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4201 std::fmt::Display::fmt(self.syntax(), f)
4202 }
4203}
3594impl AstNode for ModuleItem { 4204impl AstNode for ModuleItem {
3595 fn can_cast(kind: SyntaxKind) -> bool { 4205 fn can_cast(kind: SyntaxKind) -> bool {
3596 match kind { 4206 match kind {
@@ -3657,6 +4267,11 @@ impl From<ConstDef> for ImplItem {
3657 ImplItem::ConstDef(node) 4267 ImplItem::ConstDef(node)
3658 } 4268 }
3659} 4269}
4270impl std::fmt::Display for ImplItem {
4271 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4272 std::fmt::Display::fmt(self.syntax(), f)
4273 }
4274}
3660impl AstNode for ImplItem { 4275impl AstNode for ImplItem {
3661 fn can_cast(kind: SyntaxKind) -> bool { 4276 fn can_cast(kind: SyntaxKind) -> bool {
3662 match kind { 4277 match kind {
@@ -3871,6 +4486,11 @@ impl From<BoxExpr> for Expr {
3871 Expr::BoxExpr(node) 4486 Expr::BoxExpr(node)
3872 } 4487 }
3873} 4488}
4489impl std::fmt::Display for Expr {
4490 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4491 std::fmt::Display::fmt(self.syntax(), f)
4492 }
4493}
3874impl AstNode for Expr { 4494impl AstNode for Expr {
3875 fn can_cast(kind: SyntaxKind) -> bool { 4495 fn can_cast(kind: SyntaxKind) -> bool {
3876 match kind { 4496 match kind {
@@ -4043,6 +4663,11 @@ impl From<LiteralPat> for Pat {
4043 Pat::LiteralPat(node) 4663 Pat::LiteralPat(node)
4044 } 4664 }
4045} 4665}
4666impl std::fmt::Display for Pat {
4667 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4668 std::fmt::Display::fmt(self.syntax(), f)
4669 }
4670}
4046impl AstNode for Pat { 4671impl AstNode for Pat {
4047 fn can_cast(kind: SyntaxKind) -> bool { 4672 fn can_cast(kind: SyntaxKind) -> bool {
4048 match kind { 4673 match kind {
@@ -4106,6 +4731,11 @@ impl From<TokenTree> for AttrInput {
4106 AttrInput::TokenTree(node) 4731 AttrInput::TokenTree(node)
4107 } 4732 }
4108} 4733}
4734impl std::fmt::Display for AttrInput {
4735 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4736 std::fmt::Display::fmt(self.syntax(), f)
4737 }
4738}
4109impl AstNode for AttrInput { 4739impl AstNode for AttrInput {
4110 fn can_cast(kind: SyntaxKind) -> bool { 4740 fn can_cast(kind: SyntaxKind) -> bool {
4111 match kind { 4741 match kind {
@@ -4143,6 +4773,11 @@ impl From<LetStmt> for Stmt {
4143 Stmt::LetStmt(node) 4773 Stmt::LetStmt(node)
4144 } 4774 }
4145} 4775}
4776impl std::fmt::Display for Stmt {
4777 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
4778 std::fmt::Display::fmt(self.syntax(), f)
4779 }
4780}
4146impl AstNode for Stmt { 4781impl AstNode for Stmt {
4147 fn can_cast(kind: SyntaxKind) -> bool { 4782 fn can_cast(kind: SyntaxKind) -> bool {
4148 match kind { 4783 match kind {
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rs b/crates/ra_syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rs
new file mode 100644
index 000000000..05acc30f1
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.rs
@@ -0,0 +1,3 @@
1fn foo() {
2 v = {1}&2;
3}
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.txt b/crates/ra_syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.txt
new file mode 100644
index 000000000..d568a1d45
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0158_binop_resets_statementness.txt
@@ -0,0 +1,38 @@
1SOURCE_FILE@[0; 28)
2 FN_DEF@[0; 27)
3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " "
5 NAME@[3; 6)
6 IDENT@[3; 6) "foo"
7 PARAM_LIST@[6; 8)
8 L_PAREN@[6; 7) "("
9 R_PAREN@[7; 8) ")"
10 WHITESPACE@[8; 9) " "
11 BLOCK_EXPR@[9; 27)
12 BLOCK@[9; 27)
13 L_CURLY@[9; 10) "{"
14 WHITESPACE@[10; 15) "\n "
15 EXPR_STMT@[15; 25)
16 BIN_EXPR@[15; 24)
17 PATH_EXPR@[15; 16)
18 PATH@[15; 16)
19 PATH_SEGMENT@[15; 16)
20 NAME_REF@[15; 16)
21 IDENT@[15; 16) "v"
22 WHITESPACE@[16; 17) " "
23 EQ@[17; 18) "="
24 WHITESPACE@[18; 19) " "
25 BIN_EXPR@[19; 24)
26 BLOCK_EXPR@[19; 22)
27 BLOCK@[19; 22)
28 L_CURLY@[19; 20) "{"
29 LITERAL@[20; 21)
30 INT_NUMBER@[20; 21) "1"
31 R_CURLY@[21; 22) "}"
32 AMP@[22; 23) "&"
33 LITERAL@[23; 24)
34 INT_NUMBER@[23; 24) "2"
35 SEMI@[24; 25) ";"
36 WHITESPACE@[25; 26) "\n"
37 R_CURLY@[26; 27) "}"
38 WHITESPACE@[27; 28) "\n"
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs
index 5df29a383..2ce69c9b3 100644
--- a/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -52,7 +52,10 @@ pub(crate) fn load_cargo(
52 opts 52 opts
53 }; 53 };
54 54
55 let crate_graph = ws.to_crate_graph(&default_cfg_options, &mut |path: &Path| { 55 // FIXME: outdirs?
56 let outdirs = FxHashMap::default();
57
58 let crate_graph = ws.to_crate_graph(&default_cfg_options, &outdirs, &mut |path: &Path| {
56 let vfs_file = vfs.load(path); 59 let vfs_file = vfs.load(path);
57 log::debug!("vfs file {:?} -> {:?}", path, vfs_file); 60 log::debug!("vfs file {:?} -> {:?}", path, vfs_file);
58 vfs_file.map(vfs_file_to_id) 61 vfs_file.map(vfs_file_to_id)
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 3a6cfbe7b..bd5904db0 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -47,6 +47,9 @@ pub struct ServerConfig {
47 /// Fine grained feature flags to disable specific features. 47 /// Fine grained feature flags to disable specific features.
48 pub feature_flags: FxHashMap<String, bool>, 48 pub feature_flags: FxHashMap<String, bool>,
49 49
50 /// Fine grained controls for additional `OUT_DIR` env variables
51 pub additional_out_dirs: FxHashMap<String, String>,
52
50 pub rustfmt_args: Vec<String>, 53 pub rustfmt_args: Vec<String>,
51 54
52 /// Cargo feature configurations. 55 /// Cargo feature configurations.
@@ -67,6 +70,7 @@ impl Default for ServerConfig {
67 cargo_watch_all_targets: true, 70 cargo_watch_all_targets: true,
68 with_sysroot: true, 71 with_sysroot: true,
69 feature_flags: FxHashMap::default(), 72 feature_flags: FxHashMap::default(),
73 additional_out_dirs: FxHashMap::default(),
70 cargo_features: Default::default(), 74 cargo_features: Default::default(),
71 rustfmt_args: Vec::new(), 75 rustfmt_args: Vec::new(),
72 } 76 }
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index b6d1f28d8..495056da3 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -196,6 +196,7 @@ pub fn main_loop(
196 Watch(!config.use_client_watching), 196 Watch(!config.use_client_watching),
197 options, 197 options,
198 feature_flags, 198 feature_flags,
199 config.additional_out_dirs,
199 ) 200 )
200 }; 201 };
201 202
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs
index 004803b00..d358f6b47 100644
--- a/crates/rust-analyzer/src/world.rs
+++ b/crates/rust-analyzer/src/world.rs
@@ -27,6 +27,8 @@ use crate::{
27 vfs_glob::{Glob, RustPackageFilterBuilder}, 27 vfs_glob::{Glob, RustPackageFilterBuilder},
28 LspError, Result, 28 LspError, Result,
29}; 29};
30use ra_db::ExternSourceId;
31use rustc_hash::{FxHashMap, FxHashSet};
30 32
31#[derive(Debug, Clone)] 33#[derive(Debug, Clone)]
32pub struct Options { 34pub struct Options {
@@ -79,6 +81,7 @@ impl WorldState {
79 watch: Watch, 81 watch: Watch,
80 options: Options, 82 options: Options,
81 feature_flags: FeatureFlags, 83 feature_flags: FeatureFlags,
84 additional_out_dirs: FxHashMap<String, String>,
82 ) -> WorldState { 85 ) -> WorldState {
83 let mut change = AnalysisChange::new(); 86 let mut change = AnalysisChange::new();
84 87
@@ -100,6 +103,19 @@ impl WorldState {
100 RootEntry::new(pkg_root.path().clone(), filter.into_vfs_filter()) 103 RootEntry::new(pkg_root.path().clone(), filter.into_vfs_filter())
101 })); 104 }));
102 } 105 }
106
107 let extern_dirs: FxHashSet<_> =
108 additional_out_dirs.iter().map(|(_, path)| (PathBuf::from(path))).collect();
109 let mut extern_source_roots = FxHashMap::default();
110
111 roots.extend(additional_out_dirs.iter().map(|(_, path)| {
112 let mut filter = RustPackageFilterBuilder::default().set_member(false);
113 for glob in exclude_globs.iter() {
114 filter = filter.exclude(glob.clone());
115 }
116 RootEntry::new(PathBuf::from(&path), filter.into_vfs_filter())
117 }));
118
103 let (task_sender, task_receiver) = unbounded(); 119 let (task_sender, task_receiver) = unbounded();
104 let task_sender = Box::new(move |t| task_sender.send(t).unwrap()); 120 let task_sender = Box::new(move |t| task_sender.send(t).unwrap());
105 let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch); 121 let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch);
@@ -109,6 +125,11 @@ impl WorldState {
109 let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it)); 125 let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it));
110 change.add_root(SourceRootId(r.0), is_local); 126 change.add_root(SourceRootId(r.0), is_local);
111 change.set_debug_root_path(SourceRootId(r.0), vfs_root_path.display().to_string()); 127 change.set_debug_root_path(SourceRootId(r.0), vfs_root_path.display().to_string());
128
129 // FIXME: add path2root in vfs to simpily this logic
130 if extern_dirs.contains(&vfs_root_path) {
131 extern_source_roots.insert(vfs_root_path, ExternSourceId(r.0));
132 }
112 } 133 }
113 134
114 // FIXME: Read default cfgs from config 135 // FIXME: Read default cfgs from config
@@ -126,11 +147,20 @@ impl WorldState {
126 vfs_file.map(|f| FileId(f.0)) 147 vfs_file.map(|f| FileId(f.0))
127 }; 148 };
128 149
129 workspaces.iter().map(|ws| ws.to_crate_graph(&default_cfg_options, &mut load)).for_each( 150 let mut outdirs = FxHashMap::default();
130 |graph| { 151 for (name, path) in additional_out_dirs {
152 let path = PathBuf::from(&path);
153 if let Some(id) = extern_source_roots.get(&path) {
154 outdirs.insert(name, (id.clone(), path.to_string_lossy().replace("\\", "/")));
155 }
156 }
157
158 workspaces
159 .iter()
160 .map(|ws| ws.to_crate_graph(&default_cfg_options, &outdirs, &mut load))
161 .for_each(|graph| {
131 crate_graph.extend(graph); 162 crate_graph.extend(graph);
132 }, 163 });
133 );
134 change.set_crate_graph(crate_graph); 164 change.set_crate_graph(crate_graph);
135 165
136 // FIXME: Figure out the multi-workspace situation 166 // FIXME: Figure out the multi-workspace situation
diff --git a/editors/code/package.json b/editors/code/package.json
index 78f3539e9..3aaae357a 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -224,6 +224,11 @@
224 "default": true, 224 "default": true,
225 "description": "Whether to ask for permission before downloading any files from the Internet" 225 "description": "Whether to ask for permission before downloading any files from the Internet"
226 }, 226 },
227 "rust-analyzer.additionalOutDirs": {
228 "type": "object",
229 "default": {},
230 "markdownDescription": "Fine grained controls for OUT_DIR `env!(\"OUT_DIR\")` variable. e.g. `{\"foo\":\"/path/to/foo\"}`, "
231 },
227 "rust-analyzer.serverPath": { 232 "rust-analyzer.serverPath": {
228 "type": [ 233 "type": [
229 "null", 234 "null",
@@ -256,7 +261,7 @@
256 "rust-analyzer.cargo-watch.enable": { 261 "rust-analyzer.cargo-watch.enable": {
257 "type": "boolean", 262 "type": "boolean",
258 "default": true, 263 "default": true,
259 "markdownDescription": "Run `cargo check` for diagnostics on save" 264 "markdownDescription": "Run specified `cargo-watch` command for diagnostics on save"
260 }, 265 },
261 "rust-analyzer.cargo-watch.arguments": { 266 "rust-analyzer.cargo-watch.arguments": {
262 "type": "array", 267 "type": "array",
diff --git a/editors/code/src/client.ts b/editors/code/src/client.ts
index 3b8ea6f77..e9f261c24 100644
--- a/editors/code/src/client.ts
+++ b/editors/code/src/client.ts
@@ -37,6 +37,7 @@ export async function createClient(config: Config, serverPath: string): Promise<
37 excludeGlobs: config.excludeGlobs, 37 excludeGlobs: config.excludeGlobs,
38 useClientWatching: config.useClientWatching, 38 useClientWatching: config.useClientWatching,
39 featureFlags: config.featureFlags, 39 featureFlags: config.featureFlags,
40 additionalOutDirs: config.additionalOutDirs,
40 withSysroot: config.withSysroot, 41 withSysroot: config.withSysroot,
41 cargoFeatures: config.cargoFeatures, 42 cargoFeatures: config.cargoFeatures,
42 rustfmtArgs: config.rustfmtArgs, 43 rustfmtArgs: config.rustfmtArgs,
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index c3b3ecabf..6db073bec 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -166,6 +166,7 @@ export class Config {
166 get excludeGlobs() { return this.cfg.get("excludeGlobs") as string[]; } 166 get excludeGlobs() { return this.cfg.get("excludeGlobs") as string[]; }
167 get useClientWatching() { return this.cfg.get("useClientWatching") as boolean; } 167 get useClientWatching() { return this.cfg.get("useClientWatching") as boolean; }
168 get featureFlags() { return this.cfg.get("featureFlags") as Record<string, boolean>; } 168 get featureFlags() { return this.cfg.get("featureFlags") as Record<string, boolean>; }
169 get additionalOutDirs() { return this.cfg.get("additionalOutDirs") as Record<string, string>; }
169 get rustfmtArgs() { return this.cfg.get("rustfmtArgs") as string[]; } 170 get rustfmtArgs() { return this.cfg.get("rustfmtArgs") as string[]; }
170 171
171 get cargoWatchOptions(): CargoWatchOptions { 172 get cargoWatchOptions(): CargoWatchOptions {
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs
index db05dcebb..32afd47bc 100644
--- a/xtask/src/codegen/gen_syntax.rs
+++ b/xtask/src/codegen/gen_syntax.rs
@@ -68,6 +68,12 @@ fn generate_ast(grammar: AstSrc<'_>) -> Result<String> {
68 pub(crate) syntax: SyntaxNode, 68 pub(crate) syntax: SyntaxNode,
69 } 69 }
70 70
71 impl std::fmt::Display for #name {
72 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
73 std::fmt::Display::fmt(self.syntax(), f)
74 }
75 }
76
71 impl AstNode for #name { 77 impl AstNode for #name {
72 fn can_cast(kind: SyntaxKind) -> bool { 78 fn can_cast(kind: SyntaxKind) -> bool {
73 match kind { 79 match kind {
@@ -114,6 +120,12 @@ fn generate_ast(grammar: AstSrc<'_>) -> Result<String> {
114 } 120 }
115 )* 121 )*
116 122
123 impl std::fmt::Display for #name {
124 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
125 std::fmt::Display::fmt(self.syntax(), f)
126 }
127 }
128
117 impl AstNode for #name { 129 impl AstNode for #name {
118 fn can_cast(kind: SyntaxKind) -> bool { 130 fn can_cast(kind: SyntaxKind) -> bool {
119 match kind { 131 match kind {