mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-25 12:33:33 +00:00
Allow multiline annotations
This commit is contained in:
parent
0b0865ab22
commit
abeb003df4
3 changed files with 59 additions and 13 deletions
|
@ -261,8 +261,7 @@ fn check_diagnostics(ra_fixture: &str) {
|
||||||
// FXIME: macros...
|
// FXIME: macros...
|
||||||
let file_id = d.source().file_id.original_file(&db);
|
let file_id = d.source().file_id.original_file(&db);
|
||||||
let range = d.syntax_node(&db).text_range();
|
let range = d.syntax_node(&db).text_range();
|
||||||
// FIXME: support multi-line messages in annotations
|
let message = d.message().to_owned();
|
||||||
let message = d.message().lines().next().unwrap().to_owned();
|
|
||||||
actual.entry(file_id).or_default().push((range, message));
|
actual.entry(file_id).or_default().push((range, message));
|
||||||
});
|
});
|
||||||
actual.values_mut().for_each(|diags| diags.sort_by_key(|it| it.0.start()));
|
actual.values_mut().for_each(|diags| diags.sort_by_key(|it| it.0.start()));
|
||||||
|
|
|
@ -1162,12 +1162,14 @@ fn main() {
|
||||||
match a {
|
match a {
|
||||||
Either::A { } => (),
|
Either::A { } => (),
|
||||||
//^^^ Missing structure fields:
|
//^^^ Missing structure fields:
|
||||||
|
// | - foo
|
||||||
Either::B => (),
|
Either::B => (),
|
||||||
}
|
}
|
||||||
match a {
|
match a {
|
||||||
//^ Missing match arm
|
//^ Missing match arm
|
||||||
Either::A { } => (),
|
Either::A { } => (),
|
||||||
} //^^^ Missing structure fields:
|
} //^^^ Missing structure fields:
|
||||||
|
// | - foo
|
||||||
|
|
||||||
match a {
|
match a {
|
||||||
Either::A { foo: true } => (),
|
Either::A { foo: true } => (),
|
||||||
|
|
|
@ -179,24 +179,51 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
|
||||||
let mut res = Vec::new();
|
let mut res = Vec::new();
|
||||||
let mut prev_line_start: Option<TextSize> = None;
|
let mut prev_line_start: Option<TextSize> = None;
|
||||||
let mut line_start: TextSize = 0.into();
|
let mut line_start: TextSize = 0.into();
|
||||||
|
let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new();
|
||||||
for line in lines_with_ends(text) {
|
for line in lines_with_ends(text) {
|
||||||
|
let mut this_line_annotations = Vec::new();
|
||||||
if let Some(idx) = line.find("//") {
|
if let Some(idx) = line.find("//") {
|
||||||
let offset = prev_line_start.unwrap() + TextSize::of(&line[..idx + "//".len()]);
|
let annotation_offset = TextSize::of(&line[..idx + "//".len()]);
|
||||||
for (line_range, text) in extract_line_annotations(&line[idx + "//".len()..]) {
|
for annotation in extract_line_annotations(&line[idx + "//".len()..]) {
|
||||||
res.push((line_range + offset, text))
|
match annotation {
|
||||||
|
LineAnnotation::Annotation { mut range, content } => {
|
||||||
|
range += annotation_offset;
|
||||||
|
this_line_annotations.push((range.end(), res.len()));
|
||||||
|
res.push((range + prev_line_start.unwrap(), content))
|
||||||
|
}
|
||||||
|
LineAnnotation::Continuation { mut offset, content } => {
|
||||||
|
offset += annotation_offset;
|
||||||
|
let &(_, idx) = prev_line_annotations
|
||||||
|
.iter()
|
||||||
|
.find(|&&(off, _idx)| off == offset)
|
||||||
|
.unwrap();
|
||||||
|
res[idx].1.push('\n');
|
||||||
|
res[idx].1.push_str(&content);
|
||||||
|
res[idx].1.push('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_line_start = Some(line_start);
|
prev_line_start = Some(line_start);
|
||||||
line_start += TextSize::of(line);
|
line_start += TextSize::of(line);
|
||||||
|
|
||||||
|
prev_line_annotations = this_line_annotations;
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_line_annotations(mut line: &str) -> Vec<(TextRange, String)> {
|
enum LineAnnotation {
|
||||||
|
Annotation { range: TextRange, content: String },
|
||||||
|
Continuation { offset: TextSize, content: String },
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract_line_annotations(mut line: &str) -> Vec<LineAnnotation> {
|
||||||
let mut res = Vec::new();
|
let mut res = Vec::new();
|
||||||
let mut offset: TextSize = 0.into();
|
let mut offset: TextSize = 0.into();
|
||||||
|
let marker: fn(char) -> bool = if line.contains('^') { |c| c == '^' } else { |c| c == '|' };
|
||||||
loop {
|
loop {
|
||||||
match line.find('^') {
|
match line.find(marker) {
|
||||||
Some(idx) => {
|
Some(idx) => {
|
||||||
offset += TextSize::try_from(idx).unwrap();
|
offset += TextSize::try_from(idx).unwrap();
|
||||||
line = &line[idx..];
|
line = &line[idx..];
|
||||||
|
@ -204,14 +231,28 @@ fn extract_line_annotations(mut line: &str) -> Vec<(TextRange, String)> {
|
||||||
None => break,
|
None => break,
|
||||||
};
|
};
|
||||||
|
|
||||||
let len = line.chars().take_while(|&it| it == '^').count();
|
let mut len = line.chars().take_while(|&it| it == '^').count();
|
||||||
assert!(len > 0);
|
let mut continuation = false;
|
||||||
|
if len == 0 {
|
||||||
|
assert!(line.starts_with('|'));
|
||||||
|
continuation = true;
|
||||||
|
len = 1;
|
||||||
|
}
|
||||||
let range = TextRange::at(offset, len.try_into().unwrap());
|
let range = TextRange::at(offset, len.try_into().unwrap());
|
||||||
let next = line[len..].find('^').map_or(line.len(), |it| it + len);
|
let next = line[len..].find(marker).map_or(line.len(), |it| it + len);
|
||||||
res.push((range, line[len..][..next - len].trim().to_string()));
|
let content = line[len..][..next - len].trim().to_string();
|
||||||
|
|
||||||
|
let annotation = if continuation {
|
||||||
|
LineAnnotation::Continuation { offset: range.end(), content }
|
||||||
|
} else {
|
||||||
|
LineAnnotation::Annotation { range, content }
|
||||||
|
};
|
||||||
|
res.push(annotation);
|
||||||
|
|
||||||
line = &line[next..];
|
line = &line[next..];
|
||||||
offset += TextSize::try_from(next).unwrap();
|
offset += TextSize::try_from(next).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,14 +264,18 @@ fn main() {
|
||||||
let (x, y) = (9, 2);
|
let (x, y) = (9, 2);
|
||||||
//^ def ^ def
|
//^ def ^ def
|
||||||
zoo + 1
|
zoo + 1
|
||||||
} //^^^ i32
|
} //^^^ type:
|
||||||
|
// | i32
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
let res = extract_annotations(&text)
|
let res = extract_annotations(&text)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(range, ann)| (&text[range], ann))
|
.map(|(range, ann)| (&text[range], ann))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
assert_eq!(res, vec![("x", "def".into()), ("y", "def".into()), ("zoo", "i32".into()),]);
|
assert_eq!(
|
||||||
|
res,
|
||||||
|
vec![("x", "def".into()), ("y", "def".into()), ("zoo", "type:\ni32\n".into()),]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comparison functionality borrowed from cargo:
|
// Comparison functionality borrowed from cargo:
|
||||||
|
|
Loading…
Reference in a new issue