Skip to content

Commit fd1f908

Browse files
stepanchegfacebook-github-bot
authored andcommitted
span_display utility
Summary: Extract from `Diagnostic` to use in the following diff D48941531. Reviewed By: IanChilds Differential Revision: D48940978 fbshipit-source-id: f708b4a2993119cfc57e14489bd59b946fd63cb0
1 parent 76a9d40 commit fd1f908

File tree

4 files changed

+98
-58
lines changed

4 files changed

+98
-58
lines changed

starlark_syntax/src/codemap.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,11 @@ impl<'a> FileSpanRef<'a> {
468468
pub fn resolve_span(&self) -> ResolvedSpan {
469469
self.file.resolve_span(self.span)
470470
}
471+
472+
/// Resolve the span.
473+
pub fn source_span(self) -> &'a str {
474+
self.file.source_span(self.span)
475+
}
471476
}
472477

473478
impl FileSpan {
@@ -485,7 +490,7 @@ impl FileSpan {
485490

486491
/// Resolve the span.
487492
pub fn source_span(&self) -> &str {
488-
self.file.source_span(self.span)
493+
self.as_ref().source_span()
489494
}
490495

491496
/// Cheap reference to the span.

starlark_syntax/src/diagnostic.rs

Lines changed: 7 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,11 @@ use std::fmt;
2020
use std::fmt::Display;
2121
use std::fmt::Formatter;
2222

23-
use annotate_snippets::display_list::DisplayList;
24-
use annotate_snippets::display_list::FormatOptions;
25-
use annotate_snippets::snippet::Annotation;
26-
use annotate_snippets::snippet::AnnotationType;
27-
use annotate_snippets::snippet::Slice;
28-
use annotate_snippets::snippet::Snippet;
29-
use annotate_snippets::snippet::SourceAnnotation;
30-
3123
use crate::call_stack::CallStack;
3224
use crate::codemap::CodeMap;
3325
use crate::codemap::FileSpan;
3426
use crate::codemap::Span;
35-
use crate::fast_string;
27+
use crate::span_display::span_display;
3628

3729
/// An error plus its origination location and call stack.
3830
///
@@ -126,54 +118,12 @@ impl Diagnostic {
126118
}
127119

128120
/// Gets annotated snippets for a [`Diagnostic`].
129-
fn get_display_list<'a>(&'a self, annotation_label: &'a str, color: bool) -> DisplayList<'a> {
130-
fn convert_span_to_slice<'a>(span: &'a FileSpan) -> Slice<'a> {
131-
let region = span.resolve_span();
132-
133-
// we want the source_span to capture any whitespace ahead of the diagnostic span to
134-
// get the column numbers correct in the DisplayList, and any trailing source code
135-
// on the last line for context.
136-
let first_line_span = span.file.line_span(region.begin.line);
137-
let last_line_span = span.file.line_span(region.end.line);
138-
let source_span = span.span.merge(first_line_span).merge(last_line_span);
139-
let source = span.file.source_span(source_span);
140-
141-
// We want to highlight the span, which needs to be relative to source, and in
142-
// characters.
143-
// Our spans are in terms of bytes, but our resolved spans in terms of characters.
144-
let range_start_chars = region.begin.column;
145-
let range_len_chars = fast_string::len(span.source_span()).0;
146-
147-
Slice {
148-
source,
149-
line_start: 1 + region.begin.line,
150-
origin: Some(span.file.filename()),
151-
fold: false,
152-
annotations: vec![SourceAnnotation {
153-
label: "",
154-
annotation_type: AnnotationType::Error,
155-
range: (range_start_chars, range_start_chars + range_len_chars),
156-
}],
157-
}
158-
}
159-
160-
let slice = self.span.as_ref().map(convert_span_to_slice);
161-
162-
let snippet = Snippet {
163-
title: Some(Annotation {
164-
label: Some(annotation_label),
165-
id: None,
166-
annotation_type: AnnotationType::Error,
167-
}),
168-
footer: Vec::new(),
169-
slices: slice.map(|s| vec![s]).unwrap_or_default(),
170-
opt: FormatOptions {
171-
color,
172-
..Default::default()
173-
},
174-
};
175-
176-
DisplayList::from(snippet)
121+
fn get_display_list<'a>(&'a self, annotation_label: &'a str, color: bool) -> impl Display + 'a {
122+
span_display(
123+
self.span.as_ref().map(|s| s.as_ref()),
124+
annotation_label,
125+
color,
126+
)
177127
}
178128
}
179129

starlark_syntax/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,5 @@ pub mod lexer;
3838
#[cfg(test)]
3939
mod lexer_tests;
4040
pub mod slice_vec_ext;
41+
pub(crate) mod span_display;
4142
pub mod syntax;

starlark_syntax/src/span_display.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Copyright 2019 The Starlark in Rust Authors.
3+
* Copyright (c) Facebook, Inc. and its affiliates.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
use std::fmt::Display;
19+
20+
use annotate_snippets::display_list::DisplayList;
21+
use annotate_snippets::display_list::FormatOptions;
22+
use annotate_snippets::snippet::Annotation;
23+
use annotate_snippets::snippet::AnnotationType;
24+
use annotate_snippets::snippet::Slice;
25+
use annotate_snippets::snippet::Snippet;
26+
use annotate_snippets::snippet::SourceAnnotation;
27+
28+
use crate::codemap::FileSpanRef;
29+
use crate::fast_string;
30+
31+
/// Gets annotated snippets for a [`Diagnostic`].
32+
pub(crate) fn span_display<'a>(
33+
span: Option<FileSpanRef<'a>>,
34+
annotation_label: &'a str,
35+
color: bool,
36+
) -> impl Display + 'a {
37+
fn convert_span_to_slice<'a>(span: FileSpanRef<'a>) -> Slice<'a> {
38+
let region = span.resolve_span();
39+
40+
// we want the source_span to capture any whitespace ahead of the diagnostic span to
41+
// get the column numbers correct in the DisplayList, and any trailing source code
42+
// on the last line for context.
43+
let first_line_span = span.file.line_span(region.begin.line);
44+
let last_line_span = span.file.line_span(region.end.line);
45+
let source_span = span.span.merge(first_line_span).merge(last_line_span);
46+
let source = span.file.source_span(source_span);
47+
48+
// We want to highlight the span, which needs to be relative to source, and in
49+
// characters.
50+
// Our spans are in terms of bytes, but our resolved spans in terms of characters.
51+
let range_start_chars = region.begin.column;
52+
let range_len_chars = fast_string::len(span.source_span()).0;
53+
54+
Slice {
55+
source,
56+
line_start: 1 + region.begin.line,
57+
origin: Some(span.file.filename()),
58+
fold: false,
59+
annotations: vec![SourceAnnotation {
60+
label: "",
61+
annotation_type: AnnotationType::Error,
62+
range: (range_start_chars, range_start_chars + range_len_chars),
63+
}],
64+
}
65+
}
66+
67+
let slice = span.map(convert_span_to_slice);
68+
69+
let snippet = Snippet {
70+
title: Some(Annotation {
71+
label: Some(annotation_label),
72+
id: None,
73+
annotation_type: AnnotationType::Error,
74+
}),
75+
footer: Vec::new(),
76+
slices: slice.map(|s| vec![s]).unwrap_or_default(),
77+
opt: FormatOptions {
78+
color,
79+
..Default::default()
80+
},
81+
};
82+
83+
DisplayList::from(snippet)
84+
}

0 commit comments

Comments
 (0)