1
1
use super :: { StringReader , UnmatchedBrace } ;
2
2
3
- use rustc_ast:: token:: { self , Token } ;
3
+ use rustc_ast:: token:: { self , DelimToken , Token } ;
4
4
use rustc_ast:: tokenstream:: {
5
5
DelimSpan ,
6
6
IsJoint :: { self , * } ,
@@ -22,6 +22,7 @@ impl<'a> StringReader<'a> {
22
22
matching_delim_spans : Vec :: new ( ) ,
23
23
last_unclosed_found_span : None ,
24
24
last_delim_empty_block_spans : FxHashMap :: default ( ) ,
25
+ matching_block_spans : Vec :: new ( ) ,
25
26
} ;
26
27
let res = tt_reader. parse_all_token_trees ( ) ;
27
28
( res, tt_reader. unmatched_braces )
@@ -42,6 +43,9 @@ struct TokenTreesReader<'a> {
42
43
last_unclosed_found_span : Option < Span > ,
43
44
/// Collect empty block spans that might have been auto-inserted by editors.
44
45
last_delim_empty_block_spans : FxHashMap < token:: DelimToken , Span > ,
46
+ /// Collect the spans of braces (Open, Close). Used only
47
+ /// for detecting if blocks are empty and only braces.
48
+ matching_block_spans : Vec < ( Span , Span ) > ,
45
49
}
46
50
47
51
impl < ' a > TokenTreesReader < ' a > {
@@ -77,6 +81,7 @@ impl<'a> TokenTreesReader<'a> {
77
81
78
82
fn parse_token_tree ( & mut self ) -> PResult < ' a , TreeAndJoint > {
79
83
let sm = self . string_reader . sess . source_map ( ) ;
84
+
80
85
match self . token . kind {
81
86
token:: Eof => {
82
87
let msg = "this file contains an unclosed delimiter" ;
@@ -146,6 +151,14 @@ impl<'a> TokenTreesReader<'a> {
146
151
}
147
152
}
148
153
154
+ match ( open_brace, delim) {
155
+ //only add braces
156
+ ( DelimToken :: Brace , DelimToken :: Brace ) => {
157
+ self . matching_block_spans . push ( ( open_brace_span, close_brace_span) ) ;
158
+ }
159
+ _ => { }
160
+ }
161
+
149
162
if self . open_braces . is_empty ( ) {
150
163
// Clear up these spans to avoid suggesting them as we've found
151
164
// properly matched delimiters so far for an entire block.
@@ -164,6 +177,7 @@ impl<'a> TokenTreesReader<'a> {
164
177
token:: CloseDelim ( other) => {
165
178
let mut unclosed_delimiter = None ;
166
179
let mut candidate = None ;
180
+
167
181
if self . last_unclosed_found_span != Some ( self . token . span ) {
168
182
// do not complain about the same unclosed delimiter multiple times
169
183
self . last_unclosed_found_span = Some ( self . token . span ) ;
@@ -224,12 +238,27 @@ impl<'a> TokenTreesReader<'a> {
224
238
let mut err =
225
239
self . string_reader . sess . span_diagnostic . struct_span_err ( self . token . span , & msg) ;
226
240
227
- if let Some ( span) = self . last_delim_empty_block_spans . remove ( & delim) {
228
- err. span_label (
229
- span,
230
- "this block is empty, you might have not meant to close it" ,
231
- ) ;
241
+ // Braces are added at the end, so the last element is the biggest block
242
+ if let Some ( parent) = self . matching_block_spans . last ( ) {
243
+ if let Some ( span) = self . last_delim_empty_block_spans . remove ( & delim) {
244
+ // Check if the (empty block) is in the last properly closed block
245
+ if ( parent. 0 . to ( parent. 1 ) ) . contains ( span) {
246
+ err. span_label (
247
+ span,
248
+ "block is empty, you might have not meant to close it" ,
249
+ ) ;
250
+ } else {
251
+ err. span_label ( parent. 0 , "this opening brace..." ) ;
252
+
253
+ err. span_label ( parent. 1 , "...matches this closing brace" ) ;
254
+ }
255
+ } else {
256
+ err. span_label ( parent. 0 , "this opening brace..." ) ;
257
+
258
+ err. span_label ( parent. 1 , "...matches this closing brace" ) ;
259
+ }
232
260
}
261
+
233
262
err. span_label ( self . token . span , "unexpected closing delimiter" ) ;
234
263
Err ( err)
235
264
}
0 commit comments