Compare commits
2 Commits
0.9.3
...
dhruv/form
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce4d4ae6ac | ||
|
|
128414cd95 |
@@ -64,28 +64,15 @@ pub(crate) fn avoidable_escaped_quote(checker: &mut Checker, string_like: String
|
||||
|
||||
let mut rule_checker = AvoidableEscapedQuoteChecker::new(checker.locator(), checker.settings);
|
||||
|
||||
match string_like {
|
||||
StringLike::String(expr) => {
|
||||
for string_literal in &expr.value {
|
||||
for part in string_like.parts() {
|
||||
match part {
|
||||
ast::StringLikePart::String(string_literal) => {
|
||||
rule_checker.visit_string_literal(string_literal);
|
||||
}
|
||||
}
|
||||
StringLike::Bytes(expr) => {
|
||||
for bytes_literal in &expr.value {
|
||||
ast::StringLikePart::Bytes(bytes_literal) => {
|
||||
rule_checker.visit_bytes_literal(bytes_literal);
|
||||
}
|
||||
}
|
||||
StringLike::FString(expr) => {
|
||||
for part in &expr.value {
|
||||
match part {
|
||||
ast::FStringPart::Literal(string_literal) => {
|
||||
rule_checker.visit_string_literal(string_literal);
|
||||
}
|
||||
ast::FStringPart::FString(f_string) => {
|
||||
rule_checker.visit_f_string(f_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::StringLikePart::FString(f_string) => rule_checker.visit_f_string(f_string),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -454,11 +454,10 @@ pub(crate) fn check_string_quotes(checker: &mut Checker, string_like: StringLike
|
||||
return;
|
||||
}
|
||||
|
||||
let ranges: Vec<TextRange> = match string_like {
|
||||
StringLike::String(node) => node.value.iter().map(Ranged::range).collect(),
|
||||
StringLike::Bytes(node) => node.value.iter().map(Ranged::range).collect(),
|
||||
StringLike::FString(node) => node.value.iter().map(Ranged::range).collect(),
|
||||
};
|
||||
let ranges = string_like
|
||||
.parts()
|
||||
.map(|part| part.range())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if checker.semantic().in_pep_257_docstring() {
|
||||
if checker.enabled(Rule::BadQuotesDocstring) {
|
||||
|
||||
@@ -53,39 +53,30 @@ pub(crate) fn unnecessary_escaped_quote(checker: &mut Checker, string_like: Stri
|
||||
|
||||
let locator = checker.locator();
|
||||
|
||||
match string_like {
|
||||
StringLike::String(expr) => {
|
||||
for string in &expr.value {
|
||||
for part in string_like.parts() {
|
||||
match part {
|
||||
ast::StringLikePart::String(string_literal) => {
|
||||
if let Some(diagnostic) = check_string_or_bytes(
|
||||
locator,
|
||||
string.range(),
|
||||
AnyStringKind::from(string.flags),
|
||||
string_literal.range(),
|
||||
AnyStringKind::from(string_literal.flags),
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
StringLike::Bytes(expr) => {
|
||||
for bytes in &expr.value {
|
||||
if let Some(diagnostic) =
|
||||
check_string_or_bytes(locator, bytes.range(), AnyStringKind::from(bytes.flags))
|
||||
{
|
||||
ast::StringLikePart::Bytes(bytes_literal) => {
|
||||
if let Some(diagnostic) = check_string_or_bytes(
|
||||
locator,
|
||||
bytes_literal.range(),
|
||||
AnyStringKind::from(bytes_literal.flags),
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
StringLike::FString(expr) => {
|
||||
for part in &expr.value {
|
||||
if let Some(diagnostic) = match part {
|
||||
ast::FStringPart::Literal(string) => check_string_or_bytes(
|
||||
locator,
|
||||
string.range(),
|
||||
AnyStringKind::from(string.flags),
|
||||
),
|
||||
ast::FStringPart::FString(f_string) => check_f_string(locator, f_string),
|
||||
} {
|
||||
ast::StringLikePart::FString(f_string) => {
|
||||
if let Some(diagnostic) = check_f_string(locator, f_string) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,48 +192,32 @@ pub(crate) fn ambiguous_unicode_character_string(checker: &mut Checker, string_l
|
||||
Context::String
|
||||
};
|
||||
|
||||
match string_like {
|
||||
StringLike::String(node) => {
|
||||
for literal in &node.value {
|
||||
let text = checker.locator().slice(literal);
|
||||
for part in string_like.parts() {
|
||||
match part {
|
||||
ast::StringLikePart::String(string_literal) => {
|
||||
let text = checker.locator().slice(string_literal);
|
||||
ambiguous_unicode_character(
|
||||
&mut checker.diagnostics,
|
||||
text,
|
||||
literal.range(),
|
||||
string_literal.range(),
|
||||
context,
|
||||
checker.settings,
|
||||
);
|
||||
}
|
||||
}
|
||||
StringLike::FString(node) => {
|
||||
for part in &node.value {
|
||||
match part {
|
||||
ast::FStringPart::Literal(literal) => {
|
||||
let text = checker.locator().slice(literal);
|
||||
ambiguous_unicode_character(
|
||||
&mut checker.diagnostics,
|
||||
text,
|
||||
literal.range(),
|
||||
context,
|
||||
checker.settings,
|
||||
);
|
||||
}
|
||||
ast::FStringPart::FString(f_string) => {
|
||||
for literal in f_string.literals() {
|
||||
let text = checker.locator().slice(literal);
|
||||
ambiguous_unicode_character(
|
||||
&mut checker.diagnostics,
|
||||
text,
|
||||
literal.range(),
|
||||
context,
|
||||
checker.settings,
|
||||
);
|
||||
}
|
||||
}
|
||||
ast::StringLikePart::Bytes(_) => {}
|
||||
ast::StringLikePart::FString(f_string) => {
|
||||
for literal in f_string.literals() {
|
||||
let text = checker.locator().slice(literal);
|
||||
ambiguous_unicode_character(
|
||||
&mut checker.diagnostics,
|
||||
text,
|
||||
literal.range(),
|
||||
context,
|
||||
checker.settings,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
StringLike::Bytes(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::iter::FusedIterator;
|
||||
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::AnyNodeRef;
|
||||
@@ -394,9 +396,8 @@ impl LiteralExpressionRef<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// An enum that holds a reference to a string-like literal from the AST.
|
||||
/// This includes string literals, bytes literals, and the literal parts of
|
||||
/// f-strings.
|
||||
/// An enum that holds a reference to a string-like expression from the AST. This includes string
|
||||
/// literals, bytes literals, and f-strings.
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum StringLike<'a> {
|
||||
String(&'a ast::ExprStringLiteral),
|
||||
@@ -404,6 +405,17 @@ pub enum StringLike<'a> {
|
||||
FString(&'a ast::ExprFString),
|
||||
}
|
||||
|
||||
impl<'a> StringLike<'a> {
|
||||
/// Returns an iterator over the [`StringLikePart`] contained in this string-like expression.
|
||||
pub fn parts(&self) -> StringLikePartIter<'_> {
|
||||
match self {
|
||||
StringLike::String(expr) => StringLikePartIter::String(expr.value.iter()),
|
||||
StringLike::Bytes(expr) => StringLikePartIter::Bytes(expr.value.iter()),
|
||||
StringLike::FString(expr) => StringLikePartIter::FString(expr.value.iter()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::ExprStringLiteral> for StringLike<'a> {
|
||||
fn from(value: &'a ast::ExprStringLiteral) -> Self {
|
||||
StringLike::String(value)
|
||||
@@ -431,3 +443,81 @@ impl Ranged for StringLike<'_> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An enum that holds a reference to an individual part of a string-like expression.
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum StringLikePart<'a> {
|
||||
String(&'a ast::StringLiteral),
|
||||
Bytes(&'a ast::BytesLiteral),
|
||||
FString(&'a ast::FString),
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::StringLiteral> for StringLikePart<'a> {
|
||||
fn from(value: &'a ast::StringLiteral) -> Self {
|
||||
StringLikePart::String(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::BytesLiteral> for StringLikePart<'a> {
|
||||
fn from(value: &'a ast::BytesLiteral) -> Self {
|
||||
StringLikePart::Bytes(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a ast::FString> for StringLikePart<'a> {
|
||||
fn from(value: &'a ast::FString) -> Self {
|
||||
StringLikePart::FString(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ranged for StringLikePart<'_> {
|
||||
fn range(&self) -> TextRange {
|
||||
match self {
|
||||
StringLikePart::String(part) => part.range(),
|
||||
StringLikePart::Bytes(part) => part.range(),
|
||||
StringLikePart::FString(part) => part.range(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over all the [`StringLikePart`] of a string-like expression.
|
||||
///
|
||||
/// This is created by the [`StringLike::parts`] method.
|
||||
pub enum StringLikePartIter<'a> {
|
||||
String(std::slice::Iter<'a, ast::StringLiteral>),
|
||||
Bytes(std::slice::Iter<'a, ast::BytesLiteral>),
|
||||
FString(std::slice::Iter<'a, ast::FStringPart>),
|
||||
}
|
||||
|
||||
impl<'a> Iterator for StringLikePartIter<'a> {
|
||||
type Item = StringLikePart<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let part = match self {
|
||||
StringLikePartIter::String(inner) => StringLikePart::String(inner.next()?),
|
||||
StringLikePartIter::Bytes(inner) => StringLikePart::Bytes(inner.next()?),
|
||||
StringLikePartIter::FString(inner) => {
|
||||
let part = inner.next()?;
|
||||
match part {
|
||||
ast::FStringPart::Literal(string_literal) => {
|
||||
StringLikePart::String(string_literal)
|
||||
}
|
||||
ast::FStringPart::FString(f_string) => StringLikePart::FString(f_string),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Some(part)
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
match self {
|
||||
StringLikePartIter::String(inner) => inner.size_hint(),
|
||||
StringLikePartIter::Bytes(inner) => inner.size_hint(),
|
||||
StringLikePartIter::FString(inner) => inner.size_hint(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FusedIterator for StringLikePartIter<'_> {}
|
||||
impl ExactSizeIterator for StringLikePartIter<'_> {}
|
||||
|
||||
@@ -1087,6 +1087,24 @@ pub struct FStringFormatSpec {
|
||||
pub elements: Vec<FStringElement>,
|
||||
}
|
||||
|
||||
impl FStringFormatSpec {
|
||||
/// Returns an iterator over all the [`FStringLiteralElement`] nodes contained in this format
|
||||
/// spec of the f-string.
|
||||
pub fn literals(&self) -> impl Iterator<Item = &FStringLiteralElement> {
|
||||
self.elements
|
||||
.iter()
|
||||
.filter_map(|element| element.as_literal())
|
||||
}
|
||||
|
||||
/// Returns an iterator over all the [`FStringExpressionElement`] nodes contained in this
|
||||
/// format spec of the f-string.
|
||||
pub fn expressions(&self) -> impl Iterator<Item = &FStringExpressionElement> {
|
||||
self.elements
|
||||
.iter()
|
||||
.filter_map(|element| element.as_expression())
|
||||
}
|
||||
}
|
||||
|
||||
impl Ranged for FStringFormatSpec {
|
||||
fn range(&self) -> TextRange {
|
||||
self.range
|
||||
|
||||
Reference in New Issue
Block a user