1
- use rustc_ast:: token:: Delimiter ;
1
+ use rustc_ast:: token:: { self , Delimiter } ;
2
+ use rustc_ast_pretty:: pprust;
2
3
use rustc_errors:: Diag ;
4
+ use rustc_session:: parse:: ParseSess ;
3
5
use rustc_span:: Span ;
4
6
use rustc_span:: source_map:: SourceMap ;
5
7
6
8
use super :: UnmatchedDelim ;
9
+ use crate :: errors:: MismatchedClosingDelimiter ;
7
10
8
11
#[ derive( Default ) ]
9
12
pub ( super ) struct TokenTreeDiagInfo {
13
+ /// record span of `(` for diagnostic
14
+ pub open_parens : Vec < Span > ,
15
+ /// record span of `{` for diagnostic
16
+ pub open_braces : Vec < Span > ,
17
+ /// record span of `[` for diagnostic
18
+ pub open_brackets : Vec < Span > ,
19
+
10
20
/// Stack of open delimiters and their spans. Used for error message.
11
21
pub open_delimiters : Vec < ( Delimiter , Span ) > ,
12
22
pub unmatched_delims : Vec < UnmatchedDelim > ,
@@ -22,13 +32,58 @@ pub(super) struct TokenTreeDiagInfo {
22
32
pub matching_block_spans : Vec < ( Span , Span ) > ,
23
33
}
24
34
35
+ impl TokenTreeDiagInfo {
36
+ pub ( super ) fn push_open_delimiter ( & mut self , delim : Delimiter , span : Span ) {
37
+ self . open_delimiters . push ( ( delim, span) ) ;
38
+ match delim {
39
+ Delimiter :: Parenthesis => self . open_parens . push ( span) ,
40
+ Delimiter :: Brace => self . open_braces . push ( span) ,
41
+ Delimiter :: Bracket => self . open_brackets . push ( span) ,
42
+ _ => { }
43
+ }
44
+ }
45
+
46
+ pub ( super ) fn pop_open_delimiter ( & mut self ) -> Option < ( Delimiter , Span ) > {
47
+ let ( delim, span) = self . open_delimiters . pop ( ) ?;
48
+ match delim {
49
+ Delimiter :: Parenthesis => self . open_parens . pop ( ) ,
50
+ Delimiter :: Brace => self . open_braces . pop ( ) ,
51
+ Delimiter :: Bracket => self . open_brackets . pop ( ) ,
52
+ _ => unreachable ! ( ) ,
53
+ } ;
54
+ Some ( ( delim, span) )
55
+ }
56
+ }
57
+
25
58
pub ( super ) fn same_indentation_level ( sm : & SourceMap , open_sp : Span , close_sp : Span ) -> bool {
26
59
match ( sm. span_to_margin ( open_sp) , sm. span_to_margin ( close_sp) ) {
27
60
( Some ( open_padding) , Some ( close_padding) ) => open_padding == close_padding,
28
61
_ => false ,
29
62
}
30
63
}
31
64
65
+ pub ( crate ) fn make_unclosed_delims_error (
66
+ unmatched : UnmatchedDelim ,
67
+ psess : & ParseSess ,
68
+ ) -> Option < Diag < ' _ > > {
69
+ // `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to
70
+ // `unmatched_delims` only for error recovery in the `Parser`.
71
+ let found_delim = unmatched. found_delim ?;
72
+ let mut spans = vec ! [ unmatched. found_span] ;
73
+ if let Some ( sp) = unmatched. unclosed_span {
74
+ spans. push ( sp) ;
75
+ } ;
76
+ let mut err = psess. dcx ( ) . create_err ( MismatchedClosingDelimiter {
77
+ spans,
78
+ delimiter : pprust:: token_kind_to_string ( & token:: CloseDelim ( found_delim) ) . to_string ( ) ,
79
+ unmatched : unmatched. found_span ,
80
+ opening_candidate : unmatched. candidate_span ,
81
+ unclosed : unmatched. unclosed_span ,
82
+ } ) ;
83
+ report_missing_open_delim ( & mut err, & [ unmatched] ) ;
84
+ Some ( err)
85
+ }
86
+
32
87
// When we get a `)` or `]` for `{`, we should emit help message here
33
88
// it's more friendly compared to report `unmatched error` in later phase
34
89
fn report_missing_open_delim ( err : & mut Diag < ' _ > , unmatched_delims : & [ UnmatchedDelim ] ) -> bool {
@@ -58,10 +113,6 @@ pub(super) fn report_suspicious_mismatch_block(
58
113
sm : & SourceMap ,
59
114
delim : Delimiter ,
60
115
) {
61
- if report_missing_open_delim ( err, & diag_info. unmatched_delims ) {
62
- return ;
63
- }
64
-
65
116
let mut matched_spans: Vec < ( Span , bool ) > = diag_info
66
117
. matching_block_spans
67
118
. iter ( )
0 commit comments