Use CompactString for Identifier (#12101)

This commit is contained in:
Micha Reiser 2024-07-01 10:06:02 +02:00 committed by GitHub
parent db6ee74cbe
commit 5109b50bb3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
474 changed files with 4953 additions and 4776 deletions

29
Cargo.lock generated
View file

@ -232,6 +232,15 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "castaway"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc"
dependencies = [
"rustversion",
]
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.95" version = "1.0.95"
@ -436,6 +445,20 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "compact_str"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f"
dependencies = [
"castaway",
"cfg-if",
"itoa",
"ryu",
"serde",
"static_assertions",
]
[[package]] [[package]]
name = "console" name = "console"
version = "0.15.8" version = "0.15.8"
@ -1900,7 +1923,6 @@ dependencies = [
"rustc-hash 2.0.0", "rustc-hash 2.0.0",
"salsa", "salsa",
"smallvec", "smallvec",
"smol_str",
"tracing", "tracing",
] ]
@ -2259,13 +2281,17 @@ version = "0.0.0"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"bitflags 2.6.0", "bitflags 2.6.0",
"compact_str",
"is-macro", "is-macro",
"itertools 0.13.0", "itertools 0.13.0",
"once_cell", "once_cell",
"ruff_cache",
"ruff_macros",
"ruff_python_trivia", "ruff_python_trivia",
"ruff_source_file", "ruff_source_file",
"ruff_text_size", "ruff_text_size",
"rustc-hash 2.0.0", "rustc-hash 2.0.0",
"schemars",
"serde", "serde",
] ]
@ -2352,6 +2378,7 @@ dependencies = [
"anyhow", "anyhow",
"bitflags 2.6.0", "bitflags 2.6.0",
"bstr", "bstr",
"compact_str",
"insta", "insta",
"memchr", "memchr",
"ruff_python_ast", "ruff_python_ast",

View file

@ -55,6 +55,7 @@ colored = { version = "2.1.0" }
console_error_panic_hook = { version = "0.1.7" } console_error_panic_hook = { version = "0.1.7" }
console_log = { version = "1.0.0" } console_log = { version = "1.0.0" }
countme = { version = "3.0.1" } countme = { version = "3.0.1" }
compact_str = "0.7.1"
criterion = { version = "0.5.1", default-features = false } criterion = { version = "0.5.1", default-features = false }
crossbeam = { version = "0.8.4" } crossbeam = { version = "0.8.4" }
dashmap = { version = "5.5.3" } dashmap = { version = "5.5.3" }

View file

@ -1,6 +1,4 @@
use std::fmt::Formatter;
use std::hash::BuildHasherDefault; use std::hash::BuildHasherDefault;
use std::ops::Deref;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use rustc_hash::{FxHashSet, FxHasher}; use rustc_hash::{FxHashSet, FxHasher};
@ -68,41 +66,3 @@ impl Workspace {
self.open_files.contains(&file_id) self.open_files.contains(&file_id)
} }
} }
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Name(smol_str::SmolStr);
impl Name {
#[inline]
pub fn new(name: &str) -> Self {
Self(smol_str::SmolStr::new(name))
}
pub fn as_str(&self) -> &str {
self.0.as_str()
}
}
impl Deref for Name {
type Target = str;
#[inline]
fn deref(&self) -> &Self::Target {
self.as_str()
}
}
impl<T> From<T> for Name
where
T: Into<smol_str::SmolStr>,
{
fn from(value: T) -> Self {
Self(value.into())
}
}
impl std::fmt::Display for Name {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}

View file

@ -11,7 +11,6 @@ use crate::files::FileId;
use crate::module::Module; use crate::module::Module;
use crate::module::ModuleName; use crate::module::ModuleName;
use crate::parse::parse; use crate::parse::parse;
use crate::Name;
pub(crate) use definitions::Definition; pub(crate) use definitions::Definition;
use definitions::{ImportDefinition, ImportFromDefinition}; use definitions::{ImportDefinition, ImportFromDefinition};
pub(crate) use flow_graph::ConstrainedDefinition; pub(crate) use flow_graph::ConstrainedDefinition;
@ -437,7 +436,7 @@ impl SourceOrderVisitor<'_> for SemanticIndexer {
}; };
let def = Definition::ImportFrom(ImportFromDefinition { let def = Definition::ImportFrom(ImportFromDefinition {
module: module.clone(), module: module.clone(),
name: Name::new(&alias.name.id), name: alias.name.id.clone(),
level: *level, level: *level,
}); });
self.add_or_update_symbol_with_def(symbol_name, def); self.add_or_update_symbol_with_def(symbol_name, def);

View file

@ -1,7 +1,7 @@
use crate::ast_ids::TypedNodeKey; use crate::ast_ids::TypedNodeKey;
use crate::semantic::ModuleName; use crate::semantic::ModuleName;
use crate::Name;
use ruff_python_ast as ast; use ruff_python_ast as ast;
use ruff_python_ast::name::Name;
// TODO storing TypedNodeKey for definitions means we have to search to find them again in the AST; // TODO storing TypedNodeKey for definitions means we have to search to find them again in the AST;
// this is at best O(log n). If looking up definitions is a bottleneck we should look for // this is at best O(log n). If looking up definitions is a bottleneck we should look for

View file

@ -9,11 +9,11 @@ use hashbrown::hash_map::{Keys, RawEntryMut};
use rustc_hash::{FxHashMap, FxHasher}; use rustc_hash::{FxHashMap, FxHasher};
use ruff_index::{newtype_index, IndexVec}; use ruff_index::{newtype_index, IndexVec};
use ruff_python_ast::name::Name;
use crate::ast_ids::NodeKey; use crate::ast_ids::NodeKey;
use crate::module::ModuleName; use crate::module::ModuleName;
use crate::semantic::{Definition, ExpressionId}; use crate::semantic::{Definition, ExpressionId};
use crate::Name;
type Map<K, V> = hashbrown::HashMap<K, V, ()>; type Map<K, V> = hashbrown::HashMap<K, V, ()>;

View file

@ -6,7 +6,7 @@ use crate::module::{Module, ModuleName};
use crate::semantic::{ use crate::semantic::{
resolve_global_symbol, semantic_index, GlobalSymbolId, ScopeId, ScopeKind, SymbolId, resolve_global_symbol, semantic_index, GlobalSymbolId, ScopeId, ScopeKind, SymbolId,
}; };
use crate::{FxDashMap, FxIndexSet, Name}; use crate::{FxDashMap, FxIndexSet};
use ruff_index::{newtype_index, IndexVec}; use ruff_index::{newtype_index, IndexVec};
use ruff_python_ast as ast; use ruff_python_ast as ast;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -14,6 +14,7 @@ use rustc_hash::FxHashMap;
pub(crate) mod infer; pub(crate) mod infer;
pub(crate) use infer::{infer_definition_type, infer_symbol_public_type}; pub(crate) use infer::{infer_definition_type, infer_symbol_public_type};
use ruff_python_ast::name::Name;
/// unique ID for a type /// unique ID for a type
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]

View file

@ -13,7 +13,7 @@ use crate::semantic::{
resolve_global_symbol, semantic_index, ConstrainedDefinition, Definition, GlobalSymbolId, resolve_global_symbol, semantic_index, ConstrainedDefinition, Definition, GlobalSymbolId,
ImportDefinition, ImportFromDefinition, ImportDefinition, ImportFromDefinition,
}; };
use crate::{FileId, Name}; use crate::FileId;
// FIXME: Figure out proper dead-lock free synchronisation now that this takes `&db` instead of `&mut db`. // FIXME: Figure out proper dead-lock free synchronisation now that this takes `&db` instead of `&mut db`.
/// Resolve the public-facing type for a symbol (the type seen by other scopes: other modules, or /// Resolve the public-facing type for a symbol (the type seen by other scopes: other modules, or
@ -315,7 +315,7 @@ fn infer_expr_type(db: &dyn SemanticDb, file_id: FileId, expr: &ast::Expr) -> Qu
} }
ast::Expr::Attribute(ast::ExprAttribute { value, attr, .. }) => { ast::Expr::Attribute(ast::ExprAttribute { value, attr, .. }) => {
let value_type = infer_expr_type(db, file_id, value)?; let value_type = infer_expr_type(db, file_id, value)?;
let attr_name = &Name::new(&attr.id); let attr_name = &attr.id;
value_type value_type
.get_member(db, attr_name) .get_member(db, attr_name)
.map(|ty| ty.unwrap_or(Type::Unknown)) .map(|ty| ty.unwrap_or(Type::Unknown))
@ -343,6 +343,7 @@ fn infer_expr_type(db: &dyn SemanticDb, file_id: FileId, expr: &ast::Expr) -> Qu
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use ruff_python_ast::name::Name;
use std::path::PathBuf; use std::path::PathBuf;
use crate::db::tests::TestDb; use crate::db::tests::TestDb;
@ -351,7 +352,6 @@ mod tests {
resolve_module, set_module_search_paths, ModuleName, ModuleResolutionInputs, resolve_module, set_module_search_paths, ModuleName, ModuleResolutionInputs,
}; };
use crate::semantic::{infer_symbol_public_type, resolve_global_symbol, Type}; use crate::semantic::{infer_symbol_public_type, resolve_global_symbol, Type};
use crate::Name;
// TODO with virtual filesystem we shouldn't have to write files to disk for these // TODO with virtual filesystem we shouldn't have to write files to disk for these
// tests // tests
@ -476,7 +476,7 @@ mod tests {
}; };
let member_ty = class_id let member_ty = class_id
.get_own_class_member(&case.db, &Name::new("f")) .get_own_class_member(&case.db, &Name::new_static("f"))
.expect("C.f to resolve"); .expect("C.f to resolve");
let Some(Type::Function(func_id)) = member_ty else { let Some(Type::Function(func_id)) = member_ty else {

View file

@ -21,7 +21,6 @@ bitflags = { workspace = true }
indexmap = { workspace = true } indexmap = { workspace = true }
salsa = { workspace = true } salsa = { workspace = true }
smallvec = { workspace = true } smallvec = { workspace = true }
smol_str = { workspace = true }
tracing = { workspace = true } tracing = { workspace = true }
rustc-hash = { workspace = true } rustc-hash = { workspace = true }
hashbrown = { workspace = true } hashbrown = { workspace = true }

View file

@ -1,6 +1,5 @@
pub mod ast_node_ref; pub mod ast_node_ref;
mod db; mod db;
pub mod name;
mod node_key; mod node_key;
pub mod semantic_index; pub mod semantic_index;
pub mod types; pub mod types;

View file

@ -1,56 +0,0 @@
use std::ops::Deref;
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Name(smol_str::SmolStr);
impl Name {
#[inline]
pub fn new(name: &str) -> Self {
Self(smol_str::SmolStr::new(name))
}
#[inline]
pub fn new_static(name: &'static str) -> Self {
Self(smol_str::SmolStr::new_static(name))
}
pub fn as_str(&self) -> &str {
self.0.as_str()
}
}
impl Deref for Name {
type Target = str;
#[inline]
fn deref(&self) -> &Self::Target {
self.as_str()
}
}
impl<T> From<T> for Name
where
T: Into<smol_str::SmolStr>,
{
fn from(value: T) -> Self {
Self(value.into())
}
}
impl std::fmt::Display for Name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
impl PartialEq<str> for Name {
fn eq(&self, other: &str) -> bool {
self.as_str() == other
}
}
impl PartialEq<Name> for str {
fn eq(&self, other: &Name) -> bool {
other == self
}
}

View file

@ -5,9 +5,9 @@ use rustc_hash::FxHashMap;
use ruff_db::parsed::ParsedModule; use ruff_db::parsed::ParsedModule;
use ruff_index::IndexVec; use ruff_index::IndexVec;
use ruff_python_ast as ast; use ruff_python_ast as ast;
use ruff_python_ast::name::Name;
use ruff_python_ast::visitor::{walk_expr, walk_stmt, Visitor}; use ruff_python_ast::visitor::{walk_expr, walk_stmt, Visitor};
use crate::name::Name;
use crate::node_key::NodeKey; use crate::node_key::NodeKey;
use crate::semantic_index::ast_ids::{ use crate::semantic_index::ast_ids::{
AstId, AstIdsBuilder, ScopeAssignmentId, ScopeClassId, ScopeFunctionId, ScopeImportFromId, AstId, AstIdsBuilder, ScopeAssignmentId, ScopeClassId, ScopeFunctionId, ScopeImportFromId,
@ -133,7 +133,6 @@ impl<'a> SemanticIndexBuilder<'a> {
fn add_or_update_symbol_with_definition( fn add_or_update_symbol_with_definition(
&mut self, &mut self,
name: Name, name: Name,
definition: Definition, definition: Definition,
) -> ScopedSymbolId { ) -> ScopedSymbolId {
let symbol_table = self.current_symbol_table(); let symbol_table = self.current_symbol_table();
@ -168,7 +167,7 @@ impl<'a> SemanticIndexBuilder<'a> {
ast::TypeParam::ParamSpec(ast::TypeParamParamSpec { name, .. }) => name, ast::TypeParam::ParamSpec(ast::TypeParamParamSpec { name, .. }) => name,
ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { name, .. }) => name, ast::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { name, .. }) => name,
}; };
self.add_or_update_symbol(Name::new(name), SymbolFlags::IS_DEFINED); self.add_or_update_symbol(name.id.clone(), SymbolFlags::IS_DEFINED);
} }
} }
@ -233,7 +232,7 @@ impl Visitor<'_> for SemanticIndexBuilder<'_> {
for decorator in &function_def.decorator_list { for decorator in &function_def.decorator_list {
self.visit_decorator(decorator); self.visit_decorator(decorator);
} }
let name = Name::new(&function_def.name.id); let name = &function_def.name.id;
let function_id = ScopeFunctionId(statement_id); let function_id = ScopeFunctionId(statement_id);
let definition = Definition::FunctionDef(function_id); let definition = Definition::FunctionDef(function_id);
let scope = self.current_scope(); let scope = self.current_scope();
@ -243,7 +242,7 @@ impl Visitor<'_> for SemanticIndexBuilder<'_> {
); );
self.with_type_params( self.with_type_params(
&name, name,
&WithTypeParams::FunctionDef { &WithTypeParams::FunctionDef {
node: function_def, node: function_def,
id: AstId::new(scope, function_id), id: AstId::new(scope, function_id),
@ -257,7 +256,7 @@ impl Visitor<'_> for SemanticIndexBuilder<'_> {
builder.push_scope( builder.push_scope(
NodeWithScopeId::Function(AstId::new(scope, function_id)), NodeWithScopeId::Function(AstId::new(scope, function_id)),
&name, name,
Some(symbol), Some(symbol),
Some(definition), Some(definition),
); );
@ -271,7 +270,7 @@ impl Visitor<'_> for SemanticIndexBuilder<'_> {
self.visit_decorator(decorator); self.visit_decorator(decorator);
} }
let name = Name::new(&class.name.id); let name = &class.name.id;
let class_id = ScopeClassId(statement_id); let class_id = ScopeClassId(statement_id);
let definition = Definition::from(class_id); let definition = Definition::from(class_id);
let scope = self.current_scope(); let scope = self.current_scope();
@ -280,7 +279,7 @@ impl Visitor<'_> for SemanticIndexBuilder<'_> {
self.add_or_update_symbol_with_definition(name.clone(), definition), self.add_or_update_symbol_with_definition(name.clone(), definition),
); );
self.with_type_params( self.with_type_params(
&name, name,
&WithTypeParams::ClassDef { &WithTypeParams::ClassDef {
node: class, node: class,
id: AstId::new(scope, class_id), id: AstId::new(scope, class_id),
@ -293,7 +292,7 @@ impl Visitor<'_> for SemanticIndexBuilder<'_> {
builder.push_scope( builder.push_scope(
NodeWithScopeId::Class(AstId::new(scope, class_id)), NodeWithScopeId::Class(AstId::new(scope, class_id)),
&name, name,
Some(id), Some(id),
Some(definition), Some(definition),
); );
@ -306,16 +305,16 @@ impl Visitor<'_> for SemanticIndexBuilder<'_> {
ast::Stmt::Import(ast::StmtImport { names, .. }) => { ast::Stmt::Import(ast::StmtImport { names, .. }) => {
for (i, alias) in names.iter().enumerate() { for (i, alias) in names.iter().enumerate() {
let symbol_name = if let Some(asname) = &alias.asname { let symbol_name = if let Some(asname) = &alias.asname {
asname.id.as_str() asname.id.clone()
} else { } else {
alias.name.id.split('.').next().unwrap() Name::new(alias.name.id.split('.').next().unwrap())
}; };
let def = Definition::Import(ImportDefinition { let def = Definition::Import(ImportDefinition {
import_id: ScopeImportId(statement_id), import_id: ScopeImportId(statement_id),
alias: u32::try_from(i).unwrap(), alias: u32::try_from(i).unwrap(),
}); });
self.add_or_update_symbol_with_definition(Name::new(symbol_name), def); self.add_or_update_symbol_with_definition(symbol_name, def);
} }
} }
ast::Stmt::ImportFrom(ast::StmtImportFrom { ast::Stmt::ImportFrom(ast::StmtImportFrom {
@ -326,15 +325,15 @@ impl Visitor<'_> for SemanticIndexBuilder<'_> {
}) => { }) => {
for (i, alias) in names.iter().enumerate() { for (i, alias) in names.iter().enumerate() {
let symbol_name = if let Some(asname) = &alias.asname { let symbol_name = if let Some(asname) = &alias.asname {
asname.id.as_str() &asname.id
} else { } else {
alias.name.id.as_str() &alias.name.id
}; };
let def = Definition::ImportFrom(ImportFromDefinition { let def = Definition::ImportFrom(ImportFromDefinition {
import_id: ScopeImportFromId(statement_id), import_id: ScopeImportFromId(statement_id),
name: u32::try_from(i).unwrap(), name: u32::try_from(i).unwrap(),
}); });
self.add_or_update_symbol_with_definition(Name::new(symbol_name), def); self.add_or_update_symbol_with_definition(symbol_name.clone(), def);
} }
} }
ast::Stmt::Assign(node) => { ast::Stmt::Assign(node) => {
@ -375,10 +374,10 @@ impl Visitor<'_> for SemanticIndexBuilder<'_> {
}; };
match self.current_definition { match self.current_definition {
Some(definition) if flags.contains(SymbolFlags::IS_DEFINED) => { Some(definition) if flags.contains(SymbolFlags::IS_DEFINED) => {
self.add_or_update_symbol_with_definition(Name::new(id), definition); self.add_or_update_symbol_with_definition(id.clone(), definition);
} }
_ => { _ => {
self.add_or_update_symbol(Name::new(id), flags); self.add_or_update_symbol(id.clone(), flags);
} }
} }

View file

@ -7,13 +7,12 @@ use rustc_hash::FxHasher;
use salsa::DebugWithDb; use salsa::DebugWithDb;
use smallvec::SmallVec; use smallvec::SmallVec;
use ruff_db::vfs::VfsFile;
use ruff_index::{newtype_index, IndexVec};
use crate::name::Name;
use crate::semantic_index::definition::Definition; use crate::semantic_index::definition::Definition;
use crate::semantic_index::{root_scope, semantic_index, symbol_table, SymbolMap}; use crate::semantic_index::{root_scope, semantic_index, symbol_table, SymbolMap};
use crate::Db; use crate::Db;
use ruff_db::vfs::VfsFile;
use ruff_index::{newtype_index, IndexVec};
use ruff_python_ast::name::Name;
#[derive(Eq, PartialEq, Debug)] #[derive(Eq, PartialEq, Debug)]
pub struct Symbol { pub struct Symbol {

View file

@ -1,11 +1,5 @@
use salsa::DebugWithDb; use salsa::DebugWithDb;
use ruff_db::parsed::parsed_module;
use ruff_db::vfs::VfsFile;
use ruff_index::newtype_index;
use ruff_python_ast as ast;
use crate::name::Name;
use crate::semantic_index::ast_ids::{AstIdNode, ScopeAstIdNode}; use crate::semantic_index::ast_ids::{AstIdNode, ScopeAstIdNode};
use crate::semantic_index::symbol::{FileScopeId, PublicSymbolId, ScopeId}; use crate::semantic_index::symbol::{FileScopeId, PublicSymbolId, ScopeId};
use crate::semantic_index::{ use crate::semantic_index::{
@ -14,6 +8,11 @@ use crate::semantic_index::{
use crate::types::infer::{TypeInference, TypeInferenceBuilder}; use crate::types::infer::{TypeInference, TypeInferenceBuilder};
use crate::Db; use crate::Db;
use crate::FxIndexSet; use crate::FxIndexSet;
use ruff_db::parsed::parsed_module;
use ruff_db::vfs::VfsFile;
use ruff_index::newtype_index;
use ruff_python_ast as ast;
use ruff_python_ast::name::Name;
mod display; mod display;
mod infer; mod infer;

View file

@ -9,7 +9,6 @@ use ruff_index::IndexVec;
use ruff_python_ast as ast; use ruff_python_ast as ast;
use ruff_python_ast::{ExprContext, TypeParams}; use ruff_python_ast::{ExprContext, TypeParams};
use crate::name::Name;
use crate::semantic_index::ast_ids::{ScopeAstIdNode, ScopeExpressionId}; use crate::semantic_index::ast_ids::{ScopeAstIdNode, ScopeExpressionId};
use crate::semantic_index::definition::{Definition, ImportDefinition, ImportFromDefinition}; use crate::semantic_index::definition::{Definition, ImportDefinition, ImportFromDefinition};
use crate::semantic_index::symbol::{FileScopeId, ScopeId, ScopeKind, ScopedSymbolId, SymbolTable}; use crate::semantic_index::symbol::{FileScopeId, ScopeId, ScopeKind, ScopedSymbolId, SymbolTable};
@ -199,7 +198,7 @@ impl<'db> TypeInferenceBuilder<'db> {
} }
let function_ty = self.function_ty(FunctionType { let function_ty = self.function_ty(FunctionType {
name: Name::new(&name.id), name: name.id.clone(),
decorators: decorator_tys, decorators: decorator_tys,
}); });
@ -248,7 +247,7 @@ impl<'db> TypeInferenceBuilder<'db> {
assert_eq!(class_body_scope.kind(), ScopeKind::Class); assert_eq!(class_body_scope.kind(), ScopeKind::Class);
let class_ty = self.class_ty(ClassType { let class_ty = self.class_ty(ClassType {
name: Name::new(name), name: name.id.clone(),
bases, bases,
body_scope: class_body_scope_id.to_scope_id(self.db, self.file_id), body_scope: class_body_scope_id.to_scope_id(self.db, self.file_id),
}); });
@ -398,7 +397,7 @@ impl<'db> TypeInferenceBuilder<'db> {
} = alias; } = alias;
let ty = module_ty let ty = module_ty
.member(&self.typing_context(), &Name::new(&name.id)) .member(&self.typing_context(), &name.id)
.unwrap_or(Type::Unknown); .unwrap_or(Type::Unknown);
self.definition_tys.insert( self.definition_tys.insert(
@ -557,7 +556,7 @@ impl<'db> TypeInferenceBuilder<'db> {
let value_ty = self.infer_expression(value); let value_ty = self.infer_expression(value);
let member_ty = value_ty let member_ty = value_ty
.member(&self.typing_context(), &Name::new(&attr.id)) .member(&self.typing_context(), &attr.id)
.unwrap_or(Type::Unknown); .unwrap_or(Type::Unknown);
match ctx { match ctx {
@ -695,9 +694,9 @@ mod tests {
use ruff_db::vfs::system_path_to_file; use ruff_db::vfs::system_path_to_file;
use crate::db::tests::TestDb; use crate::db::tests::TestDb;
use crate::name::Name;
use crate::types::{public_symbol_ty_by_name, Type, TypingContext}; use crate::types::{public_symbol_ty_by_name, Type, TypingContext};
use red_knot_module_resolver::{set_module_resolution_settings, ModuleResolutionSettings}; use red_knot_module_resolver::{set_module_resolution_settings, ModuleResolutionSettings};
use ruff_python_ast::name::Name;
fn setup_db() -> TestDb { fn setup_db() -> TestDb {
let mut db = TestDb::new(); let mut db = TestDb::new();
@ -791,7 +790,7 @@ class C:
}; };
let context = TypingContext::global(&db); let context = TypingContext::global(&db);
let member_ty = class_id.class_member(&context, &Name::new("f")); let member_ty = class_id.class_member(&context, &Name::new_static("f"));
let Some(Type::Function(func_id)) = member_ty else { let Some(Type::Function(func_id)) = member_ty else {
panic!("C.f is not a Function"); panic!("C.f is not a Function");

View file

@ -140,7 +140,7 @@ pub(crate) fn make_redundant_alias<'a>(
.filter_map(|name| { .filter_map(|name| {
aliases aliases
.iter() .iter()
.find(|alias| alias.asname.is_none() && name == alias.name.id) .find(|alias| alias.asname.is_none() && *name == alias.name.id)
.map(|alias| Edit::range_replacement(format!("{name} as {name}"), alias.range)) .map(|alias| Edit::range_replacement(format!("{name} as {name}"), alias.range))
}) })
.collect() .collect()

View file

@ -6,17 +6,17 @@
use std::error::Error; use std::error::Error;
use anyhow::Result; use anyhow::Result;
use libcst_native::{ImportAlias, Name, NameOrAttribute}; use libcst_native::{ImportAlias, Name as cstName, NameOrAttribute};
use ruff_python_ast::{self as ast, ModModule, Stmt};
use ruff_python_parser::{Parsed, Tokens};
use ruff_text_size::{Ranged, TextSize};
use ruff_diagnostics::Edit; use ruff_diagnostics::Edit;
use ruff_python_ast::imports::{AnyImport, Import, ImportFrom}; use ruff_python_ast::imports::{AnyImport, Import, ImportFrom};
use ruff_python_ast::{self as ast, ModModule, Stmt};
use ruff_python_codegen::Stylist; use ruff_python_codegen::Stylist;
use ruff_python_parser::{Parsed, Tokens};
use ruff_python_semantic::{ImportedName, SemanticModel}; use ruff_python_semantic::{ImportedName, SemanticModel};
use ruff_python_trivia::textwrap::indent; use ruff_python_trivia::textwrap::indent;
use ruff_source_file::Locator; use ruff_source_file::Locator;
use ruff_text_size::{Ranged, TextSize};
use crate::cst::matchers::{match_aliases, match_import_from, match_statement}; use crate::cst::matchers::{match_aliases, match_import_from, match_statement};
use crate::fix; use crate::fix;
@ -425,7 +425,7 @@ impl<'a> Importer<'a> {
let import_from = match_import_from(&mut statement)?; let import_from = match_import_from(&mut statement)?;
let aliases = match_aliases(import_from)?; let aliases = match_aliases(import_from)?;
aliases.push(ImportAlias { aliases.push(ImportAlias {
name: NameOrAttribute::N(Box::new(Name { name: NameOrAttribute::N(Box::new(cstName {
value: member, value: member,
lpar: vec![], lpar: vec![],
rpar: vec![], rpar: vec![],

View file

@ -81,7 +81,7 @@ pub(crate) fn variable_name_task_id(
let ast::ExprStringLiteral { value: task_id, .. } = keyword.value.as_string_literal_expr()?; let ast::ExprStringLiteral { value: task_id, .. } = keyword.value.as_string_literal_expr()?;
// If the target name is the same as the task_id, no violation. // If the target name is the same as the task_id, no violation.
if task_id == id { if task_id == id.as_str() {
return None; return None;
} }

View file

@ -5,6 +5,7 @@ use ruff_diagnostics::Edit;
use ruff_python_ast::helpers::{ use ruff_python_ast::helpers::{
pep_604_union, typing_optional, typing_union, ReturnStatementVisitor, pep_604_union, typing_optional, typing_union, ReturnStatementVisitor,
}; };
use ruff_python_ast::name::Name;
use ruff_python_ast::visitor::Visitor; use ruff_python_ast::visitor::Visitor;
use ruff_python_ast::{self as ast, Expr, ExprContext}; use ruff_python_ast::{self as ast, Expr, ExprContext};
use ruff_python_semantic::analyze::terminal::Terminal; use ruff_python_semantic::analyze::terminal::Terminal;
@ -140,7 +141,7 @@ impl AutoPythonType {
) )
.ok()?; .ok()?;
let expr = Expr::Name(ast::ExprName { let expr = Expr::Name(ast::ExprName {
id: binding, id: Name::from(binding),
range: TextRange::default(), range: TextRange::default(),
ctx: ExprContext::Load, ctx: ExprContext::Load,
}); });
@ -181,7 +182,7 @@ impl AutoPythonType {
semantic, semantic,
) )
.ok()?; .ok()?;
let expr = typing_optional(element, binding); let expr = typing_optional(element, Name::from(binding));
Some((expr, vec![optional_edit])) Some((expr, vec![optional_edit]))
} }
_ => { _ => {
@ -198,7 +199,7 @@ impl AutoPythonType {
semantic, semantic,
) )
.ok()?; .ok()?;
let expr = typing_union(&elements, binding); let expr = typing_union(&elements, Name::from(binding));
Some((expr, vec![union_edit])) Some((expr, vec![union_edit]))
} }
} }

View file

@ -1,11 +1,12 @@
//! Rules from [flake8-gettext](https://pypi.org/project/flake8-gettext/). //! Rules from [flake8-gettext](https://pypi.org/project/flake8-gettext/).
use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, Expr}; use ruff_python_ast::{self as ast, Expr};
pub(crate) mod rules; pub(crate) mod rules;
pub mod settings; pub mod settings;
/// Returns true if the [`Expr`] is an internationalization function call. /// Returns true if the [`Expr`] is an internationalization function call.
pub(crate) fn is_gettext_func_call(func: &Expr, functions_names: &[String]) -> bool { pub(crate) fn is_gettext_func_call(func: &Expr, functions_names: &[Name]) -> bool {
if let Expr::Name(ast::ExprName { id, .. }) = func { if let Expr::Name(ast::ExprName { id, .. }) = func {
functions_names.contains(id) functions_names.contains(id)
} else { } else {

View file

@ -1,17 +1,18 @@
use crate::display_settings; use crate::display_settings;
use ruff_macros::CacheKey; use ruff_macros::CacheKey;
use ruff_python_ast::name::Name;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
#[derive(Debug, Clone, CacheKey)] #[derive(Debug, Clone, CacheKey)]
pub struct Settings { pub struct Settings {
pub functions_names: Vec<String>, pub functions_names: Vec<Name>,
} }
pub fn default_func_names() -> Vec<String> { pub fn default_func_names() -> Vec<Name> {
vec![ vec![
"_".to_string(), Name::new_static("_"),
"gettext".to_string(), Name::new_static("gettext"),
"ngettext".to_string(), Name::new_static("ngettext"),
] ]
} }

View file

@ -2,6 +2,7 @@ use ast::ExprContext;
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::helpers::pep_604_union; use ruff_python_ast::helpers::pep_604_union;
use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, Expr}; use ruff_python_ast::{self as ast, Expr};
use ruff_python_semantic::analyze::typing::traverse_union; use ruff_python_semantic::analyze::typing::traverse_union;
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
@ -26,7 +27,7 @@ use crate::checkers::ast::Checker;
/// ``` /// ```
#[violation] #[violation]
pub struct UnnecessaryTypeUnion { pub struct UnnecessaryTypeUnion {
members: Vec<String>, members: Vec<Name>,
is_pep604_union: bool, is_pep604_union: bool,
} }
@ -83,10 +84,10 @@ pub(crate) fn unnecessary_type_union<'a>(checker: &mut Checker, union: &'a Expr)
traverse_union(&mut collect_type_exprs, semantic, union); traverse_union(&mut collect_type_exprs, semantic, union);
if type_exprs.len() > 1 { if type_exprs.len() > 1 {
let type_members: Vec<String> = type_exprs let type_members: Vec<Name> = type_exprs
.clone() .clone()
.into_iter() .into_iter()
.map(|type_expr| checker.locator().slice(type_expr).to_string()) .map(|type_expr| Name::new(checker.locator().slice(type_expr)))
.collect(); .collect();
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
@ -101,7 +102,7 @@ pub(crate) fn unnecessary_type_union<'a>(checker: &mut Checker, union: &'a Expr)
let content = if let Some(subscript) = subscript { let content = if let Some(subscript) = subscript {
let types = &Expr::Subscript(ast::ExprSubscript { let types = &Expr::Subscript(ast::ExprSubscript {
value: Box::new(Expr::Name(ast::ExprName { value: Box::new(Expr::Name(ast::ExprName {
id: "type".into(), id: Name::new_static("type"),
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
})), })),
@ -154,7 +155,7 @@ pub(crate) fn unnecessary_type_union<'a>(checker: &mut Checker, union: &'a Expr)
let elts: Vec<Expr> = type_exprs.into_iter().cloned().collect(); let elts: Vec<Expr> = type_exprs.into_iter().cloned().collect();
let types = Expr::Subscript(ast::ExprSubscript { let types = Expr::Subscript(ast::ExprSubscript {
value: Box::new(Expr::Name(ast::ExprName { value: Box::new(Expr::Name(ast::ExprName {
id: "type".into(), id: Name::new_static("type"),
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
})), })),

View file

@ -1,4 +1,5 @@
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, bail, Result};
use ruff_python_ast::name::Name;
use ruff_python_ast::{ use ruff_python_ast::{
self as ast, Arguments, CmpOp, Expr, ExprContext, Identifier, Keyword, Stmt, UnaryOp, self as ast, Arguments, CmpOp, Expr, ExprContext, Identifier, Keyword, Stmt, UnaryOp,
}; };
@ -379,7 +380,7 @@ impl UnittestAssert {
.ok_or_else(|| anyhow!("Missing argument `cls`"))?; .ok_or_else(|| anyhow!("Missing argument `cls`"))?;
let msg = args.get("msg").copied(); let msg = args.get("msg").copied();
let node = ast::ExprName { let node = ast::ExprName {
id: "isinstance".into(), id: Name::new_static("isinstance"),
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}; };
@ -417,7 +418,7 @@ impl UnittestAssert {
.ok_or_else(|| anyhow!("Missing argument `regex`"))?; .ok_or_else(|| anyhow!("Missing argument `regex`"))?;
let msg = args.get("msg").copied(); let msg = args.get("msg").copied();
let node = ast::ExprName { let node = ast::ExprName {
id: "re".into(), id: Name::new_static("re"),
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}; };

View file

@ -7,13 +7,13 @@ mod tests {
use std::convert::AsRef; use std::convert::AsRef;
use std::path::Path; use std::path::Path;
use anyhow::Result;
use test_case::test_case;
use crate::registry::Rule; use crate::registry::Rule;
use crate::rules::flake8_self; use crate::rules::flake8_self;
use crate::test::test_path; use crate::test::test_path;
use crate::{assert_messages, settings}; use crate::{assert_messages, settings};
use anyhow::Result;
use ruff_python_ast::name::Name;
use test_case::test_case;
#[test_case(Rule::PrivateMemberAccess, Path::new("SLF001.py"))] #[test_case(Rule::PrivateMemberAccess, Path::new("SLF001.py"))]
fn rules(rule_code: Rule, path: &Path) -> Result<()> { fn rules(rule_code: Rule, path: &Path) -> Result<()> {
@ -32,7 +32,7 @@ mod tests {
Path::new("flake8_self/SLF001_extended.py"), Path::new("flake8_self/SLF001_extended.py"),
&settings::LinterSettings { &settings::LinterSettings {
flake8_self: flake8_self::settings::Settings { flake8_self: flake8_self::settings::Settings {
ignore_names: vec!["_meta".to_string()], ignore_names: vec![Name::new_static("_meta")],
}, },
..settings::LinterSettings::for_rule(Rule::PrivateMemberAccess) ..settings::LinterSettings::for_rule(Rule::PrivateMemberAccess)
}, },

View file

@ -97,7 +97,7 @@ pub(crate) fn private_member_access(checker: &mut Checker, expr: &Expr) {
.settings .settings
.flake8_self .flake8_self
.ignore_names .ignore_names
.contains(attr.as_ref()) .contains(attr.id())
{ {
return; return;
} }

View file

@ -2,6 +2,7 @@
use crate::display_settings; use crate::display_settings;
use ruff_macros::CacheKey; use ruff_macros::CacheKey;
use ruff_python_ast::name::Name;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
// By default, ignore the `namedtuple` methods and attributes, as well as the // By default, ignore the `namedtuple` methods and attributes, as well as the
@ -19,13 +20,13 @@ pub const IGNORE_NAMES: [&str; 7] = [
#[derive(Debug, Clone, CacheKey)] #[derive(Debug, Clone, CacheKey)]
pub struct Settings { pub struct Settings {
pub ignore_names: Vec<String>, pub ignore_names: Vec<Name>,
} }
impl Default for Settings { impl Default for Settings {
fn default() -> Self { fn default() -> Self {
Self { Self {
ignore_names: IGNORE_NAMES.map(String::from).to_vec(), ignore_names: IGNORE_NAMES.map(Name::new_static).to_vec(),
} }
} }
} }

View file

@ -10,6 +10,7 @@ use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix, FixAvailab
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::comparable::ComparableExpr; use ruff_python_ast::comparable::ComparableExpr;
use ruff_python_ast::helpers::{contains_effect, Truthiness}; use ruff_python_ast::helpers::{contains_effect, Truthiness};
use ruff_python_ast::name::Name;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::parenthesize::parenthesized_range;
use ruff_python_codegen::Generator; use ruff_python_codegen::Generator;
use ruff_python_semantic::SemanticModel; use ruff_python_semantic::SemanticModel;
@ -425,7 +426,7 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) {
let isinstance_call = ast::ExprCall { let isinstance_call = ast::ExprCall {
func: Box::new( func: Box::new(
ast::ExprName { ast::ExprName {
id: "isinstance".into(), id: Name::new_static("isinstance"),
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
} }
@ -469,7 +470,7 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) {
} }
} }
fn match_eq_target(expr: &Expr) -> Option<(&str, &Expr)> { fn match_eq_target(expr: &Expr) -> Option<(&Name, &Expr)> {
let Expr::Compare(ast::ExprCompare { let Expr::Compare(ast::ExprCompare {
left, left,
ops, ops,
@ -482,7 +483,7 @@ fn match_eq_target(expr: &Expr) -> Option<(&str, &Expr)> {
if **ops != [CmpOp::Eq] { if **ops != [CmpOp::Eq] {
return None; return None;
} }
let Expr::Name(ast::ExprName { id, .. }) = left.as_ref() else { let Expr::Name(ast::ExprName { id, .. }) = &**left else {
return None; return None;
}; };
let [comparator] = &**comparators else { let [comparator] = &**comparators else {
@ -507,7 +508,7 @@ pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) {
// Given `a == "foo" or a == "bar"`, we generate `{"a": [(0, "foo"), (1, // Given `a == "foo" or a == "bar"`, we generate `{"a": [(0, "foo"), (1,
// "bar")]}`. // "bar")]}`.
let mut id_to_comparators: BTreeMap<&str, Vec<(usize, &Expr)>> = BTreeMap::new(); let mut id_to_comparators: BTreeMap<&Name, Vec<(usize, &Expr)>> = BTreeMap::new();
for (index, value) in values.iter().enumerate() { for (index, value) in values.iter().enumerate() {
if let Some((id, comparator)) = match_eq_target(value) { if let Some((id, comparator)) = match_eq_target(value) {
id_to_comparators id_to_comparators
@ -548,7 +549,7 @@ pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) {
parenthesized: true, parenthesized: true,
}; };
let node1 = ast::ExprName { let node1 = ast::ExprName {
id: id.into(), id: id.clone(),
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}; };

View file

@ -4,6 +4,7 @@ use ruff_text_size::{Ranged, TextRange};
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::helpers::{is_const_false, is_const_true}; use ruff_python_ast::helpers::{is_const_false, is_const_true};
use ruff_python_ast::name::Name;
use ruff_python_ast::parenthesize::parenthesized_range; use ruff_python_ast::parenthesize::parenthesized_range;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -178,7 +179,7 @@ pub(crate) fn if_expr_with_true_false(
&ast::ExprCall { &ast::ExprCall {
func: Box::new( func: Box::new(
ast::ExprName { ast::ExprName {
id: "bool".into(), id: Name::new_static("bool"),
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
} }

View file

@ -3,6 +3,7 @@ use ruff_text_size::{Ranged, TextRange};
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::name::Name;
use ruff_python_semantic::ScopeKind; use ruff_python_semantic::ScopeKind;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -272,7 +273,7 @@ pub(crate) fn double_negation(checker: &mut Checker, expr: &Expr, op: UnaryOp, o
))); )));
} else if checker.semantic().has_builtin_binding("bool") { } else if checker.semantic().has_builtin_binding("bool") {
let node = ast::ExprName { let node = ast::ExprName {
id: "bool".into(), id: Name::new_static("bool"),
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}; };

View file

@ -1,5 +1,6 @@
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::name::Name;
use ruff_python_ast::traversal; use ruff_python_ast::traversal;
use ruff_python_ast::{self as ast, Arguments, ElifElseClause, Expr, ExprContext, Stmt}; use ruff_python_ast::{self as ast, Arguments, ElifElseClause, Expr, ExprContext, Stmt};
use ruff_python_semantic::analyze::typing::{is_sys_version_block, is_type_checking_block}; use ruff_python_semantic::analyze::typing::{is_sys_version_block, is_type_checking_block};
@ -226,7 +227,7 @@ pub(crate) fn needless_bool(checker: &mut Checker, stmt: &Stmt) {
} else if checker.semantic().has_builtin_binding("bool") { } else if checker.semantic().has_builtin_binding("bool") {
// Otherwise, we need to wrap the condition in a call to `bool`. // Otherwise, we need to wrap the condition in a call to `bool`.
let func_node = ast::ExprName { let func_node = ast::ExprName {
id: "bool".into(), id: Name::new_static("bool"),
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}; };

View file

@ -1,6 +1,7 @@
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::helpers::any_over_expr; use ruff_python_ast::helpers::any_over_expr;
use ruff_python_ast::name::Name;
use ruff_python_ast::traversal; use ruff_python_ast::traversal;
use ruff_python_ast::{ use ruff_python_ast::{
self as ast, Arguments, CmpOp, Comprehension, Expr, ExprContext, Stmt, UnaryOp, self as ast, Arguments, CmpOp, Comprehension, Expr, ExprContext, Stmt, UnaryOp,
@ -89,7 +90,7 @@ pub(crate) fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt) {
// Replace with `any`. // Replace with `any`.
(true, false) => { (true, false) => {
let contents = return_stmt( let contents = return_stmt(
"any", Name::new_static("any"),
loop_.test, loop_.test,
loop_.target, loop_.target,
loop_.iter, loop_.iter,
@ -177,7 +178,13 @@ pub(crate) fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt) {
node.into() node.into()
} }
}; };
let contents = return_stmt("all", &test, loop_.target, loop_.iter, checker.generator()); let contents = return_stmt(
Name::new_static("all"),
&test,
loop_.target,
loop_.iter,
checker.generator(),
);
// Don't flag if the resulting expression would exceed the maximum line length. // Don't flag if the resulting expression would exceed the maximum line length.
let line_start = checker.locator().line_start(stmt.start()); let line_start = checker.locator().line_start(stmt.start());
@ -372,7 +379,7 @@ fn match_sibling_return<'a>(stmt: &'a Stmt, sibling: &'a Stmt) -> Option<Termina
} }
/// Generate a return statement for an `any` or `all` builtin comprehension. /// Generate a return statement for an `any` or `all` builtin comprehension.
fn return_stmt(id: &str, test: &Expr, target: &Expr, iter: &Expr, generator: Generator) -> String { fn return_stmt(id: Name, test: &Expr, target: &Expr, iter: &Expr, generator: Generator) -> String {
let node = ast::ExprGenerator { let node = ast::ExprGenerator {
elt: Box::new(test.clone()), elt: Box::new(test.clone()),
generators: vec![Comprehension { generators: vec![Comprehension {
@ -386,7 +393,7 @@ fn return_stmt(id: &str, test: &Expr, target: &Expr, iter: &Expr, generator: Gen
parenthesized: false, parenthesized: false,
}; };
let node1 = ast::ExprName { let node1 = ast::ExprName {
id: id.into(), id,
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}; };

View file

@ -1,9 +1,9 @@
//! Implements helper functions for using vendored/format.rs //! Implements helper functions for using vendored/format.rs
use std::convert::TryFrom; use ruff_python_ast::name::Name;
use ruff_python_literal::format::{ use ruff_python_literal::format::{
FieldName, FieldType, FormatParseError, FormatPart, FormatString, FromTemplate, FieldName, FieldType, FormatParseError, FormatPart, FormatString, FromTemplate,
}; };
use std::convert::TryFrom;
pub(crate) fn error_to_string(err: &FormatParseError) -> String { pub(crate) fn error_to_string(err: &FormatParseError) -> String {
match err { match err {
@ -26,7 +26,7 @@ pub(crate) fn error_to_string(err: &FormatParseError) -> String {
pub(crate) struct FormatSummary { pub(crate) struct FormatSummary {
pub(crate) autos: Vec<usize>, pub(crate) autos: Vec<usize>,
pub(crate) indices: Vec<usize>, pub(crate) indices: Vec<usize>,
pub(crate) keywords: Vec<String>, pub(crate) keywords: Vec<Name>,
pub(crate) has_nested_parts: bool, pub(crate) has_nested_parts: bool,
} }
@ -54,7 +54,7 @@ impl TryFrom<&str> for FormatSummary {
match parsed.field_type { match parsed.field_type {
FieldType::Auto => autos.push(autos.len()), FieldType::Auto => autos.push(autos.len()),
FieldType::Index(i) => indices.push(i), FieldType::Index(i) => indices.push(i),
FieldType::Keyword(k) => keywords.push(k), FieldType::Keyword(k) => keywords.push(Name::from(k)),
}; };
let nested = FormatString::from_str(format_spec)?; let nested = FormatString::from_str(format_spec)?;
@ -66,7 +66,7 @@ impl TryFrom<&str> for FormatSummary {
match parsed.field_type { match parsed.field_type {
FieldType::Auto => autos.push(autos.len()), FieldType::Auto => autos.push(autos.len()),
FieldType::Index(i) => indices.push(i), FieldType::Index(i) => indices.push(i),
FieldType::Keyword(k) => keywords.push(k), FieldType::Keyword(k) => keywords.push(Name::from(k)),
}; };
has_nested_parts = true; has_nested_parts = true;
} }

View file

@ -4,7 +4,8 @@ use rustc_hash::FxHashSet;
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Fix, FixAvailability, Violation}; use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::{self as ast, Expr, Identifier, Keyword}; use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, Expr, Keyword};
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -382,7 +383,7 @@ impl Violation for StringDotFormatInvalidFormat {
/// - [Python documentation: `str.format`](https://docs.python.org/3/library/stdtypes.html#str.format) /// - [Python documentation: `str.format`](https://docs.python.org/3/library/stdtypes.html#str.format)
#[violation] #[violation]
pub struct StringDotFormatExtraNamedArguments { pub struct StringDotFormatExtraNamedArguments {
missing: Vec<String>, missing: Vec<Name>,
} }
impl Violation for StringDotFormatExtraNamedArguments { impl Violation for StringDotFormatExtraNamedArguments {
@ -743,13 +744,13 @@ pub(crate) fn string_dot_format_extra_named_arguments(
.iter() .iter()
.filter_map(|Keyword { arg, .. }| arg.as_ref()); .filter_map(|Keyword { arg, .. }| arg.as_ref());
let missing: Vec<(usize, &str)> = keywords let missing: Vec<(usize, &Name)> = keywords
.enumerate() .enumerate()
.filter_map(|(index, keyword)| { .filter_map(|(index, keyword)| {
if summary.keywords.contains(keyword.as_ref()) { if summary.keywords.contains(keyword.id()) {
None None
} else { } else {
Some((index, keyword.as_str())) Some((index, &keyword.id))
} }
}) })
.collect(); .collect();
@ -758,10 +759,7 @@ pub(crate) fn string_dot_format_extra_named_arguments(
return; return;
} }
let names: Vec<String> = missing let names: Vec<Name> = missing.iter().map(|(_, name)| (*name).clone()).collect();
.iter()
.map(|(_, name)| (*name).to_string())
.collect();
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
StringDotFormatExtraNamedArguments { missing: names }, StringDotFormatExtraNamedArguments { missing: names },
call.range(), call.range(),
@ -865,7 +863,7 @@ pub(crate) fn string_dot_format_missing_argument(
.iter() .iter()
.filter_map(|k| { .filter_map(|k| {
let Keyword { arg, .. } = &k; let Keyword { arg, .. } = &k;
arg.as_ref().map(Identifier::as_str) arg.as_ref().map(ruff_python_ast::Identifier::id)
}) })
.collect(); .collect();
@ -879,8 +877,8 @@ pub(crate) fn string_dot_format_missing_argument(
summary summary
.keywords .keywords
.iter() .iter()
.filter(|k| !keywords.contains(k.as_str())) .filter(|k| !keywords.contains(*k))
.cloned(), .map(ToString::to_string),
) )
.collect(); .collect();

View file

@ -1,6 +1,7 @@
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::helpers::any_over_body; use ruff_python_ast::helpers::any_over_body;
use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, Expr, StmtFor}; use ruff_python_ast::{self as ast, Expr, StmtFor};
use ruff_python_semantic::analyze::typing::is_set; use ruff_python_semantic::analyze::typing::is_set;
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
@ -41,7 +42,7 @@ use crate::checkers::ast::Checker;
/// - [Python documentation: `set`](https://docs.python.org/3/library/stdtypes.html#set) /// - [Python documentation: `set`](https://docs.python.org/3/library/stdtypes.html#set)
#[violation] #[violation]
pub struct ModifiedIteratingSet { pub struct ModifiedIteratingSet {
name: String, name: Name,
} }
impl AlwaysFixableViolation for ModifiedIteratingSet { impl AlwaysFixableViolation for ModifiedIteratingSet {

View file

@ -2,6 +2,7 @@ use std::collections::HashMap;
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, DiagnosticKind, Edit, Fix}; use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, DiagnosticKind, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, Expr, Stmt}; use ruff_python_ast::{self as ast, Expr, Stmt};
use ruff_python_trivia::indentation_at_offset; use ruff_python_trivia::indentation_at_offset;
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
@ -101,7 +102,7 @@ fn get_undecorated_methods(checker: &mut Checker, class_stmt: &Stmt, method_type
return; return;
}; };
let mut explicit_decorator_calls: HashMap<String, &Stmt> = HashMap::default(); let mut explicit_decorator_calls: HashMap<Name, &Stmt> = HashMap::default();
let (method_name, diagnostic_type): (&str, DiagnosticKind) = match method_type { let (method_name, diagnostic_type): (&str, DiagnosticKind) = match method_type {
MethodType::Classmethod => ("classmethod", NoClassmethodDecorator.into()), MethodType::Classmethod => ("classmethod", NoClassmethodDecorator.into()),
@ -152,7 +153,7 @@ fn get_undecorated_methods(checker: &mut Checker, class_stmt: &Stmt, method_type
.. ..
}) = stmt }) = stmt
{ {
let Some(decorator_call_statement) = explicit_decorator_calls.get(name.as_str()) else { let Some(decorator_call_statement) = explicit_decorator_calls.get(name.id()) else {
continue; continue;
}; };

View file

@ -2,6 +2,7 @@ use ruff_python_ast::{self as ast, Expr};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::name::Name;
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -42,14 +43,14 @@ impl Violation for RedeclaredAssignedName {
/// PLW0128 /// PLW0128
pub(crate) fn redeclared_assigned_name(checker: &mut Checker, targets: &Vec<Expr>) { pub(crate) fn redeclared_assigned_name(checker: &mut Checker, targets: &Vec<Expr>) {
let mut names: Vec<String> = Vec::new(); let mut names: Vec<Name> = Vec::new();
for target in targets { for target in targets {
check_expr(checker, target, &mut names); check_expr(checker, target, &mut names);
} }
} }
fn check_expr(checker: &mut Checker, expr: &Expr, names: &mut Vec<String>) { fn check_expr(checker: &mut Checker, expr: &Expr, names: &mut Vec<Name>) {
match expr { match expr {
Expr::Tuple(ast::ExprTuple { elts, .. }) => { Expr::Tuple(ast::ExprTuple { elts, .. }) => {
for target in elts { for target in elts {
@ -69,7 +70,7 @@ fn check_expr(checker: &mut Checker, expr: &Expr, names: &mut Vec<String>) {
expr.range(), expr.range(),
)); ));
} }
names.push(id.to_string()); names.push(id.clone());
} }
_ => {} _ => {}
} }

View file

@ -3,6 +3,7 @@ use log::debug;
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::helpers::is_dunder; use ruff_python_ast::helpers::is_dunder;
use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, Arguments, Expr, ExprContext, Identifier, Keyword, Stmt}; use ruff_python_ast::{self as ast, Arguments, Expr, ExprContext, Identifier, Keyword, Stmt};
use ruff_python_codegen::Generator; use ruff_python_codegen::Generator;
use ruff_python_semantic::SemanticModel; use ruff_python_semantic::SemanticModel;
@ -148,11 +149,11 @@ fn match_named_tuple_assign<'a>(
} }
/// Generate a [`Stmt::AnnAssign`] representing the provided field definition. /// Generate a [`Stmt::AnnAssign`] representing the provided field definition.
fn create_field_assignment_stmt(field: &str, annotation: &Expr) -> Stmt { fn create_field_assignment_stmt(field: Name, annotation: &Expr) -> Stmt {
ast::StmtAnnAssign { ast::StmtAnnAssign {
target: Box::new( target: Box::new(
ast::ExprName { ast::ExprName {
id: field.into(), id: field,
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
} }
@ -191,7 +192,10 @@ fn create_fields_from_fields_arg(fields: &Expr) -> Option<Vec<Stmt>> {
if is_dunder(field.to_str()) { if is_dunder(field.to_str()) {
return None; return None;
} }
Some(create_field_assignment_stmt(field.to_str(), annotation)) Some(create_field_assignment_stmt(
Name::new(field.to_str()),
annotation,
))
}) })
.collect() .collect()
} }
@ -205,7 +209,7 @@ fn create_fields_from_keywords(keywords: &[Keyword]) -> Option<Vec<Stmt>> {
keyword keyword
.arg .arg
.as_ref() .as_ref()
.map(|field| create_field_assignment_stmt(field.as_str(), &keyword.value)) .map(|field| create_field_assignment_stmt(field.id.clone(), &keyword.value))
}) })
.collect() .collect()
} }

View file

@ -4,7 +4,7 @@ use ruff_text_size::{Ranged, TextRange};
use crate::fix::edits::pad; use crate::fix::edits::pad;
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::name::UnqualifiedName; use ruff_python_ast::name::{Name, UnqualifiedName};
use ruff_python_semantic::SemanticModel; use ruff_python_semantic::SemanticModel;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -116,7 +116,7 @@ fn tuple_diagnostic(checker: &mut Checker, tuple: &ast::ExprTuple, aliases: &[&E
.all(|elt| !semantic.match_builtin_expr(elt, "OSError")) .all(|elt| !semantic.match_builtin_expr(elt, "OSError"))
{ {
let node = ast::ExprName { let node = ast::ExprName {
id: "OSError".into(), id: Name::new_static("OSError"),
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}; };

View file

@ -4,7 +4,7 @@ use ruff_text_size::{Ranged, TextRange};
use crate::fix::edits::pad; use crate::fix::edits::pad;
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::name::UnqualifiedName; use ruff_python_ast::name::{Name, UnqualifiedName};
use ruff_python_semantic::SemanticModel; use ruff_python_semantic::SemanticModel;
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -128,7 +128,7 @@ fn tuple_diagnostic(checker: &mut Checker, tuple: &ast::ExprTuple, aliases: &[&E
.all(|elt| !semantic.match_builtin_expr(elt, "TimeoutError")) .all(|elt| !semantic.match_builtin_expr(elt, "TimeoutError"))
{ {
let node = ast::ExprName { let node = ast::ExprName {
id: "TimeoutError".into(), id: Name::new_static("TimeoutError"),
ctx: ExprContext::Load, ctx: ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}; };

View file

@ -2,6 +2,7 @@ use itertools::Itertools;
use ruff_diagnostics::{Applicability, Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_diagnostics::{Applicability, Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::name::Name;
use ruff_python_ast::{ use ruff_python_ast::{
self as ast, self as ast,
visitor::{self, Visitor}, visitor::{self, Visitor},
@ -104,7 +105,7 @@ pub(crate) fn non_pep695_type_alias_type(checker: &mut Checker, stmt: &StmtAssig
return; return;
}; };
if name.value.to_str() != target_name.id { if &name.value != target_name.id.as_str() {
return; return;
} }
@ -143,7 +144,7 @@ pub(crate) fn non_pep695_type_alias_type(checker: &mut Checker, stmt: &StmtAssig
checker.diagnostics.push(create_diagnostic( checker.diagnostics.push(create_diagnostic(
checker.generator(), checker.generator(),
stmt.range(), stmt.range(),
&target_name.id, target_name.id.clone(),
value, value,
&vars, &vars,
Applicability::Safe, Applicability::Safe,
@ -199,7 +200,7 @@ pub(crate) fn non_pep695_type_alias(checker: &mut Checker, stmt: &StmtAnnAssign)
checker.diagnostics.push(create_diagnostic( checker.diagnostics.push(create_diagnostic(
checker.generator(), checker.generator(),
stmt.range(), stmt.range(),
name, name.clone(),
value, value,
&vars, &vars,
// The fix is only safe in a type stub because new-style aliases have different runtime behavior // The fix is only safe in a type stub because new-style aliases have different runtime behavior
@ -217,7 +218,7 @@ pub(crate) fn non_pep695_type_alias(checker: &mut Checker, stmt: &StmtAnnAssign)
fn create_diagnostic( fn create_diagnostic(
generator: Generator, generator: Generator,
stmt_range: TextRange, stmt_range: TextRange,
name: &str, name: Name,
value: &Expr, value: &Expr,
vars: &[TypeVar], vars: &[TypeVar],
applicability: Applicability, applicability: Applicability,
@ -270,7 +271,7 @@ fn create_diagnostic(
range: TextRange::default(), range: TextRange::default(),
name: Box::new(Expr::Name(ExprName { name: Box::new(Expr::Name(ExprName {
range: TextRange::default(), range: TextRange::default(),
id: name.to_string(), id: name,
ctx: ast::ExprContext::Load, ctx: ast::ExprContext::Load,
})), })),
type_params, type_params,

View file

@ -1,13 +1,14 @@
use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, Expr}; use ruff_python_ast::{self as ast, Expr};
use ruff_python_codegen::Generator; use ruff_python_codegen::Generator;
use ruff_python_semantic::{BindingId, ResolvedReference, SemanticModel}; use ruff_python_semantic::{BindingId, ResolvedReference, SemanticModel};
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
/// Format a code snippet to call `name.method()`. /// Format a code snippet to call `name.method()`.
pub(super) fn generate_method_call(name: &str, method: &str, generator: Generator) -> String { pub(super) fn generate_method_call(name: Name, method: &str, generator: Generator) -> String {
// Construct `name`. // Construct `name`.
let var = ast::ExprName { let var = ast::ExprName {
id: name.to_string(), id: name,
ctx: ast::ExprContext::Load, ctx: ast::ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}; };
@ -38,13 +39,13 @@ pub(super) fn generate_method_call(name: &str, method: &str, generator: Generato
/// Format a code snippet comparing `name` to `None` (e.g., `name is None`). /// Format a code snippet comparing `name` to `None` (e.g., `name is None`).
pub(super) fn generate_none_identity_comparison( pub(super) fn generate_none_identity_comparison(
name: &str, name: Name,
negate: bool, negate: bool,
generator: Generator, generator: Generator,
) -> String { ) -> String {
// Construct `name`. // Construct `name`.
let var = ast::ExprName { let var = ast::ExprName {
id: name.to_string(), id: name,
ctx: ast::ExprContext::Load, ctx: ast::ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}; };
@ -77,12 +78,12 @@ pub(super) enum OpenMode {
} }
impl OpenMode { impl OpenMode {
pub(super) fn pathlib_method(self) -> String { pub(super) fn pathlib_method(self) -> Name {
match self { match self {
OpenMode::ReadText => "read_text".to_string(), OpenMode::ReadText => Name::new_static("read_text"),
OpenMode::ReadBytes => "read_bytes".to_string(), OpenMode::ReadBytes => Name::new_static("read_bytes"),
OpenMode::WriteText => "write_text".to_string(), OpenMode::WriteText => Name::new_static("write_text"),
OpenMode::WriteBytes => "write_bytes".to_string(), OpenMode::WriteBytes => Name::new_static("write_bytes"),
} }
} }
} }

View file

@ -70,7 +70,7 @@ pub(crate) fn delete_full_slice(checker: &mut Checker, delete: &ast::StmtDelete)
// Fix is only supported for single-target deletions. // Fix is only supported for single-target deletions.
if delete.targets.len() == 1 { if delete.targets.len() == 1 {
let replacement = generate_method_call(&name.id, "clear", checker.generator()); let replacement = generate_method_call(name.id.clone(), "clear", checker.generator());
diagnostic.set_fix(Fix::unsafe_edit(Edit::replacement( diagnostic.set_fix(Fix::unsafe_edit(Edit::replacement(
replacement, replacement,
delete.start(), delete.start(),

View file

@ -66,7 +66,7 @@ pub(crate) fn isinstance_type_none(checker: &mut Checker, call: &ast::ExprCall)
}; };
let mut diagnostic = Diagnostic::new(IsinstanceTypeNone, call.range()); let mut diagnostic = Diagnostic::new(IsinstanceTypeNone, call.range());
let replacement = let replacement =
generate_none_identity_comparison(object_name, false, checker.generator()); generate_none_identity_comparison(object_name.clone(), false, checker.generator());
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
pad(replacement, call.range(), checker.locator()), pad(replacement, call.range(), checker.locator()),
call.range(), call.range(),

View file

@ -3,6 +3,7 @@ use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::comparable::ComparableExpr; use ruff_python_ast::comparable::ComparableExpr;
use ruff_python_ast::helpers::any_over_expr; use ruff_python_ast::helpers::any_over_expr;
use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, Expr}; use ruff_python_ast::{self as ast, Expr};
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
@ -165,7 +166,12 @@ pub(crate) fn reimplemented_starmap(checker: &mut Checker, target: &StarmapCandi
// - For list and set comprehensions, we'd want to wrap it with `list` and `set` // - For list and set comprehensions, we'd want to wrap it with `list` and `set`
// correspondingly. // correspondingly.
let main_edit = Edit::range_replacement( let main_edit = Edit::range_replacement(
target.try_make_suggestion(starmap_name, &comprehension.iter, func, checker)?, target.try_make_suggestion(
Name::from(starmap_name),
&comprehension.iter,
func,
checker,
)?,
target.range(), target.range(),
); );
Ok(Fix::safe_edits(import_edit, [main_edit])) Ok(Fix::safe_edits(import_edit, [main_edit]))
@ -231,7 +237,7 @@ impl StarmapCandidate<'_> {
/// Try to produce a fix suggestion transforming this node into a call to `starmap`. /// Try to produce a fix suggestion transforming this node into a call to `starmap`.
pub(crate) fn try_make_suggestion( pub(crate) fn try_make_suggestion(
&self, &self,
name: String, name: Name,
iter: &Expr, iter: &Expr,
func: &Expr, func: &Expr,
checker: &Checker, checker: &Checker,
@ -260,7 +266,7 @@ impl StarmapCandidate<'_> {
// ```python // ```python
// list(itertools.starmap(foo, iter)) // list(itertools.starmap(foo, iter))
// ``` // ```
try_construct_call(name, iter, func, "list", checker) try_construct_call(name, iter, func, Name::new_static("list"), checker)
} }
Self::SetComp(_) => { Self::SetComp(_) => {
// For set comprehensions, we replace: // For set comprehensions, we replace:
@ -272,7 +278,7 @@ impl StarmapCandidate<'_> {
// ```python // ```python
// set(itertools.starmap(foo, iter)) // set(itertools.starmap(foo, iter))
// ``` // ```
try_construct_call(name, iter, func, "set", checker) try_construct_call(name, iter, func, Name::new_static("set"), checker)
} }
} }
} }
@ -280,15 +286,15 @@ impl StarmapCandidate<'_> {
/// Try constructing the call to `itertools.starmap` and wrapping it with the given builtin. /// Try constructing the call to `itertools.starmap` and wrapping it with the given builtin.
fn try_construct_call( fn try_construct_call(
name: String, name: Name,
iter: &Expr, iter: &Expr,
func: &Expr, func: &Expr,
builtin: &str, builtin: Name,
checker: &Checker, checker: &Checker,
) -> Result<String> { ) -> Result<String> {
// We can only do our fix if `builtin` identifier is still bound to // We can only do our fix if `builtin` identifier is still bound to
// the built-in type. // the built-in type.
if !checker.semantic().has_builtin_binding(builtin) { if !checker.semantic().has_builtin_binding(&builtin) {
bail!("Can't use built-in `{builtin}` constructor") bail!("Can't use built-in `{builtin}` constructor")
} }
@ -308,7 +314,7 @@ fn try_construct_call(
} }
/// Construct the call to `itertools.starmap` for suggestion. /// Construct the call to `itertools.starmap` for suggestion.
fn construct_starmap_call(starmap_binding: String, iter: &Expr, func: &Expr) -> ast::ExprCall { fn construct_starmap_call(starmap_binding: Name, iter: &Expr, func: &Expr) -> ast::ExprCall {
let starmap = ast::ExprName { let starmap = ast::ExprName {
id: starmap_binding, id: starmap_binding,
ctx: ast::ExprContext::Load, ctx: ast::ExprContext::Load,
@ -326,9 +332,9 @@ fn construct_starmap_call(starmap_binding: String, iter: &Expr, func: &Expr) ->
} }
/// Wrap given function call with yet another call. /// Wrap given function call with yet another call.
fn wrap_with_call_to(call: ast::ExprCall, func_name: &str) -> ast::ExprCall { fn wrap_with_call_to(call: ast::ExprCall, func_name: Name) -> ast::ExprCall {
let name = ast::ExprName { let name = ast::ExprName {
id: func_name.to_string(), id: func_name,
ctx: ast::ExprContext::Load, ctx: ast::ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}; };

View file

@ -86,7 +86,7 @@ pub(crate) fn repeated_global(checker: &mut Checker, mut suite: &[Stmt]) {
Stmt::Nonlocal(stmt) => &stmt.names, Stmt::Nonlocal(stmt) => &stmt.names,
_ => unreachable!(), _ => unreachable!(),
}) })
.map(|identifier| &identifier.id) .map(ruff_python_ast::Identifier::id)
.format(", ") .format(", ")
), ),
range, range,

View file

@ -1,5 +1,6 @@
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, Expr}; use ruff_python_ast::{self as ast, Expr};
use ruff_python_semantic::analyze::typing::is_list; use ruff_python_semantic::analyze::typing::is_list;
use ruff_python_semantic::{Binding, SemanticModel}; use ruff_python_semantic::{Binding, SemanticModel};
@ -61,7 +62,7 @@ pub(crate) fn slice_copy(checker: &mut Checker, subscript: &ast::ExprSubscript)
return; return;
}; };
let mut diagnostic = Diagnostic::new(SliceCopy, subscript.range()); let mut diagnostic = Diagnostic::new(SliceCopy, subscript.range());
let replacement = generate_method_call(name, "copy", checker.generator()); let replacement = generate_method_call(name.clone(), "copy", checker.generator());
diagnostic.set_fix(Fix::safe_edit(Edit::replacement( diagnostic.set_fix(Fix::safe_edit(Edit::replacement(
replacement, replacement,
subscript.start(), subscript.start(),
@ -74,7 +75,7 @@ pub(crate) fn slice_copy(checker: &mut Checker, subscript: &ast::ExprSubscript)
fn match_list_full_slice<'a>( fn match_list_full_slice<'a>(
subscript: &'a ast::ExprSubscript, subscript: &'a ast::ExprSubscript,
semantic: &SemanticModel, semantic: &SemanticModel,
) -> Option<&'a str> { ) -> Option<&'a Name> {
// Check that it is `obj[:]`. // Check that it is `obj[:]`.
if !matches!( if !matches!(
subscript.slice.as_ref(), subscript.slice.as_ref(),

View file

@ -1,5 +1,6 @@
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, CmpOp, Expr}; use ruff_python_ast::{self as ast, CmpOp, Expr};
use ruff_python_semantic::SemanticModel; use ruff_python_semantic::SemanticModel;
use ruff_text_size::Ranged; use ruff_text_size::Ranged;
@ -33,7 +34,7 @@ use crate::rules::refurb::helpers::generate_none_identity_comparison;
/// - [Python documentation: Identity comparisons](https://docs.python.org/3/reference/expressions.html#is-not) /// - [Python documentation: Identity comparisons](https://docs.python.org/3/reference/expressions.html#is-not)
#[violation] #[violation]
pub struct TypeNoneComparison { pub struct TypeNoneComparison {
object: String, object: Name,
comparison: Comparison, comparison: Comparison,
} }
@ -94,14 +95,14 @@ pub(crate) fn type_none_comparison(checker: &mut Checker, compare: &ast::ExprCom
// Get the name of the other object (or `None` if both were `None`). // Get the name of the other object (or `None` if both were `None`).
let other_arg_name = match other_arg { let other_arg_name = match other_arg {
Expr::Name(ast::ExprName { id, .. }) => id.as_str(), Expr::Name(ast::ExprName { id, .. }) => id.clone(),
Expr::NoneLiteral { .. } => "None", Expr::NoneLiteral { .. } => Name::new_static("None"),
_ => return, _ => return,
}; };
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
TypeNoneComparison { TypeNoneComparison {
object: other_arg_name.to_string(), object: other_arg_name.clone(),
comparison, comparison,
}, },
compare.range(), compare.range(),

View file

@ -3,6 +3,7 @@ use std::fmt;
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast as ast; use ruff_python_ast as ast;
use ruff_python_ast::name::Name;
use ruff_python_ast::{Arguments, Expr, Int}; use ruff_python_ast::{Arguments, Expr, Int};
use ruff_python_codegen::Generator; use ruff_python_codegen::Generator;
use ruff_python_semantic::analyze::typing::{is_dict, is_list, is_set, is_tuple}; use ruff_python_semantic::analyze::typing::{is_dict, is_list, is_set, is_tuple};
@ -189,7 +190,7 @@ pub(crate) fn unnecessary_enumerate(checker: &mut Checker, stmt_for: &ast::StmtF
) )
}) { }) {
let replace_iter = Edit::range_replacement( let replace_iter = Edit::range_replacement(
generate_range_len_call(&sequence.id, checker.generator()), generate_range_len_call(sequence.id.clone(), checker.generator()),
stmt_for.iter.range(), stmt_for.iter.range(),
); );
@ -229,10 +230,10 @@ impl fmt::Display for EnumerateSubset {
/// Format a code snippet to call `range(len(name))`, where `name` is the given /// Format a code snippet to call `range(len(name))`, where `name` is the given
/// sequence name. /// sequence name.
fn generate_range_len_call(name: &str, generator: Generator) -> String { fn generate_range_len_call(name: Name, generator: Generator) -> String {
// Construct `name`. // Construct `name`.
let var = ast::ExprName { let var = ast::ExprName {
id: name.to_string(), id: name,
ctx: ast::ExprContext::Load, ctx: ast::ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}; };
@ -240,7 +241,7 @@ fn generate_range_len_call(name: &str, generator: Generator) -> String {
let len = ast::ExprCall { let len = ast::ExprCall {
func: Box::new( func: Box::new(
ast::ExprName { ast::ExprName {
id: "len".to_string(), id: Name::new_static("len"),
ctx: ast::ExprContext::Load, ctx: ast::ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
} }
@ -257,7 +258,7 @@ fn generate_range_len_call(name: &str, generator: Generator) -> String {
let range = ast::ExprCall { let range = ast::ExprCall {
func: Box::new( func: Box::new(
ast::ExprName { ast::ExprName {
id: "range".to_string(), id: Name::new_static("range"),
ctx: ast::ExprContext::Load, ctx: ast::ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
} }

View file

@ -5,6 +5,7 @@ use anyhow::Result;
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, Expr, Operator, ParameterWithDefault, Parameters}; use ruff_python_ast::{self as ast, Expr, Operator, ParameterWithDefault, Parameters};
use ruff_python_parser::typing::parse_type_annotation; use ruff_python_parser::typing::parse_type_annotation;
use ruff_text_size::{Ranged, TextRange}; use ruff_text_size::{Ranged, TextRange};
@ -145,7 +146,7 @@ fn generate_fix(checker: &Checker, conversion_type: ConversionType, expr: &Expr)
let new_expr = Expr::Subscript(ast::ExprSubscript { let new_expr = Expr::Subscript(ast::ExprSubscript {
range: TextRange::default(), range: TextRange::default(),
value: Box::new(Expr::Name(ast::ExprName { value: Box::new(Expr::Name(ast::ExprName {
id: binding, id: Name::new(binding),
ctx: ast::ExprContext::Store, ctx: ast::ExprContext::Store,
range: TextRange::default(), range: TextRange::default(),
})), })),

View file

@ -1,5 +1,6 @@
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation}; use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, Expr}; use ruff_python_ast::{self as ast, Expr};
use ruff_python_semantic::analyze::typing::is_mutable_expr; use ruff_python_semantic::analyze::typing::is_mutable_expr;
@ -99,7 +100,7 @@ pub(crate) fn mutable_fromkeys_value(checker: &mut Checker, call: &ast::ExprCall
fn generate_dict_comprehension(keys: &Expr, value: &Expr, generator: Generator) -> String { fn generate_dict_comprehension(keys: &Expr, value: &Expr, generator: Generator) -> String {
// Construct `key`. // Construct `key`.
let key = ast::ExprName { let key = ast::ExprName {
id: "key".to_string(), id: Name::new_static("key"),
ctx: ast::ExprContext::Load, ctx: ast::ExprContext::Load,
range: TextRange::default(), range: TextRange::default(),
}; };

View file

@ -13,6 +13,8 @@ license = { workspace = true }
[lib] [lib]
[dependencies] [dependencies]
ruff_cache = { workspace = true, optional = true }
ruff_macros = { workspace = true, optional = true }
ruff_python_trivia = { workspace = true } ruff_python_trivia = { workspace = true }
ruff_source_file = { workspace = true } ruff_source_file = { workspace = true }
ruff_text_size = { workspace = true } ruff_text_size = { workspace = true }
@ -23,10 +25,16 @@ is-macro = { workspace = true }
itertools = { workspace = true } itertools = { workspace = true }
once_cell = { workspace = true } once_cell = { workspace = true }
rustc-hash = { workspace = true } rustc-hash = { workspace = true }
schemars = { workspace = true, optional = true }
serde = { workspace = true, optional = true } serde = { workspace = true, optional = true }
compact_str = { workspace = true }
[features] [features]
serde = ["dep:serde", "ruff_text_size/serde"] serde = ["dep:serde", "ruff_text_size/serde", "dep:ruff_cache", "compact_str/serde", "dep:ruff_macros", "dep:schemars"]
[lints] [lints]
workspace = true workspace = true
[package.metadata.cargo-shear]
# Used via `CacheKey` macro expansion.
ignored = ["ruff_cache"]

View file

@ -7,7 +7,7 @@ use ruff_python_trivia::{indentation_at_offset, CommentRanges, SimpleTokenKind,
use ruff_source_file::Locator; use ruff_source_file::Locator;
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize}; use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
use crate::name::{QualifiedName, QualifiedNameBuilder}; use crate::name::{Name, QualifiedName, QualifiedNameBuilder};
use crate::parenthesize::parenthesized_range; use crate::parenthesize::parenthesized_range;
use crate::statement_visitor::StatementVisitor; use crate::statement_visitor::StatementVisitor;
use crate::visitor::Visitor; use crate::visitor::Visitor;
@ -1403,7 +1403,7 @@ pub fn pep_604_union(elts: &[Expr]) -> Expr {
} }
/// Format the expression as a `typing.Optional`-style optional. /// Format the expression as a `typing.Optional`-style optional.
pub fn typing_optional(elt: Expr, binding: String) -> Expr { pub fn typing_optional(elt: Expr, binding: Name) -> Expr {
Expr::Subscript(ast::ExprSubscript { Expr::Subscript(ast::ExprSubscript {
value: Box::new(Expr::Name(ast::ExprName { value: Box::new(Expr::Name(ast::ExprName {
id: binding, id: binding,
@ -1417,8 +1417,8 @@ pub fn typing_optional(elt: Expr, binding: String) -> Expr {
} }
/// Format the expressions as a `typing.Union`-style union. /// Format the expressions as a `typing.Union`-style union.
pub fn typing_union(elts: &[Expr], binding: String) -> Expr { pub fn typing_union(elts: &[Expr], binding: Name) -> Expr {
fn tuple(elts: &[Expr], binding: String) -> Expr { fn tuple(elts: &[Expr], binding: Name) -> Expr {
match elts { match elts {
[] => Expr::Tuple(ast::ExprTuple { [] => Expr::Tuple(ast::ExprTuple {
elts: vec![], elts: vec![],

View file

@ -1,9 +1,213 @@
use std::borrow::{Borrow, Cow};
use std::fmt::{Debug, Display, Formatter, Write}; use std::fmt::{Debug, Display, Formatter, Write};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::ops::Deref; use std::ops::Deref;
use crate::{nodes, Expr}; use crate::{nodes, Expr};
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize, ruff_macros::CacheKey)
)]
pub struct Name(compact_str::CompactString);
impl Name {
#[inline]
pub fn empty() -> Self {
Self(compact_str::CompactString::default())
}
#[inline]
pub fn new(name: impl AsRef<str>) -> Self {
Self(compact_str::CompactString::new(name))
}
#[inline]
pub fn new_static(name: &'static str) -> Self {
// TODO(Micha): Use CompactString::const_new once we upgrade to 0.8 https://github.com/ParkMyCar/compact_str/pull/336
Self(compact_str::CompactString::from(name))
}
pub fn as_str(&self) -> &str {
self.0.as_str()
}
}
impl Debug for Name {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "Name({:?})", self.as_str())
}
}
impl AsRef<str> for Name {
#[inline]
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl Deref for Name {
type Target = str;
#[inline]
fn deref(&self) -> &Self::Target {
self.as_str()
}
}
impl Borrow<str> for Name {
#[inline]
fn borrow(&self) -> &str {
self.as_str()
}
}
impl<'a> From<&'a str> for Name {
#[inline]
fn from(s: &'a str) -> Self {
Name(s.into())
}
}
impl From<String> for Name {
#[inline]
fn from(s: String) -> Self {
Name(s.into())
}
}
impl<'a> From<&'a String> for Name {
#[inline]
fn from(s: &'a String) -> Self {
Name(s.into())
}
}
impl<'a> From<Cow<'a, str>> for Name {
#[inline]
fn from(cow: Cow<'a, str>) -> Self {
Name(cow.into())
}
}
impl From<Box<str>> for Name {
#[inline]
fn from(b: Box<str>) -> Self {
Name(b.into())
}
}
impl From<compact_str::CompactString> for Name {
#[inline]
fn from(value: compact_str::CompactString) -> Self {
Self(value)
}
}
impl From<Name> for compact_str::CompactString {
#[inline]
fn from(name: Name) -> Self {
name.0
}
}
impl FromIterator<char> for Name {
fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> Self {
Self(iter.into_iter().collect())
}
}
impl std::fmt::Display for Name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
impl PartialEq<str> for Name {
#[inline]
fn eq(&self, other: &str) -> bool {
self.as_str() == other
}
}
impl PartialEq<Name> for str {
#[inline]
fn eq(&self, other: &Name) -> bool {
other == self
}
}
impl PartialEq<&str> for Name {
#[inline]
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}
impl PartialEq<Name> for &str {
#[inline]
fn eq(&self, other: &Name) -> bool {
other == self
}
}
impl PartialEq<String> for Name {
fn eq(&self, other: &String) -> bool {
self == other.as_str()
}
}
impl PartialEq<Name> for String {
#[inline]
fn eq(&self, other: &Name) -> bool {
other == self
}
}
impl PartialEq<&String> for Name {
#[inline]
fn eq(&self, other: &&String) -> bool {
self.as_str() == *other
}
}
impl PartialEq<Name> for &String {
#[inline]
fn eq(&self, other: &Name) -> bool {
other == self
}
}
#[cfg(feature = "serde")]
impl schemars::JsonSchema for Name {
fn is_referenceable() -> bool {
String::is_referenceable()
}
fn schema_name() -> String {
String::schema_name()
}
fn schema_id() -> std::borrow::Cow<'static, str> {
String::schema_id()
}
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
String::json_schema(gen)
}
fn _schemars_private_non_optional_json_schema(
gen: &mut schemars::gen::SchemaGenerator,
) -> schemars::schema::Schema {
String::_schemars_private_non_optional_json_schema(gen)
}
fn _schemars_private_is_option() -> bool {
String::_schemars_private_is_option()
}
}
/// A representation of a qualified name, like `typing.List`. /// A representation of a qualified name, like `typing.List`.
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct QualifiedName<'a>(SegmentsVec<'a>); pub struct QualifiedName<'a>(SegmentsVec<'a>);

View file

@ -12,6 +12,7 @@ use itertools::Itertools;
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize}; use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
use crate::name::Name;
use crate::{ use crate::{
int, int,
str::Quote, str::Quote,
@ -1762,12 +1763,6 @@ impl PartialEq<str> for StringLiteralValue {
} }
} }
impl PartialEq<String> for StringLiteralValue {
fn eq(&self, other: &String) -> bool {
self == other.as_str()
}
}
impl fmt::Display for StringLiteralValue { impl fmt::Display for StringLiteralValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.to_str()) f.write_str(self.to_str())
@ -2740,10 +2735,16 @@ impl From<ExprStarred> for Expr {
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct ExprName { pub struct ExprName {
pub range: TextRange, pub range: TextRange,
pub id: String, pub id: Name,
pub ctx: ExprContext, pub ctx: ExprContext,
} }
impl ExprName {
pub fn id(&self) -> &Name {
&self.id
}
}
impl From<ExprName> for Expr { impl From<ExprName> for Expr {
fn from(payload: ExprName) -> Self { fn from(payload: ExprName) -> Self {
Expr::Name(payload) Expr::Name(payload)
@ -3763,19 +3764,23 @@ impl IpyEscapeKind {
/// ``` /// ```
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Identifier { pub struct Identifier {
pub id: String, pub id: Name,
pub range: TextRange, pub range: TextRange,
} }
impl Identifier { impl Identifier {
#[inline] #[inline]
pub fn new(id: impl Into<String>, range: TextRange) -> Self { pub fn new(id: impl Into<Name>, range: TextRange) -> Self {
Self { Self {
id: id.into(), id: id.into(),
range, range,
} }
} }
pub fn id(&self) -> &Name {
&self.id
}
pub fn is_valid(&self) -> bool { pub fn is_valid(&self) -> bool {
!self.id.is_empty() !self.id.is_empty()
} }
@ -3798,7 +3803,7 @@ impl PartialEq<str> for Identifier {
impl PartialEq<String> for Identifier { impl PartialEq<String> for Identifier {
#[inline] #[inline]
fn eq(&self, other: &String) -> bool { fn eq(&self, other: &String) -> bool {
&self.id == other self.id == other
} }
} }
@ -3817,22 +3822,15 @@ impl AsRef<str> for Identifier {
} }
} }
impl AsRef<String> for Identifier {
#[inline]
fn as_ref(&self) -> &String {
&self.id
}
}
impl std::fmt::Display for Identifier { impl std::fmt::Display for Identifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&self.id, f) std::fmt::Display::fmt(&self.id, f)
} }
} }
impl From<Identifier> for String { impl From<Identifier> for Name {
#[inline] #[inline]
fn from(identifier: Identifier) -> String { fn from(identifier: Identifier) -> Name {
identifier.id identifier.id
} }
} }

View file

@ -19,6 +19,7 @@ ruff_text_size = { workspace = true }
bitflags = { workspace = true } bitflags = { workspace = true }
bstr = { workspace = true } bstr = { workspace = true }
compact_str = { workspace = true }
memchr = { workspace = true } memchr = { workspace = true }
rustc-hash = { workspace = true } rustc-hash = { workspace = true }
static_assertions = { workspace = true } static_assertions = { workspace = true }

View file

@ -12,6 +12,7 @@ use std::str::FromStr;
use unicode_ident::{is_xid_continue, is_xid_start}; use unicode_ident::{is_xid_continue, is_xid_start};
use unicode_normalization::UnicodeNormalization; use unicode_normalization::UnicodeNormalization;
use ruff_python_ast::name::Name;
use ruff_python_ast::{Int, IpyEscapeKind, StringFlags}; use ruff_python_ast::{Int, IpyEscapeKind, StringFlags};
use ruff_python_trivia::is_python_whitespace; use ruff_python_trivia::is_python_whitespace;
use ruff_text_size::{TextLen, TextRange, TextSize}; use ruff_text_size::{TextLen, TextRange, TextSize};
@ -643,7 +644,7 @@ impl<'src> Lexer<'src> {
let text = self.token_text(); let text = self.token_text();
if !is_ascii { if !is_ascii {
self.current_value = TokenValue::Name(text.nfkc().collect::<String>().into_boxed_str()); self.current_value = TokenValue::Name(text.nfkc().collect::<Name>());
return TokenKind::Name; return TokenKind::Name;
} }
@ -687,7 +688,7 @@ impl<'src> Lexer<'src> {
"with" => TokenKind::With, "with" => TokenKind::With,
"yield" => TokenKind::Yield, "yield" => TokenKind::Yield,
_ => { _ => {
self.current_value = TokenValue::Name(text.to_string().into_boxed_str()); self.current_value = TokenValue::Name(Name::new(text));
TokenKind::Name TokenKind::Name
} }
} }

View file

@ -4,6 +4,7 @@ use std::ops::Deref;
use bitflags::bitflags; use bitflags::bitflags;
use rustc_hash::{FxBuildHasher, FxHashSet}; use rustc_hash::{FxBuildHasher, FxHashSet};
use ruff_python_ast::name::Name;
use ruff_python_ast::{ use ruff_python_ast::{
self as ast, BoolOp, CmpOp, ConversionFlag, Expr, ExprContext, FStringElement, FStringElements, self as ast, BoolOp, CmpOp, ConversionFlag, Expr, ExprContext, FStringElement, FStringElements,
IpyEscapeKind, Number, Operator, UnaryOp, IpyEscapeKind, Number, Operator, UnaryOp,
@ -477,14 +478,11 @@ impl<'src> Parser<'src> {
let TokenValue::Name(name) = self.bump_value(TokenKind::Name) else { let TokenValue::Name(name) = self.bump_value(TokenKind::Name) else {
unreachable!(); unreachable!();
}; };
return ast::Identifier { return ast::Identifier { id: name, range };
id: name.into_string(),
range,
};
} }
if self.current_token_kind().is_soft_keyword() { if self.current_token_kind().is_soft_keyword() {
let id = self.src_text(range).to_string(); let id = Name::new(self.src_text(range));
self.bump_soft_keyword_as_name(); self.bump_soft_keyword_as_name();
return ast::Identifier { id, range }; return ast::Identifier { id, range };
} }
@ -499,7 +497,7 @@ impl<'src> Parser<'src> {
range, range,
); );
let id = self.src_text(range).to_string(); let id = Name::new(self.src_text(range));
self.bump_any(); self.bump_any();
ast::Identifier { id, range } ast::Identifier { id, range }
} else { } else {
@ -509,7 +507,7 @@ impl<'src> Parser<'src> {
); );
ast::Identifier { ast::Identifier {
id: String::new(), id: Name::empty(),
range: self.missing_node_range(), range: self.missing_node_range(),
} }
} }
@ -597,7 +595,7 @@ impl<'src> Parser<'src> {
); );
Expr::Name(ast::ExprName { Expr::Name(ast::ExprName {
range: self.missing_node_range(), range: self.missing_node_range(),
id: String::new(), id: Name::empty(),
ctx: ExprContext::Invalid, ctx: ExprContext::Invalid,
}) })
} }
@ -719,7 +717,7 @@ impl<'src> Parser<'src> {
&parsed_expr, &parsed_expr,
); );
ast::Identifier { ast::Identifier {
id: String::new(), id: Name::empty(),
range: parsed_expr.range(), range: parsed_expr.range(),
} }
}; };
@ -793,7 +791,7 @@ impl<'src> Parser<'src> {
value: Box::new(value), value: Box::new(value),
slice: Box::new(Expr::Name(ast::ExprName { slice: Box::new(Expr::Name(ast::ExprName {
range: slice_range, range: slice_range,
id: String::new(), id: Name::empty(),
ctx: ExprContext::Invalid, ctx: ExprContext::Invalid,
})), })),
ctx: ExprContext::Load, ctx: ExprContext::Load,

View file

@ -1,3 +1,4 @@
use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, Expr, ExprContext, Number, Operator, Pattern, Singleton}; use ruff_python_ast::{self as ast, Expr, ExprContext, Number, Operator, Pattern, Singleton};
use ruff_text_size::{Ranged, TextSize}; use ruff_text_size::{Ranged, TextSize};
@ -510,7 +511,7 @@ impl<'src> Parser<'src> {
); );
let invalid_node = Expr::Name(ast::ExprName { let invalid_node = Expr::Name(ast::ExprName {
range: self.missing_node_range(), range: self.missing_node_range(),
id: String::new(), id: Name::empty(),
ctx: ExprContext::Invalid, ctx: ExprContext::Invalid,
}); });
Pattern::MatchValue(ast::PatternMatchValue { Pattern::MatchValue(ast::PatternMatchValue {
@ -616,7 +617,7 @@ impl<'src> Parser<'src> {
} else { } else {
Box::new(Expr::Name(ast::ExprName { Box::new(Expr::Name(ast::ExprName {
range: ident.range(), range: ident.range(),
id: String::new(), id: Name::empty(),
ctx: ExprContext::Invalid, ctx: ExprContext::Invalid,
})) }))
} }
@ -667,7 +668,7 @@ impl<'src> Parser<'src> {
&pattern, &pattern,
); );
ast::Identifier { ast::Identifier {
id: String::new(), id: Name::empty(),
range: parser.missing_node_range(), range: parser.missing_node_range(),
} }
}; };

View file

@ -1,3 +1,4 @@
use ruff_python_ast::name::Name;
use ruff_python_ast::{self as ast, Expr, ExprContext, Pattern}; use ruff_python_ast::{self as ast, Expr, ExprContext, Pattern};
use ruff_text_size::{Ranged, TextLen, TextRange}; use ruff_text_size::{Ranged, TextLen, TextRange};
@ -110,7 +111,7 @@ pub(super) fn pattern_to_expr(pattern: Pattern) -> Expr {
range, range,
value: Box::new(Expr::Name(ast::ExprName { value: Box::new(Expr::Name(ast::ExprName {
range: TextRange::new(range.end() - "_".text_len(), range.end()), range: TextRange::new(range.end() - "_".text_len(), range.end()),
id: "_".to_string(), id: Name::new_static("_"),
ctx: ExprContext::Store, ctx: ExprContext::Store,
})), })),
ctx: ExprContext::Store, ctx: ExprContext::Store,
@ -124,7 +125,7 @@ pub(super) fn pattern_to_expr(pattern: Pattern) -> Expr {
}) => match (pattern, name) { }) => match (pattern, name) {
(Some(_), Some(_)) => Expr::Name(ast::ExprName { (Some(_), Some(_)) => Expr::Name(ast::ExprName {
range, range,
id: String::new(), id: Name::empty(),
ctx: ExprContext::Invalid, ctx: ExprContext::Invalid,
}), }),
(Some(pattern), None) => pattern_to_expr(*pattern), (Some(pattern), None) => pattern_to_expr(*pattern),
@ -135,7 +136,7 @@ pub(super) fn pattern_to_expr(pattern: Pattern) -> Expr {
}), }),
(None, None) => Expr::Name(ast::ExprName { (None, None) => Expr::Name(ast::ExprName {
range, range,
id: "_".to_string(), id: Name::new_static("_"),
ctx: ExprContext::Store, ctx: ExprContext::Store,
}), }),
}, },

View file

@ -1,11 +1,11 @@
--- ---
source: crates/ruff_python_parser/src/parser/tests.rs source: crates/ruff_python_parser/src/parser/tests.rs
expression: expr expression: parsed.expr()
--- ---
Name( Name(
ExprName { ExprName {
range: 0..5, range: 0..5,
id: "first", id: Name("first"),
ctx: Load, ctx: Load,
}, },
) )

View file

@ -1,6 +1,6 @@
--- ---
source: crates/ruff_python_parser/src/parser/tests.rs source: crates/ruff_python_parser/src/parser/tests.rs
expression: parse_ast expression: parsed.syntax()
--- ---
Module( Module(
ModModule { ModModule {
@ -15,7 +15,7 @@ Module(
left: Name( left: Name(
ExprName { ExprName {
range: 27..28, range: 27..28,
id: "a", id: Name("a"),
ctx: Load, ctx: Load,
}, },
), ),
@ -23,7 +23,7 @@ Module(
right: Name( right: Name(
ExprName { ExprName {
range: 39..40, range: 39..40,
id: "b", id: Name("b"),
ctx: Load, ctx: Load,
}, },
), ),
@ -128,7 +128,7 @@ Module(
is_async: false, is_async: false,
decorator_list: [], decorator_list: [],
name: Identifier { name: Identifier {
id: "foo", id: Name("foo"),
range: 570..573, range: 570..573,
}, },
type_params: None, type_params: None,
@ -152,7 +152,7 @@ Module(
left: Name( left: Name(
ExprName { ExprName {
range: 598..599, range: 598..599,
id: "a", id: Name("a"),
ctx: Load, ctx: Load,
}, },
), ),
@ -163,7 +163,7 @@ Module(
Name( Name(
ExprName { ExprName {
range: 619..620, range: 619..620,
id: "b", id: Name("b"),
ctx: Load, ctx: Load,
}, },
), ),
@ -204,7 +204,7 @@ Module(
target: Name( target: Name(
ExprName { ExprName {
range: 715..716, range: 715..716,
id: "a", id: Name("a"),
ctx: Store, ctx: Store,
}, },
), ),
@ -214,7 +214,7 @@ Module(
func: Name( func: Name(
ExprName { ExprName {
range: 720..725, range: 720..725,
id: "range", id: Name("range"),
ctx: Load, ctx: Load,
}, },
), ),
@ -253,7 +253,7 @@ Module(
Name( Name(
ExprName { ExprName {
range: 739..741, range: 739..741,
id: "p1", id: Name("p1"),
ctx: Store, ctx: Store,
}, },
), ),
@ -273,14 +273,14 @@ Module(
target: Name( target: Name(
ExprName { ExprName {
range: 749..751, range: 749..751,
id: "p2", id: Name("p2"),
ctx: Store, ctx: Store,
}, },
), ),
annotation: Name( annotation: Name(
ExprName { ExprName {
range: 753..756, range: 753..756,
id: "str", id: Name("str"),
ctx: Load, ctx: Load,
}, },
), ),
@ -303,7 +303,7 @@ Module(
Name( Name(
ExprName { ExprName {
range: 764..767, range: 764..767,
id: "foo", id: Name("foo"),
ctx: Store, ctx: Store,
}, },
), ),
@ -331,7 +331,7 @@ Module(
Name( Name(
ExprName { ExprName {
range: 792..795, range: 792..795,
id: "foo", id: Name("foo"),
ctx: Store, ctx: Store,
}, },
), ),

View file

@ -1,6 +1,6 @@
--- ---
source: crates/ruff_python_parser/src/parser/tests.rs source: crates/ruff_python_parser/src/parser/tests.rs
expression: parse_ast expression: suite
--- ---
[ [
Assign( Assign(
@ -10,7 +10,7 @@ expression: parse_ast
Name( Name(
ExprName { ExprName {
range: 0..1, range: 0..1,
id: "x", id: Name("x"),
ctx: Store, ctx: Store,
}, },
), ),

View file

@ -1,7 +1,9 @@
use compact_str::CompactString;
use std::fmt::Display; use std::fmt::Display;
use rustc_hash::{FxBuildHasher, FxHashSet}; use rustc_hash::{FxBuildHasher, FxHashSet};
use ruff_python_ast::name::Name;
use ruff_python_ast::{ use ruff_python_ast::{
self as ast, ExceptHandler, Expr, ExprContext, IpyEscapeKind, Operator, Stmt, WithItem, self as ast, ExceptHandler, Expr, ExprContext, IpyEscapeKind, Operator, Stmt, WithItem,
}; };
@ -623,7 +625,7 @@ impl<'src> Parser<'src> {
let range = self.node_range(start); let range = self.node_range(start);
return ast::Alias { return ast::Alias {
name: ast::Identifier { name: ast::Identifier {
id: "*".into(), id: Name::new_static("*"),
range, range,
}, },
asname: None, asname: None,
@ -669,7 +671,7 @@ impl<'src> Parser<'src> {
fn parse_dotted_name(&mut self) -> ast::Identifier { fn parse_dotted_name(&mut self) -> ast::Identifier {
let start = self.node_start(); let start = self.node_start();
let mut dotted_name = self.parse_identifier().id; let mut dotted_name: CompactString = self.parse_identifier().id.into();
let mut progress = ParserProgress::default(); let mut progress = ParserProgress::default();
while self.eat(TokenKind::Dot) { while self.eat(TokenKind::Dot) {
@ -686,7 +688,7 @@ impl<'src> Parser<'src> {
// import a.b.c // import a.b.c
// import a . b . c // import a . b . c
ast::Identifier { ast::Identifier {
id: dotted_name, id: Name::from(dotted_name),
range: self.node_range(start), range: self.node_range(start),
} }
} }

View file

@ -7,7 +7,7 @@ expression: lex_source(source)
[ [
( (
Name( Name(
"a_variable", Name("a_variable"),
), ),
0..10, 0..10,
), ),

View file

@ -7,7 +7,7 @@ expression: lex_source(source)
[ [
( (
Name( Name(
"x", Name("x"),
), ),
3..4, 3..4,
), ),

View file

@ -7,7 +7,7 @@ expression: "lex_source_with_offset(source, TextSize::new(7))"
[ [
( (
Name( Name(
"y", Name("y"),
), ),
7..8, 7..8,
), ),
@ -17,7 +17,7 @@ expression: "lex_source_with_offset(source, TextSize::new(7))"
), ),
( (
Name( Name(
"z", Name("z"),
), ),
11..12, 11..12,
), ),

View file

@ -7,7 +7,7 @@ expression: "lex_source_with_offset(source, TextSize::new(11))"
[ [
( (
Name( Name(
"z", Name("z"),
), ),
11..12, 11..12,
), ),

View file

@ -11,7 +11,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"first", Name("first"),
), ),
3..8, 3..8,
), ),
@ -33,7 +33,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"second", Name("second"),
), ),
17..23, 17..23,
), ),
@ -63,7 +63,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
42..45, 42..45,
), ),

View file

@ -11,7 +11,7 @@ expression: double_dedent_with_eol(MAC_EOL)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
4..7, 4..7,
), ),
@ -41,7 +41,7 @@ expression: double_dedent_with_eol(MAC_EOL)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
15..16, 15..16,
), ),

View file

@ -11,7 +11,7 @@ expression: double_dedent_with_tabs_eol(MAC_EOL)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
4..7, 4..7,
), ),
@ -41,7 +41,7 @@ expression: double_dedent_with_tabs_eol(MAC_EOL)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
15..16, 15..16,
), ),

View file

@ -11,7 +11,7 @@ expression: double_dedent_with_tabs_eol(UNIX_EOL)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
4..7, 4..7,
), ),
@ -41,7 +41,7 @@ expression: double_dedent_with_tabs_eol(UNIX_EOL)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
15..16, 15..16,
), ),

View file

@ -11,7 +11,7 @@ expression: double_dedent_with_tabs_eol(WINDOWS_EOL)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
4..7, 4..7,
), ),
@ -41,7 +41,7 @@ expression: double_dedent_with_tabs_eol(WINDOWS_EOL)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
16..17, 16..17,
), ),

View file

@ -11,7 +11,7 @@ expression: double_dedent_with_eol(UNIX_EOL)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
4..7, 4..7,
), ),
@ -41,7 +41,7 @@ expression: double_dedent_with_eol(UNIX_EOL)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
15..16, 15..16,
), ),

View file

@ -11,7 +11,7 @@ expression: double_dedent_with_eol(WINDOWS_EOL)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
4..7, 4..7,
), ),
@ -41,7 +41,7 @@ expression: double_dedent_with_eol(WINDOWS_EOL)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
16..17, 16..17,
), ),

View file

@ -27,7 +27,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
10..13, 10..13,
), ),
@ -50,7 +50,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"bar", Name("bar"),
), ),
28..31, 28..31,
), ),
@ -73,7 +73,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"three", Name("three"),
), ),
36..41, 36..41,
), ),

View file

@ -35,7 +35,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
39..40, 39..40,
), ),

View file

@ -18,7 +18,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
3..4, 3..4,
), ),
@ -28,7 +28,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"s", Name("s"),
), ),
5..6, 5..6,
), ),
@ -51,7 +51,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
9..10, 9..10,
), ),
@ -65,7 +65,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"r", Name("r"),
), ),
12..13, 12..13,
), ),
@ -88,7 +88,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
16..17, 16..17,
), ),

View file

@ -27,7 +27,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
4..5, 4..5,
), ),
@ -50,7 +50,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
10..11, 10..11,
), ),

View file

@ -27,7 +27,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
4..7, 4..7,
), ),
@ -64,7 +64,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
15..18, 15..18,
), ),

View file

@ -27,7 +27,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
5..6, 5..6,
), ),
@ -50,7 +50,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
11..12, 11..12,
), ),

View file

@ -31,7 +31,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
14..15, 14..15,
), ),
@ -49,7 +49,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"y", Name("y"),
), ),
38..39, 38..39,
), ),

View file

@ -93,7 +93,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
81..82, 81..82,
), ),

View file

@ -27,7 +27,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"BULLET", Name("BULLET"),
), ),
6..12, 6..12,
), ),

View file

@ -47,7 +47,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
14..15, 14..15,
), ),
@ -68,7 +68,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"wow", Name("wow"),
), ),
21..24, 21..24,
), ),

View file

@ -18,7 +18,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
3..6, 3..6,
), ),
@ -45,7 +45,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
10..11, 10..11,
), ),
@ -59,7 +59,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"s", Name("s"),
), ),
13..14, 13..14,
), ),
@ -95,7 +95,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
21..22, 21..22,
), ),
@ -118,7 +118,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"y", Name("y"),
), ),
25..26, 25..26,
), ),
@ -222,7 +222,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
46..47, 46..47,
), ),
@ -254,7 +254,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"pop", Name("pop"),
), ),
53..56, 53..56,
), ),

View file

@ -31,7 +31,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"pwd", Name("pwd"),
), ),
8..11, 8..11,
), ),

View file

@ -22,7 +22,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
10..11, 10..11,
), ),
@ -36,7 +36,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
13..14, 13..14,
), ),
@ -80,7 +80,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
29..30, 29..30,
), ),
@ -94,7 +94,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
32..33, 32..33,
), ),

View file

@ -31,7 +31,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
12..13, 12..13,
), ),
@ -98,7 +98,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
35..36, 35..36,
), ),
@ -165,7 +165,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
78..79, 78..79,
), ),
@ -236,7 +236,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
97..98, 97..98,
), ),
@ -259,7 +259,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"b", Name("b"),
), ),
109..110, 109..110,
), ),

View file

@ -18,7 +18,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
3..4, 3..4,
), ),
@ -58,7 +58,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
12..13, 12..13,
), ),
@ -95,7 +95,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
21..22, 21..22,
), ),
@ -109,7 +109,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"y", Name("y"),
), ),
24..25, 24..25,
), ),
@ -150,7 +150,7 @@ expression: lex_source(source)
), ),
( (
Name( Name(
"x", Name("x"),
), ),
34..35, 34..35,
), ),

View file

@ -11,7 +11,7 @@ expression: indentation_with_eol(MAC_EOL)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
4..7, 4..7,
), ),

View file

@ -11,7 +11,7 @@ expression: indentation_with_eol(UNIX_EOL)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
4..7, 4..7,
), ),

View file

@ -11,7 +11,7 @@ expression: indentation_with_eol(WINDOWS_EOL)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
4..7, 4..7,
), ),

View file

@ -7,7 +7,7 @@ expression: lex_jupyter_source(source)
[ [
( (
Name( Name(
"pwd", Name("pwd"),
), ),
0..3, 0..3,
), ),
@ -28,7 +28,7 @@ expression: lex_jupyter_source(source)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
11..14, 11..14,
), ),
@ -49,7 +49,7 @@ expression: lex_jupyter_source(source)
), ),
( (
Name( Name(
"bar", Name("bar"),
), ),
31..34, 31..34,
), ),
@ -70,7 +70,7 @@ expression: lex_jupyter_source(source)
), ),
( (
Name( Name(
"baz", Name("baz"),
), ),
51..54, 51..54,
), ),

View file

@ -11,7 +11,7 @@ expression: lex_jupyter_source(source)
), ),
( (
Name( Name(
"foo", Name("foo"),
), ),
6..9, 6..9,
), ),
@ -33,7 +33,7 @@ expression: lex_jupyter_source(source)
), ),
( (
Name( Name(
"bar", Name("bar"),
), ),
20..23, 20..23,
), ),

View file

@ -7,7 +7,7 @@ expression: newline_in_brackets_eol(MAC_EOL)
[ [
( (
Name( Name(
"x", Name("x"),
), ),
0..1, 0..1,
), ),

View file

@ -7,7 +7,7 @@ expression: newline_in_brackets_eol(UNIX_EOL)
[ [
( (
Name( Name(
"x", Name("x"),
), ),
0..1, 0..1,
), ),

View file

@ -7,7 +7,7 @@ expression: newline_in_brackets_eol(WINDOWS_EOL)
[ [
( (
Name( Name(
"x", Name("x"),
), ),
0..1, 0..1,
), ),

View file

@ -1,6 +1,6 @@
--- ---
source: crates/ruff_python_parser/src/string.rs source: crates/ruff_python_parser/src/string.rs
expression: parse_ast expression: suite
--- ---
[ [
Assign( Assign(
@ -10,7 +10,7 @@ expression: parse_ast
Name( Name(
ExprName { ExprName {
range: 0..4, range: 0..4,
id: "bold", id: Name("bold"),
ctx: Store, ctx: Store,
}, },
), ),

View file

@ -1,6 +1,6 @@
--- ---
source: crates/ruff_python_parser/src/string.rs source: crates/ruff_python_parser/src/string.rs
expression: parse_ast expression: suite
--- ---
[ [
Expr( Expr(
@ -27,7 +27,7 @@ expression: parse_ast
expression: Name( expression: Name(
ExprName { ExprName {
range: 6..9, range: 6..9,
id: "bbb", id: Name("bbb"),
ctx: Load, ctx: Load,
}, },
), ),
@ -48,7 +48,7 @@ expression: parse_ast
expression: Name( expression: Name(
ExprName { ExprName {
range: 14..17, range: 14..17,
id: "ddd", id: Name("ddd"),
ctx: Load, ctx: Load,
}, },
), ),

View file

@ -1,6 +1,6 @@
--- ---
source: crates/ruff_python_parser/src/string.rs source: crates/ruff_python_parser/src/string.rs
expression: parse_ast expression: suite
--- ---
[ [
Expr( Expr(
@ -27,7 +27,7 @@ expression: parse_ast
expression: Name( expression: Name(
ExprName { ExprName {
range: 5..6, range: 5..6,
id: "x", id: Name("x"),
ctx: Load, ctx: Load,
}, },
), ),

Some files were not shown because too many files have changed in this diff Show more