From 13c6a41c57037333722f627ddb876768cc1e854c Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 5 Feb 2024 22:25:31 -0500 Subject: [PATCH] Try fast-path for tab detection --- .../pycodestyle/rules/tab_indentation.rs | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/crates/ruff_linter/src/rules/pycodestyle/rules/tab_indentation.rs b/crates/ruff_linter/src/rules/pycodestyle/rules/tab_indentation.rs index 153caab6484563..d7adb6a8d0e405 100644 --- a/crates/ruff_linter/src/rules/pycodestyle/rules/tab_indentation.rs +++ b/crates/ruff_linter/src/rules/pycodestyle/rules/tab_indentation.rs @@ -3,7 +3,7 @@ use ruff_macros::{derive_message_formats, violation}; use ruff_python_index::Indexer; use ruff_python_parser::lexer::LexResult; use ruff_python_parser::Tok; -use ruff_python_trivia::leading_indentation; +use ruff_python_trivia::{is_python_whitespace, leading_indentation}; use ruff_source_file::Locator; use ruff_text_size::{TextLen, TextRange, TextSize}; @@ -52,6 +52,11 @@ pub(crate) fn tab_indentation( locator: &Locator, indexer: &Indexer, ) { + // If there are no tabs in the file, give up. + if memchr::memchr(b'\t', locator.contents().as_bytes()).is_none() { + return; + } + // Always check the first line for tab indentation as there's no newline // token before it. tab_indentation_at_line_start(diagnostics, locator, TextSize::default()); @@ -81,11 +86,25 @@ fn tab_indentation_at_line_start( locator: &Locator, line_start: TextSize, ) { - let indent = leading_indentation(locator.after(line_start)); - if indent.find('\t').is_some() { - diagnostics.push(Diagnostic::new( - TabIndentation, - TextRange::at(line_start, indent.text_len()), - )); + let mut contains_tab = false; + for (i, char) in locator.after(line_start).as_bytes().iter().enumerate() { + match char { + // If we find a tab character, report it as a violation. + b'\t' => { + contains_tab = true; + } + // If we find a space, continue. + b' ' | b'\x0C' => {} + // If we find a non-whitespace character, stop. + _ => { + if contains_tab { + diagnostics.push(Diagnostic::new( + TabIndentation, + TextRange::at(line_start, TextSize::try_from(i).unwrap()), + )); + } + return; + } + } } }