mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-09 12:05:33 +00:00
Use super visibility in helpers (#4995)
This commit is contained in:
parent
1d756dc3a7
commit
c1ac50093c
12 changed files with 38 additions and 38 deletions
|
@ -8,7 +8,7 @@ static PASSWORD_CANDIDATE_REGEX: Lazy<Regex> = Lazy::new(|| {
|
||||||
Regex::new(r"(^|_)(?i)(pas+wo?r?d|pass(phrase)?|pwd|token|secrete?)($|_)").unwrap()
|
Regex::new(r"(^|_)(?i)(pas+wo?r?d|pass(phrase)?|pwd|token|secrete?)($|_)").unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
pub(crate) fn string_literal(expr: &Expr) -> Option<&str> {
|
pub(super) fn string_literal(expr: &Expr) -> Option<&str> {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Constant(ast::ExprConstant {
|
Expr::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(string),
|
value: Constant::Str(string),
|
||||||
|
@ -18,11 +18,11 @@ pub(crate) fn string_literal(expr: &Expr) -> Option<&str> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn matches_password_name(string: &str) -> bool {
|
pub(super) fn matches_password_name(string: &str) -> bool {
|
||||||
PASSWORD_CANDIDATE_REGEX.is_match(string)
|
PASSWORD_CANDIDATE_REGEX.is_match(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_untyped_exception(type_: Option<&Expr>, model: &SemanticModel) -> bool {
|
pub(super) fn is_untyped_exception(type_: Option<&Expr>, model: &SemanticModel) -> bool {
|
||||||
type_.map_or(true, |type_| {
|
type_.map_or(true, |type_| {
|
||||||
if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &type_ {
|
if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &type_ {
|
||||||
elts.iter().any(|type_| {
|
elts.iter().any(|type_| {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use rustpython_parser::ast::{self, Expr, Keyword};
|
use rustpython_parser::ast::{self, Expr, Keyword};
|
||||||
|
|
||||||
pub(crate) fn expr_name(func: &Expr) -> Option<&str> {
|
pub(super) fn expr_name(func: &Expr) -> Option<&str> {
|
||||||
if let Expr::Name(ast::ExprName { id, .. }) = func {
|
if let Expr::Name(ast::ExprName { id, .. }) = func {
|
||||||
Some(id)
|
Some(id)
|
||||||
} else {
|
} else {
|
||||||
|
@ -8,7 +8,7 @@ pub(crate) fn expr_name(func: &Expr) -> Option<&str> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn exactly_one_argument_with_matching_function<'a>(
|
pub(super) fn exactly_one_argument_with_matching_function<'a>(
|
||||||
name: &str,
|
name: &str,
|
||||||
func: &Expr,
|
func: &Expr,
|
||||||
args: &'a [Expr],
|
args: &'a [Expr],
|
||||||
|
@ -26,7 +26,7 @@ pub(crate) fn exactly_one_argument_with_matching_function<'a>(
|
||||||
Some(&args[0])
|
Some(&args[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn first_argument_with_matching_function<'a>(
|
pub(super) fn first_argument_with_matching_function<'a>(
|
||||||
name: &str,
|
name: &str,
|
||||||
func: &Expr,
|
func: &Expr,
|
||||||
args: &'a [Expr],
|
args: &'a [Expr],
|
||||||
|
|
|
@ -3,14 +3,14 @@ use rustpython_parser::ast::Expr;
|
||||||
use ruff_python_semantic::model::SemanticModel;
|
use ruff_python_semantic::model::SemanticModel;
|
||||||
|
|
||||||
/// Return `true` if a Python class appears to be a Django model, based on its base classes.
|
/// Return `true` if a Python class appears to be a Django model, based on its base classes.
|
||||||
pub(crate) fn is_model(model: &SemanticModel, base: &Expr) -> bool {
|
pub(super) fn is_model(model: &SemanticModel, base: &Expr) -> bool {
|
||||||
model.resolve_call_path(base).map_or(false, |call_path| {
|
model.resolve_call_path(base).map_or(false, |call_path| {
|
||||||
call_path.as_slice() == ["django", "db", "models", "Model"]
|
call_path.as_slice() == ["django", "db", "models", "Model"]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` if a Python class appears to be a Django model form, based on its base classes.
|
/// Return `true` if a Python class appears to be a Django model form, based on its base classes.
|
||||||
pub(crate) fn is_model_form(model: &SemanticModel, base: &Expr) -> bool {
|
pub(super) fn is_model_form(model: &SemanticModel, base: &Expr) -> bool {
|
||||||
model.resolve_call_path(base).map_or(false, |call_path| {
|
model.resolve_call_path(base).map_or(false, |call_path| {
|
||||||
call_path.as_slice() == ["django", "forms", "ModelForm"]
|
call_path.as_slice() == ["django", "forms", "ModelForm"]
|
||||||
|| call_path.as_slice() == ["django", "forms", "models", "ModelForm"]
|
|| call_path.as_slice() == ["django", "forms", "models", "ModelForm"]
|
||||||
|
@ -18,7 +18,7 @@ pub(crate) fn is_model_form(model: &SemanticModel, base: &Expr) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` if the expression is constructor for a Django model field.
|
/// Return `true` if the expression is constructor for a Django model field.
|
||||||
pub(crate) fn is_model_field(model: &SemanticModel, expr: &Expr) -> bool {
|
pub(super) fn is_model_field(model: &SemanticModel, expr: &Expr) -> bool {
|
||||||
model.resolve_call_path(expr).map_or(false, |call_path| {
|
model.resolve_call_path(expr).map_or(false, |call_path| {
|
||||||
call_path
|
call_path
|
||||||
.as_slice()
|
.as_slice()
|
||||||
|
@ -27,7 +27,7 @@ pub(crate) fn is_model_field(model: &SemanticModel, expr: &Expr) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the name of the field type, if the expression is constructor for a Django model field.
|
/// Return the name of the field type, if the expression is constructor for a Django model field.
|
||||||
pub(crate) fn get_model_field_name<'a>(
|
pub(super) fn get_model_field_name<'a>(
|
||||||
model: &'a SemanticModel,
|
model: &'a SemanticModel,
|
||||||
expr: &'a Expr,
|
expr: &'a Expr,
|
||||||
) -> Option<&'a str> {
|
) -> Option<&'a str> {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use ruff_python_whitespace::UniversalNewlines;
|
||||||
|
|
||||||
/// Return `true` if a function's return statement include at least one
|
/// Return `true` if a function's return statement include at least one
|
||||||
/// non-`None` value.
|
/// non-`None` value.
|
||||||
pub(crate) fn result_exists(returns: &[(&Stmt, Option<&Expr>)]) -> bool {
|
pub(super) fn result_exists(returns: &[(&Stmt, Option<&Expr>)]) -> bool {
|
||||||
returns.iter().any(|(_, expr)| {
|
returns.iter().any(|(_, expr)| {
|
||||||
expr.map(|expr| {
|
expr.map(|expr| {
|
||||||
!matches!(
|
!matches!(
|
||||||
|
@ -25,7 +25,7 @@ pub(crate) fn result_exists(returns: &[(&Stmt, Option<&Expr>)]) -> bool {
|
||||||
///
|
///
|
||||||
/// This method assumes that the statement is the last statement in its body; specifically, that
|
/// This method assumes that the statement is the last statement in its body; specifically, that
|
||||||
/// the statement isn't followed by a semicolon, followed by a multi-line statement.
|
/// the statement isn't followed by a semicolon, followed by a multi-line statement.
|
||||||
pub(crate) fn end_of_last_statement(stmt: &Stmt, locator: &Locator) -> TextSize {
|
pub(super) fn end_of_last_statement(stmt: &Stmt, locator: &Locator) -> TextSize {
|
||||||
// End-of-file, so just return the end of the statement.
|
// End-of-file, so just return the end of the statement.
|
||||||
if stmt.end() == locator.text_len() {
|
if stmt.end() == locator.text_len() {
|
||||||
stmt.end()
|
stmt.end()
|
||||||
|
|
|
@ -13,7 +13,7 @@ fn to_formatted_value_expr(inner: &Expr) -> Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a string to a constant string expression.
|
/// Convert a string to a constant string expression.
|
||||||
pub(crate) fn to_constant_string(s: &str) -> Expr {
|
pub(super) fn to_constant_string(s: &str) -> Expr {
|
||||||
let node = ast::ExprConstant {
|
let node = ast::ExprConstant {
|
||||||
value: Constant::Str(s.to_owned()),
|
value: Constant::Str(s.to_owned()),
|
||||||
kind: None,
|
kind: None,
|
||||||
|
@ -47,7 +47,7 @@ fn is_simple_callee(func: &Expr) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert an expression to a f-string element (if it looks like a good idea).
|
/// Convert an expression to a f-string element (if it looks like a good idea).
|
||||||
pub(crate) fn to_fstring_elem(expr: &Expr) -> Option<Expr> {
|
pub(super) fn to_fstring_elem(expr: &Expr) -> Option<Expr> {
|
||||||
match expr {
|
match expr {
|
||||||
// These are directly handled by `unparse_fstring_elem`:
|
// These are directly handled by `unparse_fstring_elem`:
|
||||||
Expr::Constant(ast::ExprConstant {
|
Expr::Constant(ast::ExprConstant {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::rules::isort::types::TrailingComma;
|
||||||
|
|
||||||
/// Return `true` if a `Stmt::ImportFrom` statement ends with a magic
|
/// Return `true` if a `Stmt::ImportFrom` statement ends with a magic
|
||||||
/// trailing comma.
|
/// trailing comma.
|
||||||
pub(crate) fn trailing_comma(stmt: &Stmt, locator: &Locator) -> TrailingComma {
|
pub(super) fn trailing_comma(stmt: &Stmt, locator: &Locator) -> TrailingComma {
|
||||||
let contents = locator.slice(stmt.range());
|
let contents = locator.slice(stmt.range());
|
||||||
let mut count = 0u32;
|
let mut count = 0u32;
|
||||||
let mut trailing_comma = TrailingComma::Absent;
|
let mut trailing_comma = TrailingComma::Absent;
|
||||||
|
@ -36,7 +36,7 @@ pub(crate) fn trailing_comma(stmt: &Stmt, locator: &Locator) -> TrailingComma {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` if a [`Stmt`] is preceded by a "comment break"
|
/// Return `true` if a [`Stmt`] is preceded by a "comment break"
|
||||||
pub(crate) fn has_comment_break(stmt: &Stmt, locator: &Locator) -> bool {
|
pub(super) fn has_comment_break(stmt: &Stmt, locator: &Locator) -> bool {
|
||||||
// Starting from the `Stmt` (`def f(): pass`), we want to detect patterns like
|
// Starting from the `Stmt` (`def f(): pass`), we want to detect patterns like
|
||||||
// this:
|
// this:
|
||||||
//
|
//
|
||||||
|
|
|
@ -4,7 +4,7 @@ use rustpython_parser::ast::Expr;
|
||||||
use ruff_python_semantic::binding::{BindingKind, Importation};
|
use ruff_python_semantic::binding::{BindingKind, Importation};
|
||||||
use ruff_python_semantic::model::SemanticModel;
|
use ruff_python_semantic::model::SemanticModel;
|
||||||
|
|
||||||
pub(crate) enum Resolution {
|
pub(super) enum Resolution {
|
||||||
/// The expression resolves to an irrelevant expression type (e.g., a constant).
|
/// The expression resolves to an irrelevant expression type (e.g., a constant).
|
||||||
IrrelevantExpression,
|
IrrelevantExpression,
|
||||||
/// The expression resolves to an irrelevant binding (e.g., a function definition).
|
/// The expression resolves to an irrelevant binding (e.g., a function definition).
|
||||||
|
@ -16,7 +16,7 @@ pub(crate) enum Resolution {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test an [`Expr`] for relevance to Pandas-related operations.
|
/// Test an [`Expr`] for relevance to Pandas-related operations.
|
||||||
pub(crate) fn test_expression(expr: &Expr, model: &SemanticModel) -> Resolution {
|
pub(super) fn test_expression(expr: &Expr, model: &SemanticModel) -> Resolution {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Constant(_)
|
Expr::Constant(_)
|
||||||
| Expr::Tuple(_)
|
| Expr::Tuple(_)
|
||||||
|
|
|
@ -4,11 +4,11 @@ use rustpython_parser::ast::{self, Expr, Stmt};
|
||||||
use ruff_python_semantic::model::SemanticModel;
|
use ruff_python_semantic::model::SemanticModel;
|
||||||
use ruff_python_stdlib::str::{is_lower, is_upper};
|
use ruff_python_stdlib::str::{is_lower, is_upper};
|
||||||
|
|
||||||
pub(crate) fn is_camelcase(name: &str) -> bool {
|
pub(super) fn is_camelcase(name: &str) -> bool {
|
||||||
!is_lower(name) && !is_upper(name) && !name.contains('_')
|
!is_lower(name) && !is_upper(name) && !name.contains('_')
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_mixed_case(name: &str) -> bool {
|
pub(super) fn is_mixed_case(name: &str) -> bool {
|
||||||
!is_lower(name)
|
!is_lower(name)
|
||||||
&& name
|
&& name
|
||||||
.strip_prefix('_')
|
.strip_prefix('_')
|
||||||
|
@ -18,11 +18,11 @@ pub(crate) fn is_mixed_case(name: &str) -> bool {
|
||||||
.map_or_else(|| false, char::is_lowercase)
|
.map_or_else(|| false, char::is_lowercase)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_acronym(name: &str, asname: &str) -> bool {
|
pub(super) fn is_acronym(name: &str, asname: &str) -> bool {
|
||||||
name.chars().filter(|c| c.is_uppercase()).join("") == asname
|
name.chars().filter(|c| c.is_uppercase()).join("") == asname
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_named_tuple_assignment(model: &SemanticModel, stmt: &Stmt) -> bool {
|
pub(super) fn is_named_tuple_assignment(model: &SemanticModel, stmt: &Stmt) -> bool {
|
||||||
let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else {
|
let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -37,7 +37,7 @@ pub(crate) fn is_named_tuple_assignment(model: &SemanticModel, stmt: &Stmt) -> b
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_typed_dict_assignment(model: &SemanticModel, stmt: &Stmt) -> bool {
|
pub(super) fn is_typed_dict_assignment(model: &SemanticModel, stmt: &Stmt) -> bool {
|
||||||
let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else {
|
let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -49,7 +49,7 @@ pub(crate) fn is_typed_dict_assignment(model: &SemanticModel, stmt: &Stmt) -> bo
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_type_var_assignment(model: &SemanticModel, stmt: &Stmt) -> bool {
|
pub(super) fn is_type_var_assignment(model: &SemanticModel, stmt: &Stmt) -> bool {
|
||||||
let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else {
|
let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -62,7 +62,7 @@ pub(crate) fn is_type_var_assignment(model: &SemanticModel, stmt: &Stmt) -> bool
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_typed_dict_class(model: &SemanticModel, bases: &[Expr]) -> bool {
|
pub(super) fn is_typed_dict_class(model: &SemanticModel, bases: &[Expr]) -> bool {
|
||||||
bases
|
bases
|
||||||
.iter()
|
.iter()
|
||||||
.any(|base| model.match_typing_expr(base, "TypedDict"))
|
.any(|base| model.match_typing_expr(base, "TypedDict"))
|
||||||
|
|
|
@ -9,7 +9,7 @@ use ruff_python_semantic::model::SemanticModel;
|
||||||
use ruff_python_whitespace::UniversalNewlines;
|
use ruff_python_whitespace::UniversalNewlines;
|
||||||
|
|
||||||
/// Return the index of the first logical line in a string.
|
/// Return the index of the first logical line in a string.
|
||||||
pub(crate) fn logical_line(content: &str) -> Option<usize> {
|
pub(super) fn logical_line(content: &str) -> Option<usize> {
|
||||||
// Find the first logical line.
|
// Find the first logical line.
|
||||||
let mut logical_line = None;
|
let mut logical_line = None;
|
||||||
for (i, line) in content.universal_newlines().enumerate() {
|
for (i, line) in content.universal_newlines().enumerate() {
|
||||||
|
@ -28,12 +28,17 @@ pub(crate) fn logical_line(content: &str) -> Option<usize> {
|
||||||
|
|
||||||
/// Normalize a word by removing all non-alphanumeric characters
|
/// Normalize a word by removing all non-alphanumeric characters
|
||||||
/// and converting it to lowercase.
|
/// and converting it to lowercase.
|
||||||
pub(crate) fn normalize_word(first_word: &str) -> String {
|
pub(super) fn normalize_word(first_word: &str) -> String {
|
||||||
first_word
|
first_word
|
||||||
.replace(|c: char| !c.is_alphanumeric(), "")
|
.replace(|c: char| !c.is_alphanumeric(), "")
|
||||||
.to_lowercase()
|
.to_lowercase()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return true if a line ends with an odd number of backslashes (i.e., ends with an escape).
|
||||||
|
pub(super) fn ends_with_backslash(line: &str) -> bool {
|
||||||
|
line.chars().rev().take_while(|c| *c == '\\').count() % 2 == 1
|
||||||
|
}
|
||||||
|
|
||||||
/// Check decorator list to see if function should be ignored.
|
/// Check decorator list to see if function should be ignored.
|
||||||
pub(crate) fn should_ignore_definition(
|
pub(crate) fn should_ignore_definition(
|
||||||
model: &SemanticModel,
|
model: &SemanticModel,
|
||||||
|
@ -64,11 +69,6 @@ pub(crate) fn should_ignore_definition(
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if a line ends with an odd number of backslashes (i.e., ends with an escape).
|
|
||||||
pub(crate) fn ends_with_backslash(line: &str) -> bool {
|
|
||||||
line.chars().rev().take_while(|c| *c == '\\').count() % 2 == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Check if a docstring should be ignored.
|
/// Check if a docstring should be ignored.
|
||||||
pub(crate) fn should_ignore_docstring(contents: &str) -> bool {
|
pub(crate) fn should_ignore_docstring(contents: &str) -> bool {
|
||||||
// Avoid analyzing docstrings that contain implicit string concatenations.
|
// Avoid analyzing docstrings that contain implicit string concatenations.
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::fmt;
|
||||||
|
|
||||||
use crate::settings::Settings;
|
use crate::settings::Settings;
|
||||||
|
|
||||||
pub(crate) fn in_dunder_init(model: &SemanticModel, settings: &Settings) -> bool {
|
pub(super) fn in_dunder_init(model: &SemanticModel, settings: &Settings) -> bool {
|
||||||
let scope = model.scope();
|
let scope = model.scope();
|
||||||
let (
|
let (
|
||||||
ScopeKind::Function(ast::StmtFunctionDef {
|
ScopeKind::Function(ast::StmtFunctionDef {
|
||||||
|
@ -49,7 +49,7 @@ pub(crate) fn in_dunder_init(model: &SemanticModel, settings: &Settings) -> bool
|
||||||
|
|
||||||
/// A wrapper around [`Cmpop`] that implements `Display`.
|
/// A wrapper around [`Cmpop`] that implements `Display`.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct CmpopExt(Cmpop);
|
pub(super) struct CmpopExt(Cmpop);
|
||||||
|
|
||||||
impl From<&Cmpop> for CmpopExt {
|
impl From<&Cmpop> for CmpopExt {
|
||||||
fn from(cmpop: &Cmpop) -> Self {
|
fn from(cmpop: &Cmpop) -> Self {
|
||||||
|
|
|
@ -3,7 +3,7 @@ use regex::{Captures, Regex};
|
||||||
|
|
||||||
static CURLY_BRACES: Lazy<Regex> = Lazy::new(|| Regex::new(r"(\\N\{[^}]+})|([{}])").unwrap());
|
static CURLY_BRACES: Lazy<Regex> = Lazy::new(|| Regex::new(r"(\\N\{[^}]+})|([{}])").unwrap());
|
||||||
|
|
||||||
pub(crate) fn curly_escape(text: &str) -> String {
|
pub(super) fn curly_escape(text: &str) -> String {
|
||||||
// Match all curly braces. This will include named unicode escapes (like
|
// Match all curly braces. This will include named unicode escapes (like
|
||||||
// \N{SNOWMAN}), which we _don't_ want to escape, so take care to preserve them.
|
// \N{SNOWMAN}), which we _don't_ want to escape, so take care to preserve them.
|
||||||
CURLY_BRACES
|
CURLY_BRACES
|
||||||
|
|
|
@ -6,13 +6,13 @@ use ruff_python_semantic::analyze::logging;
|
||||||
use ruff_python_semantic::model::SemanticModel;
|
use ruff_python_semantic::model::SemanticModel;
|
||||||
|
|
||||||
/// Collect `logging`-like calls from an AST.
|
/// Collect `logging`-like calls from an AST.
|
||||||
pub(crate) struct LoggerCandidateVisitor<'a, 'b> {
|
pub(super) struct LoggerCandidateVisitor<'a, 'b> {
|
||||||
semantic_model: &'a SemanticModel<'b>,
|
semantic_model: &'a SemanticModel<'b>,
|
||||||
pub(crate) calls: Vec<&'b ast::ExprCall>,
|
pub(super) calls: Vec<&'b ast::ExprCall>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> LoggerCandidateVisitor<'a, 'b> {
|
impl<'a, 'b> LoggerCandidateVisitor<'a, 'b> {
|
||||||
pub(crate) fn new(semantic_model: &'a SemanticModel<'b>) -> Self {
|
pub(super) fn new(semantic_model: &'a SemanticModel<'b>) -> Self {
|
||||||
LoggerCandidateVisitor {
|
LoggerCandidateVisitor {
|
||||||
semantic_model,
|
semantic_model,
|
||||||
calls: Vec::new(),
|
calls: Vec::new(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue