1- use rustc_ast:: token:: Delimiter ;
1+ use rustc_ast:: token:: { self , Delimiter } ;
2+ use rustc_ast_pretty:: pprust;
23use rustc_errors:: Diag ;
4+ use rustc_session:: parse:: ParseSess ;
35use rustc_span:: Span ;
46use rustc_span:: source_map:: SourceMap ;
57
68use super :: UnmatchedDelim ;
9+ use crate :: errors:: MismatchedClosingDelimiter ;
710
811#[ derive( Default ) ]
912pub ( 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+
1020 /// Stack of open delimiters and their spans. Used for error message.
1121 pub open_delimiters : Vec < ( Delimiter , Span ) > ,
1222 pub unmatched_delims : Vec < UnmatchedDelim > ,
@@ -22,13 +32,58 @@ pub(super) struct TokenTreeDiagInfo {
2232 pub matching_block_spans : Vec < ( Span , Span ) > ,
2333}
2434
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+
2558pub ( super ) fn same_indentation_level ( sm : & SourceMap , open_sp : Span , close_sp : Span ) -> bool {
2659 match ( sm. span_to_margin ( open_sp) , sm. span_to_margin ( close_sp) ) {
2760 ( Some ( open_padding) , Some ( close_padding) ) => open_padding == close_padding,
2861 _ => false ,
2962 }
3063}
3164
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+
3287// When we get a `)` or `]` for `{`, we should emit help message here
3388// it's more friendly compared to report `unmatched error` in later phase
3489fn report_missing_open_delim ( err : & mut Diag < ' _ > , unmatched_delims : & [ UnmatchedDelim ] ) -> bool {
@@ -58,10 +113,6 @@ pub(super) fn report_suspicious_mismatch_block(
58113 sm : & SourceMap ,
59114 delim : Delimiter ,
60115) {
61- if report_missing_open_delim ( err, & diag_info. unmatched_delims ) {
62- return ;
63- }
64-
65116 let mut matched_spans: Vec < ( Span , bool ) > = diag_info
66117 . matching_block_spans
67118 . iter ( )
0 commit comments