@@ -9,6 +9,7 @@ use crate::parse::parser::Parser;
9
9
use crate :: symbol:: Symbol ;
10
10
use crate :: tokenstream:: { TokenStream , TokenTree } ;
11
11
use crate :: diagnostics:: plugin:: ErrorMap ;
12
+ use crate :: print:: pprust:: token_to_string;
12
13
13
14
use rustc_data_structures:: sync:: { Lrc , Lock } ;
14
15
use syntax_pos:: { Span , SourceFile , FileName , MultiSpan } ;
@@ -136,15 +137,17 @@ pub fn parse_crate_attrs_from_source_str(name: FileName, source: String, sess: &
136
137
new_parser_from_source_str ( sess, name, source) . parse_inner_attributes ( )
137
138
}
138
139
139
- pub fn parse_stream_from_source_str ( name : FileName , source : String , sess : & ParseSess ,
140
- override_span : Option < Span > )
141
- -> TokenStream {
140
+ pub fn parse_stream_from_source_str (
141
+ name : FileName ,
142
+ source : String ,
143
+ sess : & ParseSess ,
144
+ override_span : Option < Span > ,
145
+ ) -> ( TokenStream , Vec < lexer:: UnmatchedBrace > ) {
142
146
source_file_to_stream ( sess, sess. source_map ( ) . new_source_file ( name, source) , override_span)
143
147
}
144
148
145
149
/// Create a new parser from a source string
146
- pub fn new_parser_from_source_str ( sess : & ParseSess , name : FileName , source : String )
147
- -> Parser < ' _ > {
150
+ pub fn new_parser_from_source_str ( sess : & ParseSess , name : FileName , source : String ) -> Parser < ' _ > {
148
151
panictry_buffer ! ( & sess. span_diagnostic, maybe_new_parser_from_source_str( sess, name, source) )
149
152
}
150
153
@@ -195,12 +198,14 @@ fn source_file_to_parser(sess: &ParseSess, source_file: Lrc<SourceFile>) -> Pars
195
198
196
199
/// Given a source_file and config, return a parser. Returns any buffered errors from lexing the
197
200
/// initial token stream.
198
- fn maybe_source_file_to_parser ( sess : & ParseSess , source_file : Lrc < SourceFile > )
199
- -> Result < Parser < ' _ > , Vec < Diagnostic > >
200
- {
201
+ fn maybe_source_file_to_parser (
202
+ sess : & ParseSess ,
203
+ source_file : Lrc < SourceFile > ,
204
+ ) -> Result < Parser < ' _ > , Vec < Diagnostic > > {
201
205
let end_pos = source_file. end_pos ;
202
- let mut parser = stream_to_parser ( sess, maybe_file_to_stream ( sess, source_file, None ) ?) ;
203
-
206
+ let ( stream, unclosed_delims) = maybe_file_to_stream ( sess, source_file, None ) ?;
207
+ let mut parser = stream_to_parser ( sess, stream) ;
208
+ parser. unclosed_delims = unclosed_delims;
204
209
if parser. token == token:: Eof && parser. span . is_dummy ( ) {
205
210
parser. span = Span :: new ( end_pos, end_pos, parser. span . ctxt ( ) ) ;
206
211
}
@@ -247,25 +252,44 @@ fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
247
252
}
248
253
249
254
/// Given a source_file, produce a sequence of token-trees
250
- pub fn source_file_to_stream ( sess : & ParseSess ,
251
- source_file : Lrc < SourceFile > ,
252
- override_span : Option < Span > ) -> TokenStream {
255
+ pub fn source_file_to_stream (
256
+ sess : & ParseSess ,
257
+ source_file : Lrc < SourceFile > ,
258
+ override_span : Option < Span > ,
259
+ ) -> ( TokenStream , Vec < lexer:: UnmatchedBrace > ) {
253
260
panictry_buffer ! ( & sess. span_diagnostic, maybe_file_to_stream( sess, source_file, override_span) )
254
261
}
255
262
256
263
/// Given a source file, produce a sequence of token-trees. Returns any buffered errors from
257
264
/// parsing the token tream.
258
- pub fn maybe_file_to_stream ( sess : & ParseSess ,
259
- source_file : Lrc < SourceFile > ,
260
- override_span : Option < Span > ) -> Result < TokenStream , Vec < Diagnostic > > {
265
+ pub fn maybe_file_to_stream (
266
+ sess : & ParseSess ,
267
+ source_file : Lrc < SourceFile > ,
268
+ override_span : Option < Span > ,
269
+ ) -> Result < ( TokenStream , Vec < lexer:: UnmatchedBrace > ) , Vec < Diagnostic > > {
261
270
let mut srdr = lexer:: StringReader :: new_or_buffered_errs ( sess, source_file, override_span) ?;
262
271
srdr. real_token ( ) ;
263
272
264
273
match srdr. parse_all_token_trees ( ) {
265
- Ok ( stream) => Ok ( stream) ,
274
+ Ok ( stream) => Ok ( ( stream, srdr . unmatched_braces ) ) ,
266
275
Err ( err) => {
267
276
let mut buffer = Vec :: with_capacity ( 1 ) ;
268
277
err. buffer ( & mut buffer) ;
278
+ // Not using `emit_unclosed_delims` to use `db.buffer`
279
+ for unmatched in srdr. unmatched_braces {
280
+ let mut db = sess. span_diagnostic . struct_span_err ( unmatched. found_span , & format ! (
281
+ "incorrect close delimiter: `{}`" ,
282
+ token_to_string( & token:: Token :: CloseDelim ( unmatched. found_delim) ) ,
283
+ ) ) ;
284
+ db. span_label ( unmatched. found_span , "incorrect close delimiter" ) ;
285
+ if let Some ( sp) = unmatched. candidate_span {
286
+ db. span_label ( sp, "close delimiter possibly meant for this" ) ;
287
+ }
288
+ if let Some ( sp) = unmatched. unclosed_span {
289
+ db. span_label ( sp, "un-closed delimiter" ) ;
290
+ }
291
+ db. buffer ( & mut buffer) ;
292
+ }
269
293
Err ( buffer)
270
294
}
271
295
}
0 commit comments