2 use crate::parse
::{PResult, source_file_to_stream}
;
3 use crate::parse
::new_parser_from_source_str
;
4 use crate::parse
::parser
::Parser
;
5 use crate::sess
::ParseSess
;
6 use crate::source_map
::{SourceMap, FilePathMapping}
;
7 use crate::tokenstream
::TokenStream
;
8 use crate::with_default_globals
;
10 use errors
::emitter
::EmitterWriter
;
12 use rustc_data_structures
::sync
::Lrc
;
13 use syntax_pos
::{BytePos, Span, MultiSpan}
;
16 use std
::io
::prelude
::*;
17 use std
::iter
::Peekable
;
18 use std
::path
::{Path, PathBuf}
;
20 use std
::sync
::{Arc, Mutex}
;
22 /// Map string to parser (via tts).
23 fn string_to_parser(ps
: &ParseSess
, source_str
: String
) -> Parser
<'_
> {
24 new_parser_from_source_str(ps
, PathBuf
::from("bogofile").into(), source_str
)
27 crate fn with_error_checking_parse
<'a
, T
, F
>(s
: String
, ps
: &'a ParseSess
, f
: F
) -> T
where
28 F
: FnOnce(&mut Parser
<'a
>) -> PResult
<'a
, T
>,
30 let mut p
= string_to_parser(&ps
, s
);
31 let x
= f(&mut p
).unwrap();
32 p
.sess
.span_diagnostic
.abort_if_errors();
36 /// Maps a string to tts, using a made-up filename.
37 crate fn string_to_stream(source_str
: String
) -> TokenStream
{
38 let ps
= ParseSess
::new(FilePathMapping
::empty());
39 source_file_to_stream(
41 ps
.source_map().new_source_file(PathBuf
::from("bogofile").into(),
46 /// Parses a string, returns a crate.
47 crate fn string_to_crate(source_str
: String
) -> ast
::Crate
{
48 let ps
= ParseSess
::new(FilePathMapping
::empty());
49 with_error_checking_parse(source_str
, &ps
, |p
| {
54 /// Does the given string match the pattern? whitespace in the first string
55 /// may be deleted or replaced with other whitespace to match the pattern.
56 /// This function is relatively Unicode-ignorant; fortunately, the careful design
57 /// of UTF-8 mitigates this ignorance. It doesn't do NKF-normalization(?).
58 crate fn matches_codepattern(a
: &str, b
: &str) -> bool
{
59 let mut a_iter
= a
.chars().peekable();
60 let mut b_iter
= b
.chars().peekable();
63 let (a
, b
) = match (a_iter
.peek(), b_iter
.peek()) {
64 (None
, None
) => return true,
65 (None
, _
) => return false,
67 if rustc_lexer
::is_whitespace(a
) {
68 break // Trailing whitespace check is out of loop for borrowck.
73 (Some(&a
), Some(&b
)) => (a
, b
)
76 if rustc_lexer
::is_whitespace(a
) && rustc_lexer
::is_whitespace(b
) {
77 // Skip whitespace for `a` and `b`.
78 scan_for_non_ws_or_end(&mut a_iter
);
79 scan_for_non_ws_or_end(&mut b_iter
);
80 } else if rustc_lexer
::is_whitespace(a
) {
81 // Skip whitespace for `a`.
82 scan_for_non_ws_or_end(&mut a_iter
);
91 // Check if a has *only* trailing whitespace.
92 a_iter
.all(rustc_lexer
::is_whitespace
)
95 /// Advances the given peekable `Iterator` until it reaches a non-whitespace character.
96 fn scan_for_non_ws_or_end
<I
: Iterator
<Item
= char>>(iter
: &mut Peekable
<I
>) {
97 while iter
.peek().copied().map(|c
| rustc_lexer
::is_whitespace(c
)) == Some(true) {
102 /// Identifies a position in the text by the n'th occurrence of a string.
104 string
: &'
static str,
114 crate struct Shared
<T
: Write
> {
115 pub data
: Arc
<Mutex
<T
>>,
118 impl<T
: Write
> Write
for Shared
<T
> {
119 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> {
120 self.data
.lock().unwrap().write(buf
)
123 fn flush(&mut self) -> io
::Result
<()> {
124 self.data
.lock().unwrap().flush()
128 fn test_harness(file_text
: &str, span_labels
: Vec
<SpanLabel
>, expected_output
: &str) {
129 with_default_globals(|| {
130 let output
= Arc
::new(Mutex
::new(Vec
::new()));
132 let source_map
= Lrc
::new(SourceMap
::new(FilePathMapping
::empty()));
133 source_map
.new_source_file(Path
::new("test.rs").to_owned().into(), file_text
.to_owned());
135 let primary_span
= make_span(&file_text
, &span_labels
[0].start
, &span_labels
[0].end
);
136 let mut msp
= MultiSpan
::from_span(primary_span
);
137 for span_label
in span_labels
{
138 let span
= make_span(&file_text
, &span_label
.start
, &span_label
.end
);
139 msp
.push_span_label(span
, span_label
.label
.to_string());
140 println
!("span: {:?} label: {:?}", span
, span_label
.label
);
141 println
!("text: {:?}", source_map
.span_to_snippet(span
));
144 let emitter
= EmitterWriter
::new(
145 Box
::new(Shared { data: output.clone() }
),
146 Some(source_map
.clone()),
153 let handler
= Handler
::with_emitter(true, None
, Box
::new(emitter
));
154 handler
.span_err(msp
, "foo");
156 assert
!(expected_output
.chars().next() == Some('
\n'
),
157 "expected output should begin with newline");
158 let expected_output
= &expected_output
[1..];
160 let bytes
= output
.lock().unwrap();
161 let actual_output
= str::from_utf8(&bytes
).unwrap();
162 println
!("expected output:\n------\n{}------", expected_output
);
163 println
!("actual output:\n------\n{}------", actual_output
);
165 assert
!(expected_output
== actual_output
)
169 fn make_span(file_text
: &str, start
: &Position
, end
: &Position
) -> Span
{
170 let start
= make_pos(file_text
, start
);
171 let end
= make_pos(file_text
, end
) + end
.string
.len(); // just after matching thing ends
172 assert
!(start
<= end
);
173 Span
::with_root_ctxt(BytePos(start
as u32), BytePos(end
as u32))
176 fn make_pos(file_text
: &str, pos
: &Position
) -> usize {
177 let mut remainder
= file_text
;
179 for _
in 0..pos
.count
{
180 if let Some(n
) = remainder
.find(&pos
.string
) {
182 remainder
= &remainder
[n
+ 1..];
184 panic
!("failed to find {} instances of {:?} in {:?}",
277 label
: "`X` is a good letter",
288 label
: "`Y` is a good letter too",
301 | ||____^__- `Y` is a good letter too
303 | `X` is a good letter
326 label
: "`X` is a good letter",
337 label
: "`Y` is a good letter too",
349 | ||____-__^ `X` is a good letter
351 | `Y` is a good letter too
357 fn different_overlap() {
376 label
: "`X` is a good letter",
387 label
: "`Y` is a good letter too",
399 | ||____^ `X` is a good letter
401 | |_____- `Y` is a good letter too
407 fn triple_overlap() {
425 label
: "`X` is a good letter",
436 label
: "`Y` is a good letter too",
461 | |||____^__-__- `Z` label
463 | |____| `Y` is a good letter too
464 | `X` is a good letter
470 fn triple_exact_overlap() {
488 label
: "`X` is a good letter",
499 label
: "`Y` is a good letter too",
522 | | `X` is a good letter
523 | |____`Y` is a good letter too
549 label
: "`X` is a good letter",
560 label
: "`Y` is a good letter too",
583 | | `X` is a good letter
585 | |____-______- `Y` is a good letter too
595 fn non_overlaping() {
614 label
: "`X` is a good letter",
625 label
: "`Y` is a good letter too",
634 | |____^ `X` is a good letter
638 | |__________- `Y` is a good letter too
644 fn overlaping_start_and_end() {
663 label
: "`X` is a good letter",
674 label
: "`Y` is a good letter too",
686 | | `X` is a good letter
689 | |___________- `Y` is a good letter too
695 fn multiple_labels_primary_without_message() {
722 label
: "`a` is a good letter",
741 | ----^^^^-^^-- `a` is a good letter
747 fn multiple_labels_secondary_without_message() {
763 label
: "`a` is a good letter",
782 | ^^^^-------^^ `a` is a good letter
788 fn multiple_labels_primary_without_message_2() {
804 label
: "`b` is a good letter",
836 | `b` is a good letter
842 fn multiple_labels_secondary_without_message_2() {
869 label
: "`b` is a good letter",
879 | `b` is a good letter
885 fn multiple_labels_secondary_without_message_3() {
901 label
: "`a` is a good letter",
922 | `a` is a good letter
928 fn multiple_labels_without_message() {
969 fn multiple_labels_without_message_2() {
1021 fn multiple_labels_with_message() {
1037 label
: "`a` is a good letter",
1048 label
: "`b` is a good letter",
1058 | | `b` is a good letter
1059 | `a` is a good letter
1065 fn single_label_with_message() {
1081 label
: "`a` is a good letter",
1089 | ^^^^^^^^^^^^^ `a` is a good letter
1095 fn single_label_without_message() {
1154 label
: "`X` is a good letter",
1165 label
: "`Y` is a good letter too",
1177 | | `X` is a good letter
1184 | |___________- `Y` is a good letter too
1190 fn long_snippet_multiple_spans() {
1219 label
: "`Y` is a good letter",
1230 label
: "`Z` is a good letter too",
1248 | ||__________- `Z` is a good letter too
1252 | |_______^ `Y` is a good letter