mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-02 01:42:25 +00:00
Remove AST checker's dependency on resolver (#3368)
This commit is contained in:
parent
074f5634a5
commit
8437399496
8 changed files with 62 additions and 58 deletions
|
@ -5,12 +5,12 @@ use rustc_hash::FxHashMap;
|
||||||
use rustpython_parser::ast::{Expr, Stmt};
|
use rustpython_parser::ast::{Expr, Stmt};
|
||||||
use smallvec::smallvec;
|
use smallvec::smallvec;
|
||||||
|
|
||||||
|
use ruff_python_stdlib::path::is_python_stub_file;
|
||||||
use ruff_python_stdlib::typing::TYPING_EXTENSIONS;
|
use ruff_python_stdlib::typing::TYPING_EXTENSIONS;
|
||||||
|
|
||||||
use crate::ast::helpers::{collect_call_path, from_relative_import, Exceptions};
|
use crate::ast::helpers::{collect_call_path, from_relative_import, Exceptions};
|
||||||
use crate::ast::types::{Binding, BindingKind, CallPath, ExecutionContext, RefEquality, Scope};
|
use crate::ast::types::{Binding, BindingKind, CallPath, ExecutionContext, RefEquality, Scope};
|
||||||
use crate::ast::visibility::{module_visibility, Modifier, VisibleScope};
|
use crate::ast::visibility::{module_visibility, Modifier, VisibleScope};
|
||||||
use crate::resolver::is_interface_definition_path;
|
|
||||||
|
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
pub struct Context<'a> {
|
pub struct Context<'a> {
|
||||||
|
@ -82,7 +82,7 @@ impl<'a> Context<'a> {
|
||||||
in_type_checking_block: false,
|
in_type_checking_block: false,
|
||||||
seen_import_boundary: false,
|
seen_import_boundary: false,
|
||||||
futures_allowed: true,
|
futures_allowed: true,
|
||||||
annotations_future_enabled: is_interface_definition_path(path),
|
annotations_future_enabled: is_python_stub_file(path),
|
||||||
handled_exceptions: Vec::default(),
|
handled_exceptions: Vec::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ use rustpython_parser::ast::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use ruff_python_stdlib::builtins::{BUILTINS, MAGIC_GLOBALS};
|
use ruff_python_stdlib::builtins::{BUILTINS, MAGIC_GLOBALS};
|
||||||
|
use ruff_python_stdlib::path::is_python_stub_file;
|
||||||
|
|
||||||
use crate::ast::context::Context;
|
use crate::ast::context::Context;
|
||||||
use crate::ast::helpers::{binding_range, extract_handled_exceptions, to_module_path, Exceptions};
|
use crate::ast::helpers::{binding_range, extract_handled_exceptions, to_module_path, Exceptions};
|
||||||
|
@ -31,7 +32,6 @@ use crate::docstrings::definition::{
|
||||||
transition_scope, Definition, DefinitionKind, Docstring, Documentable,
|
transition_scope, Definition, DefinitionKind, Docstring, Documentable,
|
||||||
};
|
};
|
||||||
use crate::registry::{Diagnostic, Rule};
|
use crate::registry::{Diagnostic, Rule};
|
||||||
use crate::resolver::is_interface_definition_path;
|
|
||||||
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,
|
||||||
flake8_bugbear, flake8_builtins, flake8_comprehensions, flake8_datetimez, flake8_debugger,
|
flake8_bugbear, flake8_builtins, flake8_comprehensions, flake8_datetimez, flake8_debugger,
|
||||||
|
@ -58,7 +58,7 @@ pub struct Checker<'a> {
|
||||||
pub path: &'a Path,
|
pub path: &'a Path,
|
||||||
module_path: Option<Vec<String>>,
|
module_path: Option<Vec<String>>,
|
||||||
package: Option<&'a Path>,
|
package: Option<&'a Path>,
|
||||||
is_interface_definition: bool,
|
is_stub: bool,
|
||||||
autofix: flags::Autofix,
|
autofix: flags::Autofix,
|
||||||
noqa: flags::Noqa,
|
noqa: flags::Noqa,
|
||||||
pub settings: &'a Settings,
|
pub settings: &'a Settings,
|
||||||
|
@ -97,7 +97,7 @@ impl<'a> Checker<'a> {
|
||||||
path,
|
path,
|
||||||
package,
|
package,
|
||||||
module_path: module_path.clone(),
|
module_path: module_path.clone(),
|
||||||
is_interface_definition: is_interface_definition_path(path),
|
is_stub: is_python_stub_file(path),
|
||||||
locator,
|
locator,
|
||||||
stylist: style,
|
stylist: style,
|
||||||
indexer,
|
indexer,
|
||||||
|
@ -378,7 +378,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_interface_definition {
|
if self.is_stub {
|
||||||
if self.settings.rules.enabled(&Rule::PassStatementStubBody) {
|
if self.settings.rules.enabled(&Rule::PassStatementStubBody) {
|
||||||
flake8_pyi::rules::pass_statement_stub_body(self, body);
|
flake8_pyi::rules::pass_statement_stub_body(self, body);
|
||||||
}
|
}
|
||||||
|
@ -756,7 +756,7 @@ where
|
||||||
flake8_bugbear::rules::useless_expression(self, body);
|
flake8_bugbear::rules::useless_expression(self, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.is_interface_definition {
|
if !self.is_stub {
|
||||||
if self
|
if self
|
||||||
.settings
|
.settings
|
||||||
.rules
|
.rules
|
||||||
|
@ -771,7 +771,7 @@ where
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.is_interface_definition {
|
if self.is_stub {
|
||||||
if self.settings.rules.enabled(&Rule::PassStatementStubBody) {
|
if self.settings.rules.enabled(&Rule::PassStatementStubBody) {
|
||||||
flake8_pyi::rules::pass_statement_stub_body(self, body);
|
flake8_pyi::rules::pass_statement_stub_body(self, body);
|
||||||
}
|
}
|
||||||
|
@ -1805,7 +1805,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_interface_definition {
|
if self.is_stub {
|
||||||
if self.settings.rules.enabled(&Rule::PrefixTypeParams) {
|
if self.settings.rules.enabled(&Rule::PrefixTypeParams) {
|
||||||
flake8_pyi::rules::prefix_type_params(self, value, targets);
|
flake8_pyi::rules::prefix_type_params(self, value, targets);
|
||||||
}
|
}
|
||||||
|
@ -3301,7 +3301,7 @@ where
|
||||||
flake8_simplify::rules::yoda_conditions(self, expr, left, ops, comparators);
|
flake8_simplify::rules::yoda_conditions(self, expr, left, ops, comparators);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_interface_definition {
|
if self.is_stub {
|
||||||
if self
|
if self
|
||||||
.settings
|
.settings
|
||||||
.rules
|
.rules
|
||||||
|
@ -3886,7 +3886,7 @@ where
|
||||||
flake8_bugbear::rules::function_call_argument_default(self, arguments);
|
flake8_bugbear::rules::function_call_argument_default(self, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_interface_definition {
|
if self.is_stub {
|
||||||
if self
|
if self
|
||||||
.settings
|
.settings
|
||||||
.rules
|
.rules
|
||||||
|
@ -3895,7 +3895,7 @@ where
|
||||||
flake8_pyi::rules::typed_argument_simple_defaults(self, arguments);
|
flake8_pyi::rules::typed_argument_simple_defaults(self, arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.is_interface_definition {
|
if self.is_stub {
|
||||||
if self.settings.rules.enabled(&Rule::ArgumentSimpleDefaults) {
|
if self.settings.rules.enabled(&Rule::ArgumentSimpleDefaults) {
|
||||||
flake8_pyi::rules::argument_simple_defaults(self, arguments);
|
flake8_pyi::rules::argument_simple_defaults(self, arguments);
|
||||||
}
|
}
|
||||||
|
@ -4710,7 +4710,7 @@ impl<'a> Checker<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_dead_scopes(&mut self) {
|
fn check_dead_scopes(&mut self) {
|
||||||
let enforce_typing_imports = !self.is_interface_definition
|
let enforce_typing_imports = !self.is_stub
|
||||||
&& (self
|
&& (self
|
||||||
.settings
|
.settings
|
||||||
.rules
|
.rules
|
||||||
|
@ -5241,7 +5241,7 @@ impl<'a> Checker<'a> {
|
||||||
}
|
}
|
||||||
overloaded_name = flake8_annotations::helpers::overloaded_name(self, &definition);
|
overloaded_name = flake8_annotations::helpers::overloaded_name(self, &definition);
|
||||||
}
|
}
|
||||||
if self.is_interface_definition {
|
if self.is_stub {
|
||||||
if self.settings.rules.enabled(&Rule::DocstringInStub) {
|
if self.settings.rules.enabled(&Rule::DocstringInStub) {
|
||||||
flake8_pyi::rules::docstring_in_stubs(self, definition.docstring);
|
flake8_pyi::rules::docstring_in_stubs(self, definition.docstring);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ pub fn check_tokens(
|
||||||
tokens: &[LexResult],
|
tokens: &[LexResult],
|
||||||
settings: &Settings,
|
settings: &Settings,
|
||||||
autofix: flags::Autofix,
|
autofix: flags::Autofix,
|
||||||
is_interface_definition: bool,
|
is_stub: bool,
|
||||||
) -> Vec<Diagnostic> {
|
) -> Vec<Diagnostic> {
|
||||||
let mut diagnostics: Vec<Diagnostic> = vec![];
|
let mut diagnostics: Vec<Diagnostic> = vec![];
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ pub fn check_tokens(
|
||||||
}
|
}
|
||||||
|
|
||||||
// PYI033
|
// PYI033
|
||||||
if enforce_type_comment_in_stub && is_interface_definition {
|
if enforce_type_comment_in_stub && is_stub {
|
||||||
diagnostics.extend(flake8_pyi::rules::type_comment_in_stub(tokens));
|
diagnostics.extend(flake8_pyi::rules::type_comment_in_stub(tokens));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ use std::path::Path;
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use log::error;
|
use log::error;
|
||||||
|
use ruff_python_stdlib::path::is_python_stub_file;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use rustpython_parser::lexer::LexResult;
|
use rustpython_parser::lexer::LexResult;
|
||||||
use rustpython_parser::ParseError;
|
use rustpython_parser::ParseError;
|
||||||
|
@ -21,7 +22,6 @@ 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, rule_is_ignored};
|
use crate::noqa::{add_noqa, rule_is_ignored};
|
||||||
use crate::registry::{Diagnostic, Rule};
|
use crate::registry::{Diagnostic, Rule};
|
||||||
use crate::resolver::is_interface_definition_path;
|
|
||||||
use crate::rules::pycodestyle;
|
use crate::rules::pycodestyle;
|
||||||
use crate::settings::{flags, Settings};
|
use crate::settings::{flags, Settings};
|
||||||
use crate::source_code::{Indexer, Locator, Stylist};
|
use crate::source_code::{Indexer, Locator, Stylist};
|
||||||
|
@ -84,14 +84,8 @@ pub fn check_path(
|
||||||
.iter_enabled()
|
.iter_enabled()
|
||||||
.any(|rule_code| rule_code.lint_source().is_tokens())
|
.any(|rule_code| rule_code.lint_source().is_tokens())
|
||||||
{
|
{
|
||||||
let is_interface_definition = is_interface_definition_path(path);
|
let is_stub = is_python_stub_file(path);
|
||||||
diagnostics.extend(check_tokens(
|
diagnostics.extend(check_tokens(locator, &tokens, settings, autofix, is_stub));
|
||||||
locator,
|
|
||||||
&tokens,
|
|
||||||
settings,
|
|
||||||
autofix,
|
|
||||||
is_interface_definition,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the filesystem-based rules.
|
// Run the filesystem-based rules.
|
||||||
|
|
|
@ -10,6 +10,7 @@ use ignore::{DirEntry, WalkBuilder, WalkState};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use path_absolutize::path_dedot;
|
use path_absolutize::path_dedot;
|
||||||
|
use ruff_python_stdlib::path::is_python_file;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
|
|
||||||
use crate::fs;
|
use crate::fs;
|
||||||
|
@ -191,20 +192,9 @@ fn match_exclusion(file_path: &str, file_basename: &str, exclusion: &globset::Gl
|
||||||
exclusion.is_match(file_path) || exclusion.is_match(file_basename)
|
exclusion.is_match(file_path) || exclusion.is_match(file_basename)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` if the [`Path`] appears to be that of a Python file.
|
|
||||||
fn is_python_path(path: &Path) -> bool {
|
|
||||||
path.extension()
|
|
||||||
.map_or(false, |ext| ext == "py" || ext == "pyi")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return `true` if the [`Path`] appears to be that of a Python interface definition file (`.pyi`).
|
|
||||||
pub fn is_interface_definition_path(path: &Path) -> bool {
|
|
||||||
path.extension().map_or(false, |ext| ext == "pyi")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return `true` if the [`DirEntry`] appears to be that of a Python file.
|
/// Return `true` if the [`DirEntry`] appears to be that of a Python file.
|
||||||
pub fn is_python_entry(entry: &DirEntry) -> bool {
|
pub fn is_python_entry(entry: &DirEntry) -> bool {
|
||||||
is_python_path(entry.path())
|
is_python_file(entry.path())
|
||||||
&& !entry
|
&& !entry
|
||||||
.file_type()
|
.file_type()
|
||||||
.map_or(false, |file_type| file_type.is_dir())
|
.map_or(false, |file_type| file_type.is_dir())
|
||||||
|
@ -430,28 +420,13 @@ mod tests {
|
||||||
|
|
||||||
use crate::fs;
|
use crate::fs;
|
||||||
use crate::resolver::{
|
use crate::resolver::{
|
||||||
is_file_excluded, is_python_path, match_exclusion, resolve_settings_with_processor,
|
is_file_excluded, match_exclusion, resolve_settings_with_processor, NoOpProcessor,
|
||||||
NoOpProcessor, PyprojectDiscovery, Relativity, Resolver,
|
PyprojectDiscovery, Relativity, Resolver,
|
||||||
};
|
};
|
||||||
use crate::settings::pyproject::find_settings_toml;
|
use crate::settings::pyproject::find_settings_toml;
|
||||||
use crate::settings::types::FilePattern;
|
use crate::settings::types::FilePattern;
|
||||||
use crate::test::test_resource_path;
|
use crate::test::test_resource_path;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn inclusions() {
|
|
||||||
let path = Path::new("foo/bar/baz.py").absolutize().unwrap();
|
|
||||||
assert!(is_python_path(&path));
|
|
||||||
|
|
||||||
let path = Path::new("foo/bar/baz.pyi").absolutize().unwrap();
|
|
||||||
assert!(is_python_path(&path));
|
|
||||||
|
|
||||||
let path = Path::new("foo/bar/baz.js").absolutize().unwrap();
|
|
||||||
assert!(!is_python_path(&path));
|
|
||||||
|
|
||||||
let path = Path::new("foo/bar/baz").absolutize().unwrap();
|
|
||||||
assert!(!is_python_path(&path));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_exclusion(file_pattern: FilePattern) -> GlobSet {
|
fn make_exclusion(file_pattern: FilePattern) -> GlobSet {
|
||||||
let mut builder = globset::GlobSetBuilder::new();
|
let mut builder = globset::GlobSetBuilder::new();
|
||||||
file_pattern.add_to(&mut builder).unwrap();
|
file_pattern.add_to(&mut builder).unwrap();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use ruff_python_stdlib::path::is_python_stub_file;
|
||||||
use rustpython_parser::ast::{
|
use rustpython_parser::ast::{
|
||||||
Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, Excepthandler,
|
Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, Excepthandler,
|
||||||
ExcepthandlerKind, Expr, ExprContext, Keyword, MatchCase, Operator, Pattern, Stmt, StmtKind,
|
ExcepthandlerKind, Expr, ExprContext, Keyword, MatchCase, Operator, Pattern, Stmt, StmtKind,
|
||||||
|
@ -9,7 +10,6 @@ use rustpython_parser::ast::{
|
||||||
use super::helpers;
|
use super::helpers;
|
||||||
use crate::ast::visitor::Visitor;
|
use crate::ast::visitor::Visitor;
|
||||||
use crate::directives::IsortDirectives;
|
use crate::directives::IsortDirectives;
|
||||||
use crate::resolver::is_interface_definition_path;
|
|
||||||
use crate::source_code::Locator;
|
use crate::source_code::Locator;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -29,7 +29,7 @@ pub struct Block<'a> {
|
||||||
pub struct ImportTracker<'a> {
|
pub struct ImportTracker<'a> {
|
||||||
locator: &'a Locator<'a>,
|
locator: &'a Locator<'a>,
|
||||||
directives: &'a IsortDirectives,
|
directives: &'a IsortDirectives,
|
||||||
pyi: bool,
|
is_stub: bool,
|
||||||
blocks: Vec<Block<'a>>,
|
blocks: Vec<Block<'a>>,
|
||||||
split_index: usize,
|
split_index: usize,
|
||||||
nested: bool,
|
nested: bool,
|
||||||
|
@ -40,7 +40,7 @@ impl<'a> ImportTracker<'a> {
|
||||||
Self {
|
Self {
|
||||||
locator,
|
locator,
|
||||||
directives,
|
directives,
|
||||||
pyi: is_interface_definition_path(path),
|
is_stub: is_python_stub_file(path),
|
||||||
blocks: vec![Block::default()],
|
blocks: vec![Block::default()],
|
||||||
split_index: 0,
|
split_index: 0,
|
||||||
nested: false,
|
nested: false,
|
||||||
|
@ -65,7 +65,7 @@ impl<'a> ImportTracker<'a> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(if self.pyi {
|
Some(if self.is_stub {
|
||||||
// Black treats interface files differently, limiting to one newline
|
// Black treats interface files differently, limiting to one newline
|
||||||
// (`Trailing::Sibling`).
|
// (`Trailing::Sibling`).
|
||||||
Trailer::Sibling
|
Trailer::Sibling
|
||||||
|
|
|
@ -3,6 +3,7 @@ pub mod bytes;
|
||||||
pub mod future;
|
pub mod future;
|
||||||
pub mod identifiers;
|
pub mod identifiers;
|
||||||
pub mod keyword;
|
pub mod keyword;
|
||||||
|
pub mod path;
|
||||||
pub mod str;
|
pub mod str;
|
||||||
pub mod sys;
|
pub mod sys;
|
||||||
pub mod typing;
|
pub mod typing;
|
||||||
|
|
34
crates/ruff_python_stdlib/src/path.rs
Normal file
34
crates/ruff_python_stdlib/src/path.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
/// Return `true` if the [`Path`] appears to be that of a Python file.
|
||||||
|
pub fn is_python_file(path: &Path) -> bool {
|
||||||
|
path.extension()
|
||||||
|
.map_or(false, |ext| ext == "py" || ext == "pyi")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return `true` if the [`Path`] appears to be that of a Python interface definition file (`.pyi`).
|
||||||
|
pub fn is_python_stub_file(path: &Path) -> bool {
|
||||||
|
path.extension().map_or(false, |ext| ext == "pyi")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use crate::path::is_python_file;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn inclusions() {
|
||||||
|
let path = Path::new("foo/bar/baz.py");
|
||||||
|
assert!(is_python_file(path));
|
||||||
|
|
||||||
|
let path = Path::new("foo/bar/baz.pyi");
|
||||||
|
assert!(is_python_file(path));
|
||||||
|
|
||||||
|
let path = Path::new("foo/bar/baz.js");
|
||||||
|
assert!(!is_python_file(path));
|
||||||
|
|
||||||
|
let path = Path::new("foo/bar/baz");
|
||||||
|
assert!(!is_python_file(path));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue