[HEAVY PERF] Optimize documentation lints 2/2
So, after https://github.com/rust-lang/rust-clippy/pull/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 <rpsalmi@gmail.com>
This commit is contained in:
parent
5dccb101ed
commit
4a7598f815
2 changed files with 54 additions and 52 deletions
|
|
@ -2,11 +2,10 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
|
|||
use itertools::Itertools;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_span::{BytePos, Span};
|
||||
use std::cmp::Ordering;
|
||||
use rustc_span::BytePos;
|
||||
use std::ops::Range;
|
||||
|
||||
use super::{DOC_LAZY_CONTINUATION, DOC_OVERINDENTED_LIST_ITEMS};
|
||||
use super::{DOC_LAZY_CONTINUATION, DOC_OVERINDENTED_LIST_ITEMS, Fragments};
|
||||
|
||||
fn map_container_to_text(c: &super::Container) -> &'static str {
|
||||
match c {
|
||||
|
|
@ -19,29 +18,27 @@ fn map_container_to_text(c: &super::Container) -> &'static str {
|
|||
pub(super) fn check(
|
||||
cx: &LateContext<'_>,
|
||||
doc: &str,
|
||||
range: Range<usize>,
|
||||
mut span: Span,
|
||||
cooked_range: Range<usize>,
|
||||
fragments: &Fragments<'_>,
|
||||
containers: &[super::Container],
|
||||
) {
|
||||
if doc[range.clone()].contains('\t') {
|
||||
// We don't do tab stops correctly.
|
||||
return;
|
||||
}
|
||||
|
||||
// Blockquote
|
||||
let ccount = doc[range.clone()].chars().filter(|c| *c == '>').count();
|
||||
// Get blockquotes
|
||||
let ccount = doc[cooked_range.clone()].chars().filter(|c| *c == '>').count();
|
||||
let blockquote_level = containers
|
||||
.iter()
|
||||
.filter(|c| matches!(c, super::Container::Blockquote))
|
||||
.count();
|
||||
if ccount < blockquote_level {
|
||||
|
||||
if ccount < blockquote_level
|
||||
&& let Some(mut span) = fragments.span(cx, cooked_range.clone())
|
||||
{
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
DOC_LAZY_CONTINUATION,
|
||||
span,
|
||||
"doc quote line without `>` marker",
|
||||
|diag| {
|
||||
let mut doc_start_range = &doc[range];
|
||||
let mut doc_start_range = &doc[cooked_range];
|
||||
let mut suggested = String::new();
|
||||
for c in containers {
|
||||
let text = map_container_to_text(c);
|
||||
|
|
@ -78,7 +75,7 @@ pub(super) fn check(
|
|||
}
|
||||
|
||||
// List
|
||||
let leading_spaces = doc[range].chars().filter(|c| *c == ' ').count();
|
||||
let leading_spaces = doc[cooked_range.clone()].chars().filter(|c| *c == ' ').count();
|
||||
let list_indentation = containers
|
||||
.iter()
|
||||
.map(|c| {
|
||||
|
|
@ -89,36 +86,41 @@ pub(super) fn check(
|
|||
}
|
||||
})
|
||||
.sum();
|
||||
match leading_spaces.cmp(&list_indentation) {
|
||||
Ordering::Less => span_lint_and_then(
|
||||
cx,
|
||||
DOC_LAZY_CONTINUATION,
|
||||
span,
|
||||
"doc list item without indentation",
|
||||
|diag| {
|
||||
// simpler suggestion style for indentation
|
||||
let indent = list_indentation - leading_spaces;
|
||||
diag.span_suggestion_verbose(
|
||||
span.shrink_to_hi(),
|
||||
"indent this line",
|
||||
std::iter::repeat_n(" ", indent).join(""),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
diag.help("if this is supposed to be its own paragraph, add a blank line");
|
||||
},
|
||||
),
|
||||
Ordering::Greater => {
|
||||
let sugg = std::iter::repeat_n(" ", list_indentation).join("");
|
||||
span_lint_and_sugg(
|
||||
|
||||
if leading_spaces != list_indentation
|
||||
&& let Some(span) = fragments.span(cx, cooked_range.clone())
|
||||
{
|
||||
if leading_spaces < list_indentation {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
DOC_OVERINDENTED_LIST_ITEMS,
|
||||
DOC_LAZY_CONTINUATION,
|
||||
span,
|
||||
"doc list item overindented",
|
||||
format!("try using `{sugg}` ({list_indentation} spaces)"),
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
"doc list item without indentation",
|
||||
|diag| {
|
||||
// simpler suggestion style for indentation
|
||||
let indent = list_indentation - leading_spaces;
|
||||
diag.span_suggestion_verbose(
|
||||
span.shrink_to_hi(),
|
||||
"indent this line",
|
||||
std::iter::repeat_n(" ", indent).join(""),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
diag.help("if this is supposed to be its own paragraph, add a blank line");
|
||||
},
|
||||
);
|
||||
},
|
||||
Ordering::Equal => {},
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let sugg = std::iter::repeat_n(" ", list_indentation).join("");
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
DOC_OVERINDENTED_LIST_ITEMS,
|
||||
span,
|
||||
"doc list item overindented",
|
||||
format!("try using `{sugg}` ({list_indentation} spaces)"),
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
use clippy_config::Conf;
|
||||
use clippy_utils::attrs::is_doc_hidden;
|
||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::{is_entrypoint_fn, is_trait_impl_item};
|
||||
use pulldown_cmark::Event::{
|
||||
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
|
|||
| TaskListMarker(_) | Code(_) | Rule | InlineMath(..) | DisplayMath(..) => (),
|
||||
SoftBreak | HardBreak => {
|
||||
if !containers.is_empty()
|
||||
&& let Some((next_event, next_range)) = events.peek()
|
||||
&& let Some(next_span) = fragments.span(cx, next_range.clone())
|
||||
&& let Some(span) = fragments.span(cx, range.clone())
|
||||
&& !in_footnote_definition
|
||||
// Tabs aren't handled correctly vvvv
|
||||
&& !doc[range.clone()].contains('\t')
|
||||
&& let Some((next_event, next_range)) = events.peek()
|
||||
&& !matches!(next_event, End(_))
|
||||
{
|
||||
lazy_continuation::check(
|
||||
cx,
|
||||
doc,
|
||||
range.end..next_range.start,
|
||||
Span::new(span.hi(), next_span.lo(), span.ctxt(), span.parent()),
|
||||
&fragments,
|
||||
&containers[..],
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(span) = fragments.span(cx, range.clone())
|
||||
|
||||
if event == HardBreak
|
||||
&& !doc[range.clone()].trim().starts_with('\\')
|
||||
&& let Some(span) = fragments.span(cx, range.clone())
|
||||
&& !span.from_expansion()
|
||||
&& let Some(snippet) = snippet_opt(cx, span)
|
||||
&& !snippet.trim().starts_with('\\')
|
||||
&& event == HardBreak {
|
||||
{
|
||||
collected_breaks.push(span);
|
||||
}
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue