mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 04:45:01 +00:00

## Summary This PR exposes our `is_expression_parenthesized` logic such that we can use it to expand expressions when autofixing to include their parenthesized ranges. This solution has a few drawbacks: (1) we need to compute parenthesized ranges in more places, which also relies on backwards lexing; and (2) we need to make use of this in any relevant fixes. However, I still think it's worth pursuing. On (1), the implementation is very contained, so IMO we can easily swap this out for a more performant solution in the future if needed. On (2), this improves correctness and fixes some bad syntax errors detected by fuzzing, which means it has value even if it's not as robust as an _actual_ `ParenthesizedExpression` node in the AST itself. Closes https://github.com/astral-sh/ruff/issues/4925. ## Test Plan `cargo test` with new cases that previously failed the fuzzer.
86 lines
1.6 KiB
Rust
86 lines
1.6 KiB
Rust
use ruff_text_size::{TextRange, TextSize};
|
|
use std::path::Path;
|
|
|
|
pub mod all;
|
|
pub mod call_path;
|
|
pub mod comparable;
|
|
pub mod docstrings;
|
|
mod expression;
|
|
pub mod hashable;
|
|
pub mod helpers;
|
|
pub mod identifier;
|
|
pub mod imports;
|
|
pub mod node;
|
|
mod nodes;
|
|
pub mod parenthesize;
|
|
pub mod relocate;
|
|
pub mod statement_visitor;
|
|
pub mod stmt_if;
|
|
pub mod str;
|
|
pub mod traversal;
|
|
pub mod types;
|
|
pub mod visitor;
|
|
pub mod whitespace;
|
|
|
|
pub use expression::*;
|
|
pub use nodes::*;
|
|
|
|
pub trait Ranged {
|
|
fn range(&self) -> TextRange;
|
|
|
|
fn start(&self) -> TextSize {
|
|
self.range().start()
|
|
}
|
|
|
|
fn end(&self) -> TextSize {
|
|
self.range().end()
|
|
}
|
|
}
|
|
|
|
impl Ranged for TextRange {
|
|
fn range(&self) -> TextRange {
|
|
*self
|
|
}
|
|
}
|
|
|
|
impl<T> Ranged for &T
|
|
where
|
|
T: Ranged,
|
|
{
|
|
fn range(&self) -> TextRange {
|
|
T::range(self)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
|
pub enum PySourceType {
|
|
#[default]
|
|
Python,
|
|
Stub,
|
|
Jupyter,
|
|
}
|
|
|
|
impl PySourceType {
|
|
pub const fn is_python(&self) -> bool {
|
|
matches!(self, PySourceType::Python)
|
|
}
|
|
|
|
pub const fn is_stub(&self) -> bool {
|
|
matches!(self, PySourceType::Stub)
|
|
}
|
|
|
|
pub const fn is_jupyter(&self) -> bool {
|
|
matches!(self, PySourceType::Jupyter)
|
|
}
|
|
}
|
|
|
|
impl From<&Path> for PySourceType {
|
|
fn from(path: &Path) -> Self {
|
|
match path.extension() {
|
|
Some(ext) if ext == "pyi" => PySourceType::Stub,
|
|
Some(ext) if ext == "ipynb" => PySourceType::Jupyter,
|
|
_ => PySourceType::Python,
|
|
}
|
|
}
|
|
}
|