mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 18:28:24 +00:00
Move CallPath
into its own module (#3847)
This commit is contained in:
parent
2f90157ce2
commit
d822e08111
34 changed files with 129 additions and 102 deletions
63
crates/ruff_python_ast/src/call_path.rs
Normal file
63
crates/ruff_python_ast/src/call_path.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
use rustpython_parser::ast::{Expr, ExprKind};
|
||||
use smallvec::smallvec;
|
||||
|
||||
/// A representation of a qualified name, like `typing.List`.
|
||||
pub type CallPath<'a> = smallvec::SmallVec<[&'a str; 8]>;
|
||||
|
||||
fn collect_call_path_inner<'a>(expr: &'a Expr, parts: &mut CallPath<'a>) -> bool {
|
||||
match &expr.node {
|
||||
ExprKind::Attribute { value, attr, .. } => {
|
||||
if collect_call_path_inner(value, parts) {
|
||||
parts.push(attr);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
ExprKind::Name { id, .. } => {
|
||||
parts.push(id);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an `Expr` to its [`CallPath`] segments (like `["typing", "List"]`).
|
||||
pub fn collect_call_path(expr: &Expr) -> CallPath {
|
||||
let mut segments = smallvec![];
|
||||
collect_call_path_inner(expr, &mut segments);
|
||||
segments
|
||||
}
|
||||
|
||||
/// Convert an `Expr` to its call path (like `List`, or `typing.List`).
|
||||
pub fn compose_call_path(expr: &Expr) -> Option<String> {
|
||||
let call_path = collect_call_path(expr);
|
||||
if call_path.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(format_call_path(&call_path))
|
||||
}
|
||||
}
|
||||
|
||||
/// Format a call path for display.
|
||||
pub fn format_call_path(call_path: &[&str]) -> String {
|
||||
if call_path
|
||||
.first()
|
||||
.expect("Unable to format empty call path")
|
||||
.is_empty()
|
||||
{
|
||||
call_path[1..].join(".")
|
||||
} else {
|
||||
call_path.join(".")
|
||||
}
|
||||
}
|
||||
|
||||
/// Split a fully-qualified name (like `typing.List`) into (`typing`, `List`).
|
||||
pub fn to_call_path(target: &str) -> CallPath {
|
||||
if target.contains('.') {
|
||||
target.split('.').collect()
|
||||
} else {
|
||||
// Special-case: for builtins, return `["", "int"]` instead of `["int"]`.
|
||||
smallvec!["", target]
|
||||
}
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
//! An equivalent object hierarchy to the [`Expr`] hierarchy, but with the
|
||||
//! ability to compare expressions for equality (via [`Eq`] and [`Hash`]).
|
||||
|
||||
use num_bigint::BigInt;
|
||||
use rustpython_parser::ast::{
|
||||
Alias, Arg, Arguments, Boolop, Cmpop, Comprehension, Constant, Excepthandler,
|
||||
ExcepthandlerKind, Expr, ExprContext, ExprKind, Keyword, MatchCase, Operator, Pattern,
|
||||
PatternKind, Stmt, StmtKind, Unaryop, Withitem,
|
||||
};
|
||||
|
||||
use num_bigint::BigInt;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
|
||||
pub enum ComparableExprContext {
|
||||
Load,
|
||||
|
|
|
@ -12,9 +12,10 @@ use crate::binding::{
|
|||
Binding, BindingId, BindingKind, Bindings, Exceptions, ExecutionContext, FromImportation,
|
||||
Importation, SubmoduleImportation,
|
||||
};
|
||||
use crate::helpers::{collect_call_path, from_relative_import};
|
||||
use crate::call_path::{collect_call_path, CallPath};
|
||||
use crate::helpers::from_relative_import;
|
||||
use crate::scope::{Scope, ScopeId, ScopeKind, ScopeStack, Scopes};
|
||||
use crate::types::{CallPath, RefEquality};
|
||||
use crate::types::RefEquality;
|
||||
use crate::typing::AnnotationKind;
|
||||
use crate::visibility::{module_visibility, Modifier, VisibleScope};
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use rustpython_parser::ast::Expr;
|
||||
|
||||
use crate::call_path::to_call_path;
|
||||
use crate::context::Context;
|
||||
use crate::helpers::{map_callable, to_call_path};
|
||||
use crate::helpers::map_callable;
|
||||
use crate::scope::{Scope, ScopeKind};
|
||||
|
||||
const CLASS_METHODS: [&str; 3] = ["__new__", "__init_subclass__", "__class_getitem__"];
|
||||
|
|
|
@ -10,11 +10,12 @@ use rustpython_parser::ast::{
|
|||
KeywordData, Located, Location, MatchCase, Pattern, PatternKind, Stmt, StmtKind,
|
||||
};
|
||||
use rustpython_parser::{lexer, Mode, Tok};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::call_path::CallPath;
|
||||
use crate::context::Context;
|
||||
use crate::source_code::{Generator, Indexer, Locator, Stylist};
|
||||
use crate::types::{CallPath, Range};
|
||||
use crate::types::Range;
|
||||
use crate::visitor;
|
||||
use crate::visitor::Visitor;
|
||||
|
||||
|
@ -49,54 +50,6 @@ pub fn unparse_constant(constant: &Constant, stylist: &Stylist) -> String {
|
|||
generator.generate()
|
||||
}
|
||||
|
||||
fn collect_call_path_inner<'a>(expr: &'a Expr, parts: &mut CallPath<'a>) -> bool {
|
||||
match &expr.node {
|
||||
ExprKind::Attribute { value, attr, .. } => {
|
||||
if collect_call_path_inner(value, parts) {
|
||||
parts.push(attr);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
ExprKind::Name { id, .. } => {
|
||||
parts.push(id);
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an `Expr` to its [`CallPath`] segments (like `["typing", "List"]`).
|
||||
pub fn collect_call_path(expr: &Expr) -> CallPath {
|
||||
let mut segments = smallvec![];
|
||||
collect_call_path_inner(expr, &mut segments);
|
||||
segments
|
||||
}
|
||||
|
||||
/// Convert an `Expr` to its call path (like `List`, or `typing.List`).
|
||||
pub fn compose_call_path(expr: &Expr) -> Option<String> {
|
||||
let call_path = collect_call_path(expr);
|
||||
if call_path.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(format_call_path(&call_path))
|
||||
}
|
||||
}
|
||||
|
||||
/// Format a call path for display.
|
||||
pub fn format_call_path(call_path: &[&str]) -> String {
|
||||
if call_path
|
||||
.first()
|
||||
.expect("Unable to format empty call path")
|
||||
.is_empty()
|
||||
{
|
||||
call_path[1..].join(".")
|
||||
} else {
|
||||
call_path.join(".")
|
||||
}
|
||||
}
|
||||
|
||||
/// Return `true` if the `Expr` contains a reference to `${module}.${target}`.
|
||||
pub fn contains_call_path(ctx: &Context, expr: &Expr, target: &[&str]) -> bool {
|
||||
any_over_expr(expr, &|expr| {
|
||||
|
@ -748,15 +701,6 @@ pub fn format_import_from_member(
|
|||
full_name
|
||||
}
|
||||
|
||||
/// Split a target string (like `typing.List`) into (`typing`, `List`).
|
||||
pub fn to_call_path(target: &str) -> CallPath {
|
||||
if target.contains('.') {
|
||||
target.split('.').collect()
|
||||
} else {
|
||||
smallvec!["", target]
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a module path from a (package, path) pair.
|
||||
///
|
||||
/// For example, if the package is `foo/bar` and the path is `foo/bar/baz.py`,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pub mod all;
|
||||
pub mod binding;
|
||||
pub mod branch_detection;
|
||||
pub mod call_path;
|
||||
pub mod cast;
|
||||
pub mod comparable;
|
||||
pub mod context;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use crate::context::Context;
|
||||
use crate::helpers::collect_call_path;
|
||||
use rustpython_parser::ast::{Expr, ExprKind};
|
||||
|
||||
use crate::call_path::collect_call_path;
|
||||
use crate::context::Context;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum LoggingLevel {
|
||||
Debug,
|
||||
|
|
|
@ -208,9 +208,10 @@ impl Utf8Index {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::source_code::locator::{AsciiIndex, Index, Utf8Index};
|
||||
use rustpython_parser::ast::Location;
|
||||
|
||||
use crate::source_code::locator::{AsciiIndex, Index, Utf8Index};
|
||||
|
||||
fn index_ascii(content: &str) -> AsciiIndex {
|
||||
match Index::from(content) {
|
||||
Index::Ascii(ascii) => ascii,
|
||||
|
|
|
@ -8,9 +8,9 @@ use rustpython_parser::ast::Location;
|
|||
use rustpython_parser::lexer::LexResult;
|
||||
use rustpython_parser::Tok;
|
||||
|
||||
use crate::source_code::Locator;
|
||||
use ruff_rustpython::vendor;
|
||||
|
||||
use crate::source_code::Locator;
|
||||
use crate::str::leading_quote;
|
||||
use crate::types::Range;
|
||||
|
||||
|
@ -213,11 +213,12 @@ fn detect_line_ending(contents: &str) -> Option<LineEnding> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::source_code::stylist::{detect_line_ending, Indentation, LineEnding, Quote};
|
||||
use crate::source_code::{Locator, Stylist};
|
||||
use rustpython_parser::lexer::lex;
|
||||
use rustpython_parser::Mode;
|
||||
|
||||
use crate::source_code::stylist::{detect_line_ending, Indentation, LineEnding, Quote};
|
||||
use crate::source_code::{Locator, Stylist};
|
||||
|
||||
#[test]
|
||||
fn indentation() {
|
||||
let contents = r#"x = 1"#;
|
||||
|
|
|
@ -97,5 +97,3 @@ impl<'a> From<&RefEquality<'a, Expr>> for &'a Expr {
|
|||
r.0
|
||||
}
|
||||
}
|
||||
|
||||
pub type CallPath<'a> = smallvec::SmallVec<[&'a str; 8]>;
|
||||
|
|
|
@ -2,9 +2,10 @@ use std::path::Path;
|
|||
|
||||
use rustpython_parser::ast::{Expr, Stmt, StmtKind};
|
||||
|
||||
use crate::call_path::collect_call_path;
|
||||
use crate::call_path::CallPath;
|
||||
use crate::context::Context;
|
||||
use crate::helpers::{collect_call_path, map_callable};
|
||||
use crate::types::CallPath;
|
||||
use crate::helpers::map_callable;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Modifier {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue