1
- use clippy_utils:: diagnostics:: span_lint_and_then;
1
+ use clippy_utils:: diagnostics:: { span_lint_and_sugg , span_lint_and_then} ;
2
2
use itertools:: Itertools ;
3
3
use rustc_errors:: Applicability ;
4
4
use rustc_lint:: LateContext ;
5
5
use rustc_span:: { BytePos , Span } ;
6
+ use std:: cmp:: Ordering ;
6
7
use std:: ops:: Range ;
7
8
8
- use super :: DOC_LAZY_CONTINUATION ;
9
+ use super :: { DOC_LAZY_CONTINUATION , DOC_OVERINDENTED_LIST_ITEMS } ;
9
10
10
11
fn map_container_to_text ( c : & super :: Container ) -> & ' static str {
11
12
match c {
@@ -28,12 +29,57 @@ pub(super) fn check(
28
29
return ;
29
30
}
30
31
32
+ // Blockquote
31
33
let ccount = doc[ range. clone ( ) ] . chars ( ) . filter ( |c| * c == '>' ) . count ( ) ;
32
34
let blockquote_level = containers
33
35
. iter ( )
34
36
. filter ( |c| matches ! ( c, super :: Container :: Blockquote ) )
35
37
. 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 ( ) ;
37
83
let list_indentation = containers
38
84
. iter ( )
39
85
. map ( |c| {
@@ -44,50 +90,36 @@ pub(super) fn check(
44
90
}
45
91
} )
46
92
. 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| {
55
100
// simpler suggestion style for indentation
56
- let indent = list_indentation - lcount ;
101
+ let indent = list_indentation - leading_spaces ;
57
102
diag. span_suggestion_verbose (
58
103
span. shrink_to_hi ( ) ,
59
104
"indent this line" ,
60
105
std:: iter:: repeat_n ( " " , indent) . join ( "" ) ,
61
106
Applicability :: MaybeIncorrect ,
62
107
) ;
63
108
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 (
109
+ } ,
110
+ ) ,
111
+ Ordering :: Greater => {
112
+ let sugg = std:: iter:: repeat_n ( " " , list_indentation) . join ( "" ) ;
113
+ span_lint_and_sugg (
114
+ cx,
115
+ DOC_OVERINDENTED_LIST_ITEMS ,
85
116
span,
86
- "add markers to start of line" ,
87
- suggested,
88
- Applicability :: MachineApplicable ,
117
+ "doc list item overindented" ,
118
+ format ! ( "try using `{sugg}` ({list_indentation} spaces)" ) ,
119
+ sugg,
120
+ Applicability :: MaybeIncorrect ,
89
121
) ;
90
- diag . help ( "if this not intended to be a quote at all, escape it with ` \\ >`" ) ;
91
- } ) ;
122
+ } ,
123
+ Ordering :: Equal => { } ,
92
124
}
93
125
}
0 commit comments