Skip to content

Commit 4a7598f

Browse files
blyxyasollpu
andcommitted
[HEAVY PERF] Optimize documentation lints 2/2
So, after #14693 was merged, this is the continuation. It performs some optimizations on `Fragments::span` , makes it so we don't call it so much, and makes a 85.75% decrease (7.51% -> 10.07%) in execution samples of `source_span_for_markdown_range` and a 6.39% -> 0.88% for `core::StrSearcher::new`. Overall a 13.11% icount decrase on docs-heavy crates. Benchmarked mainly on `regex-1.10.5`. This means that currently our heaviest function is `rustc_middle::Interners::intern_ty`, even for documentation-heavy crates Co-authored-by: Roope Salmi <[email protected]>
1 parent 5dccb10 commit 4a7598f

File tree

2 files changed

+54
-52
lines changed

2 files changed

+54
-52
lines changed

clippy_lints/src/doc/lazy_continuation.rs

Lines changed: 45 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
22
use itertools::Itertools;
33
use rustc_errors::Applicability;
44
use rustc_lint::LateContext;
5-
use rustc_span::{BytePos, Span};
6-
use std::cmp::Ordering;
5+
use rustc_span::BytePos;
76
use std::ops::Range;
87

9-
use super::{DOC_LAZY_CONTINUATION, DOC_OVERINDENTED_LIST_ITEMS};
8+
use super::{DOC_LAZY_CONTINUATION, DOC_OVERINDENTED_LIST_ITEMS, Fragments};
109

1110
fn map_container_to_text(c: &super::Container) -> &'static str {
1211
match c {
@@ -19,29 +18,27 @@ fn map_container_to_text(c: &super::Container) -> &'static str {
1918
pub(super) fn check(
2019
cx: &LateContext<'_>,
2120
doc: &str,
22-
range: Range<usize>,
23-
mut span: Span,
21+
cooked_range: Range<usize>,
22+
fragments: &Fragments<'_>,
2423
containers: &[super::Container],
2524
) {
26-
if doc[range.clone()].contains('\t') {
27-
// We don't do tab stops correctly.
28-
return;
29-
}
30-
31-
// Blockquote
32-
let ccount = doc[range.clone()].chars().filter(|c| *c == '>').count();
25+
// Get blockquotes
26+
let ccount = doc[cooked_range.clone()].chars().filter(|c| *c == '>').count();
3327
let blockquote_level = containers
3428
.iter()
3529
.filter(|c| matches!(c, super::Container::Blockquote))
3630
.count();
37-
if ccount < blockquote_level {
31+
32+
if ccount < blockquote_level
33+
&& let Some(mut span) = fragments.span(cx, cooked_range.clone())
34+
{
3835
span_lint_and_then(
3936
cx,
4037
DOC_LAZY_CONTINUATION,
4138
span,
4239
"doc quote line without `>` marker",
4340
|diag| {
44-
let mut doc_start_range = &doc[range];
41+
let mut doc_start_range = &doc[cooked_range];
4542
let mut suggested = String::new();
4643
for c in containers {
4744
let text = map_container_to_text(c);
@@ -78,7 +75,7 @@ pub(super) fn check(
7875
}
7976

8077
// List
81-
let leading_spaces = doc[range].chars().filter(|c| *c == ' ').count();
78+
let leading_spaces = doc[cooked_range.clone()].chars().filter(|c| *c == ' ').count();
8279
let list_indentation = containers
8380
.iter()
8481
.map(|c| {
@@ -89,36 +86,41 @@ pub(super) fn check(
8986
}
9087
})
9188
.sum();
92-
match leading_spaces.cmp(&list_indentation) {
93-
Ordering::Less => span_lint_and_then(
94-
cx,
95-
DOC_LAZY_CONTINUATION,
96-
span,
97-
"doc list item without indentation",
98-
|diag| {
99-
// simpler suggestion style for indentation
100-
let indent = list_indentation - leading_spaces;
101-
diag.span_suggestion_verbose(
102-
span.shrink_to_hi(),
103-
"indent this line",
104-
std::iter::repeat_n(" ", indent).join(""),
105-
Applicability::MaybeIncorrect,
106-
);
107-
diag.help("if this is supposed to be its own paragraph, add a blank line");
108-
},
109-
),
110-
Ordering::Greater => {
111-
let sugg = std::iter::repeat_n(" ", list_indentation).join("");
112-
span_lint_and_sugg(
89+
90+
if leading_spaces != list_indentation
91+
&& let Some(span) = fragments.span(cx, cooked_range.clone())
92+
{
93+
if leading_spaces < list_indentation {
94+
span_lint_and_then(
11395
cx,
114-
DOC_OVERINDENTED_LIST_ITEMS,
96+
DOC_LAZY_CONTINUATION,
11597
span,
116-
"doc list item overindented",
117-
format!("try using `{sugg}` ({list_indentation} spaces)"),
118-
sugg,
119-
Applicability::MaybeIncorrect,
98+
"doc list item without indentation",
99+
|diag| {
100+
// simpler suggestion style for indentation
101+
let indent = list_indentation - leading_spaces;
102+
diag.span_suggestion_verbose(
103+
span.shrink_to_hi(),
104+
"indent this line",
105+
std::iter::repeat_n(" ", indent).join(""),
106+
Applicability::MaybeIncorrect,
107+
);
108+
diag.help("if this is supposed to be its own paragraph, add a blank line");
109+
},
120110
);
121-
},
122-
Ordering::Equal => {},
111+
112+
return;
113+
}
114+
115+
let sugg = std::iter::repeat_n(" ", list_indentation).join("");
116+
span_lint_and_sugg(
117+
cx,
118+
DOC_OVERINDENTED_LIST_ITEMS,
119+
span,
120+
"doc list item overindented",
121+
format!("try using `{sugg}` ({list_indentation} spaces)"),
122+
sugg,
123+
Applicability::MaybeIncorrect,
124+
);
123125
}
124126
}

clippy_lints/src/doc/mod.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
use clippy_config::Conf;
44
use clippy_utils::attrs::is_doc_hidden;
55
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then};
6-
use clippy_utils::source::snippet_opt;
76
use clippy_utils::{is_entrypoint_fn, is_trait_impl_item};
87
use pulldown_cmark::Event::{
98
Code, DisplayMath, End, FootnoteReference, HardBreak, Html, InlineHtml, InlineMath, Rule, SoftBreak, Start,
@@ -1082,26 +1081,27 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
10821081
| TaskListMarker(_) | Code(_) | Rule | InlineMath(..) | DisplayMath(..) => (),
10831082
SoftBreak | HardBreak => {
10841083
if !containers.is_empty()
1085-
&& let Some((next_event, next_range)) = events.peek()
1086-
&& let Some(next_span) = fragments.span(cx, next_range.clone())
1087-
&& let Some(span) = fragments.span(cx, range.clone())
10881084
&& !in_footnote_definition
1085+
// Tabs aren't handled correctly vvvv
1086+
&& !doc[range.clone()].contains('\t')
1087+
&& let Some((next_event, next_range)) = events.peek()
10891088
&& !matches!(next_event, End(_))
10901089
{
10911090
lazy_continuation::check(
10921091
cx,
10931092
doc,
10941093
range.end..next_range.start,
1095-
Span::new(span.hi(), next_span.lo(), span.ctxt(), span.parent()),
1094+
&fragments,
10961095
&containers[..],
10971096
);
10981097
}
10991098

1100-
if let Some(span) = fragments.span(cx, range.clone())
1099+
1100+
if event == HardBreak
1101+
&& !doc[range.clone()].trim().starts_with('\\')
1102+
&& let Some(span) = fragments.span(cx, range.clone())
11011103
&& !span.from_expansion()
1102-
&& let Some(snippet) = snippet_opt(cx, span)
1103-
&& !snippet.trim().starts_with('\\')
1104-
&& event == HardBreak {
1104+
{
11051105
collected_breaks.push(span);
11061106
}
11071107
},

0 commit comments

Comments
 (0)