@@ -3,9 +3,10 @@ use itertools::Itertools;
33use rustc_errors:: Applicability ;
44use rustc_lint:: LateContext ;
55use rustc_span:: { BytePos , Span } ;
6+ use std:: cmp:: Ordering ;
67use std:: ops:: Range ;
78
8- use super :: DOC_LAZY_CONTINUATION ;
9+ use super :: { DOC_LAZY_CONTINUATION , DOC_OVERINDENTED_LIST_ITEMS } ;
910
1011fn map_container_to_text ( c : & super :: Container ) -> & ' static str {
1112 match c {
@@ -28,12 +29,57 @@ pub(super) fn check(
2829 return ;
2930 }
3031
32+ // Blockquote
3133 let ccount = doc[ range. clone ( ) ] . chars ( ) . filter ( |c| * c == '>' ) . count ( ) ;
3234 let blockquote_level = containers
3335 . iter ( )
3436 . filter ( |c| matches ! ( c, super :: Container :: Blockquote ) )
3537 . count ( ) ;
36- let lcount = doc[ range. clone ( ) ] . chars ( ) . filter ( |c| * c == ' ' ) . count ( ) ;
38+ if ccount < blockquote_level {
39+ span_lint_and_then (
40+ cx,
41+ DOC_LAZY_CONTINUATION ,
42+ span,
43+ "doc quote line without `>` marker" ,
44+ |diag| {
45+ let mut doc_start_range = & doc[ range] ;
46+ let mut suggested = String :: new ( ) ;
47+ for c in containers {
48+ let text = map_container_to_text ( c) ;
49+ if doc_start_range. starts_with ( text) {
50+ doc_start_range = & doc_start_range[ text. len ( ) ..] ;
51+ span = span. with_lo (
52+ span. lo ( ) + BytePos ( u32:: try_from ( text. len ( ) ) . expect ( "text is not 2**32 or bigger" ) ) ,
53+ ) ;
54+ } else if matches ! ( c, super :: Container :: Blockquote )
55+ && let Some ( i) = doc_start_range. find ( '>' )
56+ {
57+ doc_start_range = & doc_start_range[ i + 1 ..] ;
58+ span = span
59+ . with_lo ( span. lo ( ) + BytePos ( u32:: try_from ( i) . expect ( "text is not 2**32 or bigger" ) + 1 ) ) ;
60+ } else {
61+ suggested. push_str ( text) ;
62+ }
63+ }
64+ diag. span_suggestion_verbose (
65+ span,
66+ "add markers to start of line" ,
67+ suggested,
68+ Applicability :: MachineApplicable ,
69+ ) ;
70+ diag. help ( "if this not intended to be a quote at all, escape it with `\\ >`" ) ;
71+ } ,
72+ ) ;
73+ return ;
74+ }
75+
76+ if ccount != 0 && blockquote_level != 0 {
77+ // If this doc is a blockquote, we don't go further.
78+ return ;
79+ }
80+
81+ // List
82+ let leading_spaces = doc[ range] . chars ( ) . filter ( |c| * c == ' ' ) . count ( ) ;
3783 let list_indentation = containers
3884 . iter ( )
3985 . map ( |c| {
@@ -44,50 +90,38 @@ pub(super) fn check(
4490 }
4591 } )
4692 . sum ( ) ;
47- if ccount < blockquote_level || lcount < list_indentation {
48- let msg = if ccount < blockquote_level {
49- "doc quote line without `>` marker"
50- } else {
51- "doc list item without indentation"
52- } ;
53- span_lint_and_then ( cx, DOC_LAZY_CONTINUATION , span, msg, |diag| {
54- if ccount == 0 && blockquote_level == 0 {
93+ match leading_spaces. cmp ( & list_indentation) {
94+ Ordering :: Less => span_lint_and_then (
95+ cx,
96+ DOC_LAZY_CONTINUATION ,
97+ span,
98+ "doc list item without indentation" ,
99+ |diag| {
55100 // simpler suggestion style for indentation
56- let indent = list_indentation - lcount ;
101+ let indent = list_indentation - leading_spaces ;
57102 diag. span_suggestion_verbose (
58103 span. shrink_to_hi ( ) ,
59104 "indent this line" ,
60105 std:: iter:: repeat ( " " ) . take ( indent) . join ( "" ) ,
61106 Applicability :: MaybeIncorrect ,
62107 ) ;
63108 diag. help ( "if this is supposed to be its own paragraph, add a blank line" ) ;
64- return ;
65- }
66- let mut doc_start_range = & doc[ range] ;
67- let mut suggested = String :: new ( ) ;
68- for c in containers {
69- let text = map_container_to_text ( c) ;
70- if doc_start_range. starts_with ( text) {
71- doc_start_range = & doc_start_range[ text. len ( ) ..] ;
72- span = span
73- . with_lo ( span. lo ( ) + BytePos ( u32:: try_from ( text. len ( ) ) . expect ( "text is not 2**32 or bigger" ) ) ) ;
74- } else if matches ! ( c, super :: Container :: Blockquote )
75- && let Some ( i) = doc_start_range. find ( '>' )
76- {
77- doc_start_range = & doc_start_range[ i + 1 ..] ;
78- span =
79- span. with_lo ( span. lo ( ) + BytePos ( u32:: try_from ( i) . expect ( "text is not 2**32 or bigger" ) + 1 ) ) ;
80- } else {
81- suggested. push_str ( text) ;
82- }
83- }
84- diag. span_suggestion_verbose (
85- span,
86- "add markers to start of line" ,
87- suggested,
88- Applicability :: MachineApplicable ,
89- ) ;
90- diag. help ( "if this not intended to be a quote at all, escape it with `\\ >`" ) ;
91- } ) ;
109+ } ,
110+ ) ,
111+ Ordering :: Greater => span_lint_and_then (
112+ cx,
113+ DOC_OVERINDENTED_LIST_ITEMS ,
114+ span,
115+ "doc list item overindented" ,
116+ |diag| {
117+ diag. span_suggestion_verbose (
118+ span,
119+ "remove unnecessary spaces" ,
120+ std:: iter:: repeat ( " " ) . take ( list_indentation) . join ( "" ) ,
121+ Applicability :: MaybeIncorrect ,
122+ ) ;
123+ } ,
124+ ) ,
125+ Ordering :: Equal => { } ,
92126 }
93127}
0 commit comments