@@ -6,13 +6,15 @@ use rustc_lint::LateContext;
6
6
use rustc_span:: { BytePos , Pos , Span } ;
7
7
use url:: Url ;
8
8
9
- use crate :: doc:: DOC_MARKDOWN ;
9
+ use crate :: doc:: { DOC_MARKDOWN , Fragments } ;
10
+ use std:: ops:: { ControlFlow , Range } ;
10
11
11
12
pub fn check (
12
13
cx : & LateContext < ' _ > ,
13
14
valid_idents : & FxHashSet < String > ,
14
15
text : & str ,
15
- span : Span ,
16
+ fragments : & Fragments < ' _ > ,
17
+ fragment_range : Range < usize > ,
16
18
code_level : isize ,
17
19
blockquote_level : isize ,
18
20
) {
@@ -64,23 +66,38 @@ pub fn check(
64
66
close_parens += 1 ;
65
67
}
66
68
67
- // Adjust for the current word
68
- let offset = word. as_ptr ( ) as usize - text. as_ptr ( ) as usize ;
69
- let span = Span :: new (
70
- span. lo ( ) + BytePos :: from_usize ( offset) ,
71
- span. lo ( ) + BytePos :: from_usize ( offset + word. len ( ) ) ,
72
- span. ctxt ( ) ,
73
- span. parent ( ) ,
74
- ) ;
69
+ // We'll use this offset to calculate the span to lint.
70
+ let fragment_offset = word. as_ptr ( ) as usize - text. as_ptr ( ) as usize ;
75
71
76
- check_word ( cx, word, span, code_level, blockquote_level) ;
72
+ // Adjust for the current word
73
+ if check_word (
74
+ cx,
75
+ word,
76
+ fragments,
77
+ & fragment_range,
78
+ fragment_offset,
79
+ code_level,
80
+ blockquote_level,
81
+ )
82
+ . is_break ( )
83
+ {
84
+ return ;
85
+ }
77
86
}
78
87
}
79
88
80
- fn check_word ( cx : & LateContext < ' _ > , word : & str , span : Span , code_level : isize , blockquote_level : isize ) {
89
+ fn check_word (
90
+ cx : & LateContext < ' _ > ,
91
+ word : & str ,
92
+ fragments : & Fragments < ' _ > ,
93
+ range : & Range < usize > ,
94
+ fragment_offset : usize ,
95
+ code_level : isize ,
96
+ blockquote_level : isize ,
97
+ ) -> ControlFlow < ( ) > {
81
98
/// Checks if a string is upper-camel-case, i.e., starts with an uppercase and
82
99
/// contains at least two uppercase letters (`Clippy` is ok) and one lower-case
83
- /// letter (`NASA` is ok).
100
+ /// letter (`NASA` is ok).[
84
101
/// Plurals are also excluded (`IDs` is ok).
85
102
fn is_camel_case ( s : & str ) -> bool {
86
103
if s. starts_with ( |c : char | c. is_ascii_digit ( ) | c. is_ascii_lowercase ( ) ) {
@@ -117,6 +134,17 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b
117
134
// try to get around the fact that `foo::bar` parses as a valid URL
118
135
&& !url. cannot_be_a_base ( )
119
136
{
137
+ let Some ( fragment_span) = fragments. span ( cx, range. clone ( ) ) else {
138
+ return ControlFlow :: Break ( ( ) ) ;
139
+ } ;
140
+
141
+ let span = Span :: new (
142
+ fragment_span. lo ( ) + BytePos :: from_usize ( fragment_offset) ,
143
+ fragment_span. lo ( ) + BytePos :: from_usize ( fragment_offset + word. len ( ) ) ,
144
+ fragment_span. ctxt ( ) ,
145
+ fragment_span. parent ( ) ,
146
+ ) ;
147
+
120
148
span_lint_and_sugg (
121
149
cx,
122
150
DOC_MARKDOWN ,
@@ -126,17 +154,28 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b
126
154
format ! ( "<{word}>" ) ,
127
155
Applicability :: MachineApplicable ,
128
156
) ;
129
- return ;
157
+ return ControlFlow :: Continue ( ( ) ) ;
130
158
}
131
159
132
160
// We assume that mixed-case words are not meant to be put inside backticks. (Issue #2343)
133
161
//
134
162
// We also assume that backticks are not necessary if inside a quote. (Issue #10262)
135
163
if code_level > 0 || blockquote_level > 0 || ( has_underscore ( word) && has_hyphen ( word) ) {
136
- return ;
164
+ return ControlFlow :: Break ( ( ) ) ;
137
165
}
138
166
139
167
if has_underscore ( word) || word. contains ( "::" ) || is_camel_case ( word) || word. ends_with ( "()" ) {
168
+ let Some ( fragment_span) = fragments. span ( cx, range. clone ( ) ) else {
169
+ return ControlFlow :: Break ( ( ) ) ;
170
+ } ;
171
+
172
+ let span = Span :: new (
173
+ fragment_span. lo ( ) + BytePos :: from_usize ( fragment_offset) ,
174
+ fragment_span. lo ( ) + BytePos :: from_usize ( fragment_offset + word. len ( ) ) ,
175
+ fragment_span. ctxt ( ) ,
176
+ fragment_span. parent ( ) ,
177
+ ) ;
178
+
140
179
span_lint_and_then (
141
180
cx,
142
181
DOC_MARKDOWN ,
@@ -149,4 +188,5 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span, code_level: isize, b
149
188
} ,
150
189
) ;
151
190
}
191
+ ControlFlow :: Continue ( ( ) )
152
192
}
0 commit comments