aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-07-14 13:58:34 +0100
committerGitHub <[email protected]>2020-07-14 13:58:34 +0100
commitebb4d29d694f60f746a2b7b43980ba89cc9dc807 (patch)
tree152c05466cc8541efa920688ac4e2197cc6e96c1
parent92c5036a7cf9dc32fccdf3c831af05b74550a3e1 (diff)
parentabeb003df47de4a1b7aa36a7c4d7987d8cf40ace (diff)
Merge #5371
5371: Allow multiline annotations r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
-rw-r--r--crates/ra_hir_ty/src/diagnostics.rs3
-rw-r--r--crates/ra_hir_ty/src/diagnostics/match_check.rs2
-rw-r--r--crates/test_utils/src/lib.rs77
3 files changed, 68 insertions, 14 deletions
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs
index 3016ca3bd..3870c6d9c 100644
--- a/crates/ra_hir_ty/src/diagnostics.rs
+++ b/crates/ra_hir_ty/src/diagnostics.rs
@@ -261,8 +261,7 @@ fn check_diagnostics(ra_fixture: &str) {
261 // FXIME: macros... 261 // FXIME: macros...
262 let file_id = d.source().file_id.original_file(&db); 262 let file_id = d.source().file_id.original_file(&db);
263 let range = d.syntax_node(&db).text_range(); 263 let range = d.syntax_node(&db).text_range();
264 // FIXME: support multi-line messages in annotations 264 let message = d.message().to_owned();
265 let message = d.message().lines().next().unwrap().to_owned();
266 actual.entry(file_id).or_default().push((range, message)); 265 actual.entry(file_id).or_default().push((range, message));
267 }); 266 });
268 actual.values_mut().for_each(|diags| diags.sort_by_key(|it| it.0.start())); 267 actual.values_mut().for_each(|diags| diags.sort_by_key(|it| it.0.start()));
diff --git a/crates/ra_hir_ty/src/diagnostics/match_check.rs b/crates/ra_hir_ty/src/diagnostics/match_check.rs
index ba48b51b5..95f272811 100644
--- a/crates/ra_hir_ty/src/diagnostics/match_check.rs
+++ b/crates/ra_hir_ty/src/diagnostics/match_check.rs
@@ -1162,12 +1162,14 @@ fn main() {
1162 match a { 1162 match a {
1163 Either::A { } => (), 1163 Either::A { } => (),
1164 //^^^ Missing structure fields: 1164 //^^^ Missing structure fields:
1165 // | - foo
1165 Either::B => (), 1166 Either::B => (),
1166 } 1167 }
1167 match a { 1168 match a {
1168 //^ Missing match arm 1169 //^ Missing match arm
1169 Either::A { } => (), 1170 Either::A { } => (),
1170 } //^^^ Missing structure fields: 1171 } //^^^ Missing structure fields:
1172 // | - foo
1171 1173
1172 match a { 1174 match a {
1173 Either::A { foo: true } => (), 1175 Either::A { foo: true } => (),
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index e4aa894ac..ad586c882 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -179,31 +179,80 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
179 let mut res = Vec::new(); 179 let mut res = Vec::new();
180 let mut prev_line_start: Option<TextSize> = None; 180 let mut prev_line_start: Option<TextSize> = None;
181 let mut line_start: TextSize = 0.into(); 181 let mut line_start: TextSize = 0.into();
182 let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new();
182 for line in lines_with_ends(text) { 183 for line in lines_with_ends(text) {
183 if let Some(idx) = line.find("//^") { 184 let mut this_line_annotations = Vec::new();
184 let offset = prev_line_start.unwrap() + TextSize::of(&line[..idx + "//".len()]); 185 if let Some(idx) = line.find("//") {
185 for (line_range, text) in extract_line_annotations(&line[idx + "//".len()..]) { 186 let annotation_offset = TextSize::of(&line[..idx + "//".len()]);
186 res.push((line_range + offset, text)) 187 for annotation in extract_line_annotations(&line[idx + "//".len()..]) {
188 match annotation {
189 LineAnnotation::Annotation { mut range, content } => {
190 range += annotation_offset;
191 this_line_annotations.push((range.end(), res.len()));
192 res.push((range + prev_line_start.unwrap(), content))
193 }
194 LineAnnotation::Continuation { mut offset, content } => {
195 offset += annotation_offset;
196 let &(_, idx) = prev_line_annotations
197 .iter()
198 .find(|&&(off, _idx)| off == offset)
199 .unwrap();
200 res[idx].1.push('\n');
201 res[idx].1.push_str(&content);
202 res[idx].1.push('\n');
203 }
204 }
187 } 205 }
188 } 206 }
207
189 prev_line_start = Some(line_start); 208 prev_line_start = Some(line_start);
190 line_start += TextSize::of(line); 209 line_start += TextSize::of(line);
210
211 prev_line_annotations = this_line_annotations;
191 } 212 }
192 res 213 res
193} 214}
194 215
195fn extract_line_annotations(mut line: &str) -> Vec<(TextRange, String)> { 216enum LineAnnotation {
217 Annotation { range: TextRange, content: String },
218 Continuation { offset: TextSize, content: String },
219}
220
221fn extract_line_annotations(mut line: &str) -> Vec<LineAnnotation> {
196 let mut res = Vec::new(); 222 let mut res = Vec::new();
197 let mut offset: TextSize = 0.into(); 223 let mut offset: TextSize = 0.into();
198 while !line.is_empty() { 224 let marker: fn(char) -> bool = if line.contains('^') { |c| c == '^' } else { |c| c == '|' };
199 let len = line.chars().take_while(|&it| it == '^').count(); 225 loop {
200 assert!(len > 0); 226 match line.find(marker) {
227 Some(idx) => {
228 offset += TextSize::try_from(idx).unwrap();
229 line = &line[idx..];
230 }
231 None => break,
232 };
233
234 let mut len = line.chars().take_while(|&it| it == '^').count();
235 let mut continuation = false;
236 if len == 0 {
237 assert!(line.starts_with('|'));
238 continuation = true;
239 len = 1;
240 }
201 let range = TextRange::at(offset, len.try_into().unwrap()); 241 let range = TextRange::at(offset, len.try_into().unwrap());
202 let next = line[len..].find('^').map_or(line.len(), |it| it + len); 242 let next = line[len..].find(marker).map_or(line.len(), |it| it + len);
203 res.push((range, line[len..][..next - len].trim().to_string())); 243 let content = line[len..][..next - len].trim().to_string();
244
245 let annotation = if continuation {
246 LineAnnotation::Continuation { offset: range.end(), content }
247 } else {
248 LineAnnotation::Annotation { range, content }
249 };
250 res.push(annotation);
251
204 line = &line[next..]; 252 line = &line[next..];
205 offset += TextSize::try_from(next).unwrap(); 253 offset += TextSize::try_from(next).unwrap();
206 } 254 }
255
207 res 256 res
208} 257}
209 258
@@ -215,14 +264,18 @@ fn main() {
215 let (x, y) = (9, 2); 264 let (x, y) = (9, 2);
216 //^ def ^ def 265 //^ def ^ def
217 zoo + 1 266 zoo + 1
218} //^^^ i32 267} //^^^ type:
268 // | i32
219 "#, 269 "#,
220 ); 270 );
221 let res = extract_annotations(&text) 271 let res = extract_annotations(&text)
222 .into_iter() 272 .into_iter()
223 .map(|(range, ann)| (&text[range], ann)) 273 .map(|(range, ann)| (&text[range], ann))
224 .collect::<Vec<_>>(); 274 .collect::<Vec<_>>();
225 assert_eq!(res, vec![("x", "def".into()), ("y", "def".into()), ("zoo", "i32".into()),]); 275 assert_eq!(
276 res,
277 vec![("x", "def".into()), ("y", "def".into()), ("zoo", "type:\ni32\n".into()),]
278 );
226} 279}
227 280
228// Comparison functionality borrowed from cargo: 281// Comparison functionality borrowed from cargo: