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 smallvec::smallvec;
|
||||
|
||||
use ruff_python_stdlib::path::is_python_stub_file;
|
||||
use ruff_python_stdlib::typing::TYPING_EXTENSIONS;
|
||||
|
||||
use crate::ast::helpers::{collect_call_path, from_relative_import, Exceptions};
|
||||
use crate::ast::types::{Binding, BindingKind, CallPath, ExecutionContext, RefEquality, Scope};
|
||||
use crate::ast::visibility::{module_visibility, Modifier, VisibleScope};
|
||||
use crate::resolver::is_interface_definition_path;
|
||||
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
pub struct Context<'a> {
|
||||
|
@ -82,7 +82,7 @@ impl<'a> Context<'a> {
|
|||
in_type_checking_block: false,
|
||||
seen_import_boundary: false,
|
||||
futures_allowed: true,
|
||||
annotations_future_enabled: is_interface_definition_path(path),
|
||||
annotations_future_enabled: is_python_stub_file(path),
|
||||
handled_exceptions: Vec::default(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ use rustpython_parser::ast::{
|
|||
};
|
||||
|
||||
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::helpers::{binding_range, extract_handled_exceptions, to_module_path, Exceptions};
|
||||
|
@ -31,7 +32,6 @@ use crate::docstrings::definition::{
|
|||
transition_scope, Definition, DefinitionKind, Docstring, Documentable,
|
||||
};
|
||||
use crate::registry::{Diagnostic, Rule};
|
||||
use crate::resolver::is_interface_definition_path;
|
||||
use crate::rules::{
|
||||
flake8_2020, flake8_annotations, flake8_bandit, flake8_blind_except, flake8_boolean_trap,
|
||||
flake8_bugbear, flake8_builtins, flake8_comprehensions, flake8_datetimez, flake8_debugger,
|
||||
|
@ -58,7 +58,7 @@ pub struct Checker<'a> {
|
|||
pub path: &'a Path,
|
||||
module_path: Option<Vec<String>>,
|
||||
package: Option<&'a Path>,
|
||||
is_interface_definition: bool,
|
||||
is_stub: bool,
|
||||
autofix: flags::Autofix,
|
||||
noqa: flags::Noqa,
|
||||
pub settings: &'a Settings,
|
||||
|
@ -97,7 +97,7 @@ impl<'a> Checker<'a> {
|
|||
path,
|
||||
package,
|
||||
module_path: module_path.clone(),
|
||||
is_interface_definition: is_interface_definition_path(path),
|
||||
is_stub: is_python_stub_file(path),
|
||||
locator,
|
||||
stylist: style,
|
||||
indexer,
|
||||
|
@ -378,7 +378,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
if self.is_interface_definition {
|
||||
if self.is_stub {
|
||||
if self.settings.rules.enabled(&Rule::PassStatementStubBody) {
|
||||
flake8_pyi::rules::pass_statement_stub_body(self, body);
|
||||
}
|
||||
|
@ -756,7 +756,7 @@ where
|
|||
flake8_bugbear::rules::useless_expression(self, body);
|
||||
}
|
||||
|
||||
if !self.is_interface_definition {
|
||||
if !self.is_stub {
|
||||
if self
|
||||
.settings
|
||||
.rules
|
||||
|
@ -771,7 +771,7 @@ where
|
|||
);
|
||||
}
|
||||
}
|
||||
if self.is_interface_definition {
|
||||
if self.is_stub {
|
||||
if self.settings.rules.enabled(&Rule::PassStatementStubBody) {
|
||||
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) {
|
||||
flake8_pyi::rules::prefix_type_params(self, value, targets);
|
||||
}
|
||||
|
@ -3301,7 +3301,7 @@ where
|
|||
flake8_simplify::rules::yoda_conditions(self, expr, left, ops, comparators);
|
||||
}
|
||||
|
||||
if self.is_interface_definition {
|
||||
if self.is_stub {
|
||||
if self
|
||||
.settings
|
||||
.rules
|
||||
|
@ -3886,7 +3886,7 @@ where
|
|||
flake8_bugbear::rules::function_call_argument_default(self, arguments);
|
||||
}
|
||||
|
||||
if self.is_interface_definition {
|
||||
if self.is_stub {
|
||||
if self
|
||||
.settings
|
||||
.rules
|
||||
|
@ -3895,7 +3895,7 @@ where
|
|||
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) {
|
||||
flake8_pyi::rules::argument_simple_defaults(self, arguments);
|
||||
}
|
||||
|
@ -4710,7 +4710,7 @@ impl<'a> Checker<'a> {
|
|||
}
|
||||
|
||||
fn check_dead_scopes(&mut self) {
|
||||
let enforce_typing_imports = !self.is_interface_definition
|
||||
let enforce_typing_imports = !self.is_stub
|
||||
&& (self
|
||||
.settings
|
||||
.rules
|
||||
|
@ -5241,7 +5241,7 @@ impl<'a> Checker<'a> {
|
|||
}
|
||||
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) {
|
||||
flake8_pyi::rules::docstring_in_stubs(self, definition.docstring);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ pub fn check_tokens(
|
|||
tokens: &[LexResult],
|
||||
settings: &Settings,
|
||||
autofix: flags::Autofix,
|
||||
is_interface_definition: bool,
|
||||
is_stub: bool,
|
||||
) -> Vec<Diagnostic> {
|
||||
let mut diagnostics: Vec<Diagnostic> = vec![];
|
||||
|
||||
|
@ -164,7 +164,7 @@ pub fn check_tokens(
|
|||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::path::Path;
|
|||
use anyhow::{anyhow, Result};
|
||||
use colored::Colorize;
|
||||
use log::error;
|
||||
use ruff_python_stdlib::path::is_python_stub_file;
|
||||
use rustc_hash::FxHashMap;
|
||||
use rustpython_parser::lexer::LexResult;
|
||||
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::noqa::{add_noqa, rule_is_ignored};
|
||||
use crate::registry::{Diagnostic, Rule};
|
||||
use crate::resolver::is_interface_definition_path;
|
||||
use crate::rules::pycodestyle;
|
||||
use crate::settings::{flags, Settings};
|
||||
use crate::source_code::{Indexer, Locator, Stylist};
|
||||
|
@ -84,14 +84,8 @@ pub fn check_path(
|
|||
.iter_enabled()
|
||||
.any(|rule_code| rule_code.lint_source().is_tokens())
|
||||
{
|
||||
let is_interface_definition = is_interface_definition_path(path);
|
||||
diagnostics.extend(check_tokens(
|
||||
locator,
|
||||
&tokens,
|
||||
settings,
|
||||
autofix,
|
||||
is_interface_definition,
|
||||
));
|
||||
let is_stub = is_python_stub_file(path);
|
||||
diagnostics.extend(check_tokens(locator, &tokens, settings, autofix, is_stub));
|
||||
}
|
||||
|
||||
// Run the filesystem-based rules.
|
||||
|
|
|
@ -10,6 +10,7 @@ use ignore::{DirEntry, WalkBuilder, WalkState};
|
|||
use itertools::Itertools;
|
||||
use log::debug;
|
||||
use path_absolutize::path_dedot;
|
||||
use ruff_python_stdlib::path::is_python_file;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub fn is_python_entry(entry: &DirEntry) -> bool {
|
||||
is_python_path(entry.path())
|
||||
is_python_file(entry.path())
|
||||
&& !entry
|
||||
.file_type()
|
||||
.map_or(false, |file_type| file_type.is_dir())
|
||||
|
@ -430,28 +420,13 @@ mod tests {
|
|||
|
||||
use crate::fs;
|
||||
use crate::resolver::{
|
||||
is_file_excluded, is_python_path, match_exclusion, resolve_settings_with_processor,
|
||||
NoOpProcessor, PyprojectDiscovery, Relativity, Resolver,
|
||||
is_file_excluded, match_exclusion, resolve_settings_with_processor, NoOpProcessor,
|
||||
PyprojectDiscovery, Relativity, Resolver,
|
||||
};
|
||||
use crate::settings::pyproject::find_settings_toml;
|
||||
use crate::settings::types::FilePattern;
|
||||
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 {
|
||||
let mut builder = globset::GlobSetBuilder::new();
|
||||
file_pattern.add_to(&mut builder).unwrap();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::path::Path;
|
||||
|
||||
use ruff_python_stdlib::path::is_python_stub_file;
|
||||
use rustpython_parser::ast::{
|
||||
Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, Excepthandler,
|
||||
ExcepthandlerKind, Expr, ExprContext, Keyword, MatchCase, Operator, Pattern, Stmt, StmtKind,
|
||||
|
@ -9,7 +10,6 @@ use rustpython_parser::ast::{
|
|||
use super::helpers;
|
||||
use crate::ast::visitor::Visitor;
|
||||
use crate::directives::IsortDirectives;
|
||||
use crate::resolver::is_interface_definition_path;
|
||||
use crate::source_code::Locator;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -29,7 +29,7 @@ pub struct Block<'a> {
|
|||
pub struct ImportTracker<'a> {
|
||||
locator: &'a Locator<'a>,
|
||||
directives: &'a IsortDirectives,
|
||||
pyi: bool,
|
||||
is_stub: bool,
|
||||
blocks: Vec<Block<'a>>,
|
||||
split_index: usize,
|
||||
nested: bool,
|
||||
|
@ -40,7 +40,7 @@ impl<'a> ImportTracker<'a> {
|
|||
Self {
|
||||
locator,
|
||||
directives,
|
||||
pyi: is_interface_definition_path(path),
|
||||
is_stub: is_python_stub_file(path),
|
||||
blocks: vec![Block::default()],
|
||||
split_index: 0,
|
||||
nested: false,
|
||||
|
@ -65,7 +65,7 @@ impl<'a> ImportTracker<'a> {
|
|||
return None;
|
||||
}
|
||||
|
||||
Some(if self.pyi {
|
||||
Some(if self.is_stub {
|
||||
// Black treats interface files differently, limiting to one newline
|
||||
// (`Trailing::Sibling`).
|
||||
Trailer::Sibling
|
||||
|
|
|
@ -3,6 +3,7 @@ pub mod bytes;
|
|||
pub mod future;
|
||||
pub mod identifiers;
|
||||
pub mod keyword;
|
||||
pub mod path;
|
||||
pub mod str;
|
||||
pub mod sys;
|
||||
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