Make the AST Checker `pub(crate)` (#4498)

This commit is contained in:
Charlie Marsh 2023-05-18 11:17:26 -04:00 committed by GitHub
parent e9c6f16c56
commit 85f67b2ee3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 39 additions and 38 deletions

View File

@ -57,7 +57,7 @@ use crate::{autofix, docstrings, noqa, warn_user};
mod deferred; mod deferred;
pub struct Checker<'a> { pub(crate) struct Checker<'a> {
// Settings, static metadata, etc. // Settings, static metadata, etc.
path: &'a Path, path: &'a Path,
module_path: Option<&'a [String]>, module_path: Option<&'a [String]>,
@ -65,23 +65,23 @@ pub struct Checker<'a> {
is_stub: bool, is_stub: bool,
noqa: flags::Noqa, noqa: flags::Noqa,
noqa_line_for: &'a NoqaMapping, noqa_line_for: &'a NoqaMapping,
pub settings: &'a Settings, pub(crate) settings: &'a Settings,
pub locator: &'a Locator<'a>, pub(crate) locator: &'a Locator<'a>,
pub stylist: &'a Stylist<'a>, pub(crate) stylist: &'a Stylist<'a>,
pub indexer: &'a Indexer, pub(crate) indexer: &'a Indexer,
pub importer: Importer<'a>, pub(crate) importer: Importer<'a>,
// Stateful fields. // Stateful fields.
pub ctx: Context<'a>, pub(crate) ctx: Context<'a>,
pub diagnostics: Vec<Diagnostic>, pub(crate) diagnostics: Vec<Diagnostic>,
pub deletions: FxHashSet<RefEquality<'a, Stmt>>, pub(crate) deletions: FxHashSet<RefEquality<'a, Stmt>>,
deferred: Deferred<'a>, deferred: Deferred<'a>,
// Check-specific state. // Check-specific state.
pub flake8_bugbear_seen: Vec<&'a Expr>, pub(crate) flake8_bugbear_seen: Vec<&'a Expr>,
} }
impl<'a> Checker<'a> { impl<'a> Checker<'a> {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new( pub(crate) fn new(
settings: &'a Settings, settings: &'a Settings,
noqa_line_for: &'a NoqaMapping, noqa_line_for: &'a NoqaMapping,
noqa: flags::Noqa, noqa: flags::Noqa,
@ -117,12 +117,12 @@ impl<'a> Checker<'a> {
impl<'a> Checker<'a> { impl<'a> Checker<'a> {
/// Return `true` if a patch should be generated under the given autofix /// Return `true` if a patch should be generated under the given autofix
/// `Mode`. /// `Mode`.
pub fn patch(&self, code: Rule) -> bool { pub(crate) fn patch(&self, code: Rule) -> bool {
self.settings.rules.should_fix(code) self.settings.rules.should_fix(code)
} }
/// Return `true` if a `Rule` is disabled by a `noqa` directive. /// Return `true` if a `Rule` is disabled by a `noqa` directive.
pub fn rule_is_ignored(&self, code: Rule, offset: TextSize) -> bool { pub(crate) fn rule_is_ignored(&self, code: Rule, offset: TextSize) -> 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
@ -137,7 +137,7 @@ impl<'a> Checker<'a> {
} }
/// Create a [`Generator`] to generate source code based on the current AST state. /// Create a [`Generator`] to generate source code based on the current AST state.
pub fn generator(&self) -> Generator { pub(crate) fn generator(&self) -> Generator {
fn quote_style(context: &Context, locator: &Locator, indexer: &Indexer) -> Option<Quote> { fn quote_style(context: &Context, locator: &Locator, indexer: &Indexer) -> Option<Quote> {
if !context.in_f_string() { if !context.in_f_string() {
return None; return None;
@ -1253,7 +1253,7 @@ where
level, level,
module, module,
self.module_path, self.module_path,
&self.settings.flake8_tidy_imports.ban_relative_imports, self.settings.flake8_tidy_imports.ban_relative_imports,
) )
{ {
self.diagnostics.push(diagnostic); self.diagnostics.push(diagnostic);
@ -4528,7 +4528,7 @@ impl<'a> Checker<'a> {
} }
/// Visit an [`Expr`], and treat it as a type definition. /// Visit an [`Expr`], and treat it as a type definition.
pub fn visit_type_definition(&mut self, expr: &'a Expr) { pub(crate) fn visit_type_definition(&mut self, expr: &'a Expr) {
let snapshot = self.ctx.flags; let snapshot = self.ctx.flags;
self.ctx.flags |= ContextFlags::TYPE_DEFINITION; self.ctx.flags |= ContextFlags::TYPE_DEFINITION;
self.visit_expr(expr); self.visit_expr(expr);
@ -4536,7 +4536,7 @@ impl<'a> Checker<'a> {
} }
/// Visit an [`Expr`], and treat it as _not_ a type definition. /// Visit an [`Expr`], and treat it as _not_ a type definition.
pub fn visit_non_type_definition(&mut self, expr: &'a Expr) { pub(crate) fn visit_non_type_definition(&mut self, expr: &'a Expr) {
let snapshot = self.ctx.flags; let snapshot = self.ctx.flags;
self.ctx.flags -= ContextFlags::TYPE_DEFINITION; self.ctx.flags -= ContextFlags::TYPE_DEFINITION;
self.visit_expr(expr); self.visit_expr(expr);
@ -4546,7 +4546,7 @@ impl<'a> Checker<'a> {
/// Visit an [`Expr`], and treat it as a boolean test. This is useful for detecting whether an /// Visit an [`Expr`], and treat it as a boolean test. This is useful for detecting whether an
/// expressions return value is significant, or whether the calling context only relies on /// expressions return value is significant, or whether the calling context only relies on
/// its truthiness. /// its truthiness.
pub fn visit_boolean_test(&mut self, expr: &'a Expr) { pub(crate) fn visit_boolean_test(&mut self, expr: &'a Expr) {
let snapshot = self.ctx.flags; let snapshot = self.ctx.flags;
self.ctx.flags |= ContextFlags::BOOLEAN_TEST; self.ctx.flags |= ContextFlags::BOOLEAN_TEST;
self.visit_expr(expr); self.visit_expr(expr);

View File

@ -14,7 +14,7 @@ use crate::importer::insertion::Insertion;
mod insertion; mod insertion;
pub struct Importer<'a> { pub(crate) struct Importer<'a> {
python_ast: &'a Suite, python_ast: &'a Suite,
locator: &'a Locator<'a>, locator: &'a Locator<'a>,
stylist: &'a Stylist<'a>, stylist: &'a Stylist<'a>,
@ -22,7 +22,11 @@ pub struct Importer<'a> {
} }
impl<'a> Importer<'a> { impl<'a> Importer<'a> {
pub fn new(python_ast: &'a Suite, locator: &'a Locator<'a>, stylist: &'a Stylist<'a>) -> Self { pub(crate) fn new(
python_ast: &'a Suite,
locator: &'a Locator<'a>,
stylist: &'a Stylist<'a>,
) -> Self {
Self { Self {
python_ast, python_ast,
locator, locator,
@ -32,7 +36,7 @@ impl<'a> Importer<'a> {
} }
/// Visit a top-level import statement. /// Visit a top-level import statement.
pub fn visit_import(&mut self, import: &'a Stmt) { pub(crate) fn visit_import(&mut self, import: &'a Stmt) {
self.ordered_imports.push(import); self.ordered_imports.push(import);
} }
@ -49,7 +53,7 @@ impl<'a> Importer<'a> {
/// If there are no existing imports, the new import will be added at the top /// If there are no existing imports, the new import will be added at the top
/// of the file. Otherwise, it will be added after the most recent top-level /// of the file. Otherwise, it will be added after the most recent top-level
/// import statement. /// import statement.
pub fn add_import(&self, import: &AnyImport, at: TextSize) -> Edit { pub(crate) fn add_import(&self, import: &AnyImport, at: TextSize) -> Edit {
let required_import = import.to_string(); let required_import = import.to_string();
if let Some(stmt) = self.preceding_import(at) { if let Some(stmt) = self.preceding_import(at) {
// Insert after the last top-level import. // Insert after the last top-level import.
@ -64,7 +68,7 @@ impl<'a> Importer<'a> {
/// Return the top-level [`Stmt`] that imports the given module using `Stmt::ImportFrom` /// Return the top-level [`Stmt`] that imports the given module using `Stmt::ImportFrom`
/// preceding the given position, if any. /// preceding the given position, if any.
pub fn find_import_from(&self, module: &str, at: TextSize) -> Option<&Stmt> { pub(crate) fn find_import_from(&self, module: &str, at: TextSize) -> Option<&Stmt> {
let mut import_from = None; let mut import_from = None;
for stmt in &self.ordered_imports { for stmt in &self.ordered_imports {
if stmt.start() >= at { if stmt.start() >= at {
@ -87,7 +91,7 @@ impl<'a> Importer<'a> {
} }
/// Add the given member to an existing `Stmt::ImportFrom` statement. /// Add the given member to an existing `Stmt::ImportFrom` statement.
pub fn add_member(&self, stmt: &Stmt, member: &str) -> Result<Edit> { pub(crate) fn add_member(&self, stmt: &Stmt, member: &str) -> Result<Edit> {
let mut tree = match_module(self.locator.slice(stmt.range()))?; let mut tree = match_module(self.locator.slice(stmt.range()))?;
let import_from = match_import_from(&mut tree)?; let import_from = match_import_from(&mut tree)?;
let aliases = match_aliases(import_from)?; let aliases = match_aliases(import_from)?;

View File

@ -2,11 +2,12 @@ use rustc_hash::FxHashMap;
use rustpython_parser::ast::{Expr, Ranged}; use rustpython_parser::ast::{Expr, Ranged};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::checkers::ast::Checker;
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation, CacheKey}; use ruff_macros::{derive_message_formats, violation, CacheKey};
use ruff_python_ast::call_path::from_qualified_name; use ruff_python_ast::call_path::from_qualified_name;
use crate::checkers::ast::Checker;
pub type Settings = FxHashMap<String, ApiBan>; pub type Settings = FxHashMap<String, ApiBan>;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, CacheKey)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, CacheKey)]
@ -49,7 +50,7 @@ impl Violation for BannedApi {
} }
/// TID251 /// TID251
pub fn name_is_banned<T>(checker: &mut Checker, name: String, located: &T) pub(crate) fn name_is_banned<T>(checker: &mut Checker, name: String, located: &T)
where where
T: Ranged, T: Ranged,
{ {
@ -66,7 +67,7 @@ where
} }
/// TID251 /// TID251
pub fn name_or_parent_is_banned<T>(checker: &mut Checker, name: &str, located: &T) pub(crate) fn name_or_parent_is_banned<T>(checker: &mut Checker, name: &str, located: &T)
where where
T: Ranged, T: Ranged,
{ {
@ -93,7 +94,7 @@ where
} }
/// TID251 /// TID251
pub fn banned_attribute_access(checker: &mut Checker, expr: &Expr) { pub(crate) fn banned_attribute_access(checker: &mut Checker, expr: &Expr) {
let banned_api = &checker.settings.flake8_tidy_imports.banned_api; let banned_api = &checker.settings.flake8_tidy_imports.banned_api;
if let Some((banned_path, ban)) = checker.ctx.resolve_call_path(expr).and_then(|call_path| { if let Some((banned_path, ban)) = checker.ctx.resolve_call_path(expr).and_then(|call_path| {
banned_api banned_api

View File

@ -121,25 +121,20 @@ fn fix_banned_relative_import(
} }
/// TID252 /// TID252
pub fn banned_relative_import( pub(crate) fn banned_relative_import(
checker: &Checker, checker: &Checker,
stmt: &Stmt, stmt: &Stmt,
level: Option<u32>, level: Option<u32>,
module: Option<&str>, module: Option<&str>,
module_path: Option<&[String]>, module_path: Option<&[String]>,
strictness: &Strictness, strictness: Strictness,
) -> Option<Diagnostic> { ) -> Option<Diagnostic> {
let strictness_level = match strictness { let strictness_level = match strictness {
Strictness::All => 0, Strictness::All => 0,
Strictness::Parents => 1, Strictness::Parents => 1,
}; };
if level? > strictness_level { if level? > strictness_level {
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(RelativeImports { strictness }, stmt.range());
RelativeImports {
strictness: *strictness,
},
stmt.range(),
);
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
if let Some(fix) = if let Some(fix) =
fix_banned_relative_import(stmt, level, module, module_path, checker.generator()) fix_banned_relative_import(stmt, level, module, module_path, checker.generator())

View File

@ -76,7 +76,7 @@ def main(*, name: str, prefix: str, code: str, linter: str) -> None:
contents = rules_mod.read_text() contents = rules_mod.read_text()
parts = contents.split("\n\n") parts = contents.split("\n\n")
new_pub_use = f"pub use {rule_name_snake}::{{{rule_name_snake}, {name}}}" new_pub_use = f"pub(crate) use {rule_name_snake}::{{{rule_name_snake}, {name}}}"
new_mod = f"mod {rule_name_snake};" new_mod = f"mod {rule_name_snake};"
if len(parts) == 2: if len(parts) == 2:
@ -105,6 +105,7 @@ use crate::checkers::ast::Checker;
#[violation] #[violation]
pub struct {name}; pub struct {name};
impl Violation for {name} {{ impl Violation for {name} {{
#[derive_message_formats] #[derive_message_formats]
fn message(&self) -> String {{ fn message(&self) -> String {{
@ -117,7 +118,7 @@ impl Violation for {name} {{
fp.write( fp.write(
f""" f"""
/// {prefix}{code} /// {prefix}{code}
pub fn {rule_name_snake}(checker: &mut Checker) {{}} pub(crate) fn {rule_name_snake}(checker: &mut Checker) {{}}
""", """,
) )