mirror of https://github.com/astral-sh/ruff
Suppress parse errors with explicit `# noqa: E999` directives (#2697)
This commit is contained in:
parent
7750087f56
commit
233be0e074
|
|
@ -6,8 +6,6 @@ use std::path::Path;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use log::error;
|
use log::error;
|
||||||
use nohash_hasher::IntMap;
|
use nohash_hasher::IntMap;
|
||||||
use ruff_python::builtins::{BUILTINS, MAGIC_GLOBALS};
|
|
||||||
use ruff_python::typing::TYPING_EXTENSIONS;
|
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use rustpython_common::cformat::{CFormatError, CFormatErrorType};
|
use rustpython_common::cformat::{CFormatError, CFormatErrorType};
|
||||||
use rustpython_parser::ast::{
|
use rustpython_parser::ast::{
|
||||||
|
|
@ -17,6 +15,9 @@ use rustpython_parser::ast::{
|
||||||
use rustpython_parser::parser;
|
use rustpython_parser::parser;
|
||||||
use smallvec::smallvec;
|
use smallvec::smallvec;
|
||||||
|
|
||||||
|
use ruff_python::builtins::{BUILTINS, MAGIC_GLOBALS};
|
||||||
|
use ruff_python::typing::TYPING_EXTENSIONS;
|
||||||
|
|
||||||
use crate::ast::helpers::{
|
use crate::ast::helpers::{
|
||||||
binding_range, collect_call_path, extract_handler_names, from_relative_import, to_module_path,
|
binding_range, collect_call_path, extract_handler_names, from_relative_import, to_module_path,
|
||||||
};
|
};
|
||||||
|
|
@ -30,7 +31,6 @@ use crate::ast::typing::{match_annotated_subscript, Callable, SubscriptKind};
|
||||||
use crate::ast::visitor::{walk_excepthandler, Visitor};
|
use crate::ast::visitor::{walk_excepthandler, Visitor};
|
||||||
use crate::ast::{branch_detection, cast, helpers, operations, typing, visitor};
|
use crate::ast::{branch_detection, cast, helpers, operations, typing, visitor};
|
||||||
use crate::docstrings::definition::{Definition, DefinitionKind, Docstring, Documentable};
|
use crate::docstrings::definition::{Definition, DefinitionKind, Docstring, Documentable};
|
||||||
use crate::noqa::Directive;
|
|
||||||
use crate::registry::{Diagnostic, Rule};
|
use crate::registry::{Diagnostic, Rule};
|
||||||
use crate::rules::{
|
use crate::rules::{
|
||||||
flake8_2020, flake8_annotations, flake8_bandit, flake8_blind_except, flake8_boolean_trap,
|
flake8_2020, flake8_annotations, flake8_bandit, flake8_blind_except, flake8_boolean_trap,
|
||||||
|
|
@ -282,7 +282,7 @@ impl<'a> Checker<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` if a `Rule` is disabled by a `noqa` directive.
|
/// Return `true` if a `Rule` is disabled by a `noqa` directive.
|
||||||
pub fn is_ignored(&self, code: &Rule, lineno: usize) -> bool {
|
pub fn rule_is_ignored(&self, code: &Rule, lineno: usize) -> bool {
|
||||||
// TODO(charlie): `noqa` directives are mostly enforced in `check_lines.rs`.
|
// TODO(charlie): `noqa` directives are mostly enforced in `check_lines.rs`.
|
||||||
// However, in rare cases, we need to check them here. For example, when
|
// However, in rare cases, we need to check them here. For example, when
|
||||||
// removing unused imports, we create a single fix that's applied to all
|
// removing unused imports, we create a single fix that's applied to all
|
||||||
|
|
@ -293,16 +293,7 @@ impl<'a> Checker<'a> {
|
||||||
if matches!(self.noqa, flags::Noqa::Disabled) {
|
if matches!(self.noqa, flags::Noqa::Disabled) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let noqa_lineno = self.noqa_line_for.get(&lineno).unwrap_or(&lineno);
|
noqa::rule_is_ignored(code, lineno, self.noqa_line_for, self.locator)
|
||||||
let line = self.locator.slice_source_code_range(&Range::new(
|
|
||||||
Location::new(*noqa_lineno, 0),
|
|
||||||
Location::new(noqa_lineno + 1, 0),
|
|
||||||
));
|
|
||||||
match noqa::extract_noqa_directive(line) {
|
|
||||||
Directive::None => false,
|
|
||||||
Directive::All(..) => true,
|
|
||||||
Directive::Codes(.., codes) => noqa::includes(code, &codes),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4866,9 +4857,9 @@ impl<'a> Checker<'a> {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.is_ignored(&Rule::UnusedImport, diagnostic_lineno)
|
if self.rule_is_ignored(&Rule::UnusedImport, diagnostic_lineno)
|
||||||
|| parent_lineno.map_or(false, |parent_lineno| {
|
|| parent_lineno.map_or(false, |parent_lineno| {
|
||||||
self.is_ignored(&Rule::UnusedImport, parent_lineno)
|
self.rule_is_ignored(&Rule::UnusedImport, parent_lineno)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
ignored
|
ignored
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ use crate::checkers::tokens::check_tokens;
|
||||||
use crate::directives::Directives;
|
use crate::directives::Directives;
|
||||||
use crate::doc_lines::{doc_lines_from_ast, doc_lines_from_tokens};
|
use crate::doc_lines::{doc_lines_from_ast, doc_lines_from_tokens};
|
||||||
use crate::message::{Message, Source};
|
use crate::message::{Message, Source};
|
||||||
use crate::noqa::add_noqa;
|
use crate::noqa::{add_noqa, rule_is_ignored};
|
||||||
use crate::registry::{Diagnostic, LintSource, Rule};
|
use crate::registry::{Diagnostic, LintSource, Rule};
|
||||||
use crate::rules::pycodestyle;
|
use crate::rules::pycodestyle;
|
||||||
use crate::settings::{flags, Settings};
|
use crate::settings::{flags, Settings};
|
||||||
|
|
@ -149,7 +149,17 @@ pub fn check_path(
|
||||||
if settings.rules.enabled(&Rule::SyntaxError) {
|
if settings.rules.enabled(&Rule::SyntaxError) {
|
||||||
pycodestyle::rules::syntax_error(&mut diagnostics, &parse_error);
|
pycodestyle::rules::syntax_error(&mut diagnostics, &parse_error);
|
||||||
}
|
}
|
||||||
error = Some(parse_error);
|
|
||||||
|
// If the syntax error is ignored, suppress it (regardless of whether
|
||||||
|
// `Rule::SyntaxError` is enabled).
|
||||||
|
if !rule_is_ignored(
|
||||||
|
&Rule::SyntaxError,
|
||||||
|
parse_error.location.row(),
|
||||||
|
&directives.noqa_line_for,
|
||||||
|
locator,
|
||||||
|
) {
|
||||||
|
error = Some(parse_error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,12 @@ use nohash_hasher::IntMap;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
use rustpython_parser::ast::Location;
|
||||||
|
|
||||||
|
use crate::ast::types::Range;
|
||||||
use crate::registry::{Diagnostic, Rule};
|
use crate::registry::{Diagnostic, Rule};
|
||||||
use crate::rule_redirects::get_redirect_target;
|
use crate::rule_redirects::get_redirect_target;
|
||||||
use crate::source_code::LineEnding;
|
use crate::source_code::{LineEnding, Locator};
|
||||||
|
|
||||||
static NOQA_LINE_REGEX: Lazy<Regex> = Lazy::new(|| {
|
static NOQA_LINE_REGEX: Lazy<Regex> = Lazy::new(|| {
|
||||||
Regex::new(
|
Regex::new(
|
||||||
|
|
@ -76,6 +78,25 @@ pub fn includes(needle: &Rule, haystack: &[&str]) -> bool {
|
||||||
.any(|candidate| needle == get_redirect_target(candidate).unwrap_or(candidate))
|
.any(|candidate| needle == get_redirect_target(candidate).unwrap_or(candidate))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the given [`Rule`] is ignored at the specified `lineno`.
|
||||||
|
pub fn rule_is_ignored(
|
||||||
|
code: &Rule,
|
||||||
|
lineno: usize,
|
||||||
|
noqa_line_for: &IntMap<usize, usize>,
|
||||||
|
locator: &Locator,
|
||||||
|
) -> bool {
|
||||||
|
let noqa_lineno = noqa_line_for.get(&lineno).unwrap_or(&lineno);
|
||||||
|
let line = locator.slice_source_code_range(&Range::new(
|
||||||
|
Location::new(*noqa_lineno, 0),
|
||||||
|
Location::new(noqa_lineno + 1, 0),
|
||||||
|
));
|
||||||
|
match extract_noqa_directive(line) {
|
||||||
|
Directive::None => false,
|
||||||
|
Directive::All(..) => true,
|
||||||
|
Directive::Codes(.., codes) => includes(code, &codes),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_noqa(
|
pub fn add_noqa(
|
||||||
path: &Path,
|
path: &Path,
|
||||||
diagnostics: &[Diagnostic],
|
diagnostics: &[Diagnostic],
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue