@@ -9,6 +9,7 @@ use crate::parse::parser::Parser;
99use crate :: symbol:: Symbol ;
1010use crate :: tokenstream:: { TokenStream , TokenTree } ;
1111use crate :: diagnostics:: plugin:: ErrorMap ;
12+ use crate :: print:: pprust:: token_to_string;
1213
1314use rustc_data_structures:: sync:: { Lrc , Lock } ;
1415use syntax_pos:: { Span , SourceFile , FileName , MultiSpan } ;
@@ -136,15 +137,17 @@ pub fn parse_crate_attrs_from_source_str(name: FileName, source: String, sess: &
136137 new_parser_from_source_str ( sess, name, source) . parse_inner_attributes ( )
137138}
138139
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 > ) {
142146 source_file_to_stream ( sess, sess. source_map ( ) . new_source_file ( name, source) , override_span)
143147}
144148
145149/// 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 < ' _ > {
148151 panictry_buffer ! ( & sess. span_diagnostic, maybe_new_parser_from_source_str( sess, name, source) )
149152}
150153
@@ -195,12 +198,14 @@ fn source_file_to_parser(sess: &ParseSess, source_file: Lrc<SourceFile>) -> Pars
195198
196199/// Given a source_file and config, return a parser. Returns any buffered errors from lexing the
197200/// 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 > > {
201205 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;
204209 if parser. token == token:: Eof && parser. span . is_dummy ( ) {
205210 parser. span = Span :: new ( end_pos, end_pos, parser. span . ctxt ( ) ) ;
206211 }
@@ -247,25 +252,44 @@ fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
247252}
248253
249254/// 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 > ) {
253260 panictry_buffer ! ( & sess. span_diagnostic, maybe_file_to_stream( sess, source_file, override_span) )
254261}
255262
256263/// Given a source file, produce a sequence of token-trees. Returns any buffered errors from
257264/// 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 > > {
261270 let mut srdr = lexer:: StringReader :: new_or_buffered_errs ( sess, source_file, override_span) ?;
262271 srdr. real_token ( ) ;
263272
264273 match srdr. parse_all_token_trees ( ) {
265- Ok ( stream) => Ok ( stream) ,
274+ Ok ( stream) => Ok ( ( stream, srdr . unmatched_braces ) ) ,
266275 Err ( err) => {
267276 let mut buffer = Vec :: with_capacity ( 1 ) ;
268277 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+ }
269293 Err ( buffer)
270294 }
271295 }
0 commit comments