mirror of https://github.com/astral-sh/ruff
Merge remote-tracking branch 'origin/main' into dcreager/callable-return
* origin/main: (36 commits) [ty] Defer all parameter and return type annotations (#21906) [ty] Fix workspace symbols to return members too (#21926) Document range suppressions, reorganize suppression docs (#21884) Ignore ruff:isort like ruff:noqa in new suppressions (#21922) [ty] Handle `Definition`s in `SemanticModel::scope` (#21919) [ty] Attach salsa db when running ide tests for easier debugging (#21917) [ty] Don't show hover for expressions with no inferred type (#21924) [ty] avoid unions of generic aliases of the same class in fixpoint (#21909) [ty] Squash false positive logs for failing to find `builtins` as a real module [ty] Uniformly use "not supported" in diagnostics (#21916) [ty] Reduce size of ty-ide snapshots (#21915) [ty] Adjust scope completions to use all reachable symbols [ty] Rename `all_members_of_scope` to `all_end_of_scope_members` [ty] Remove `all_` prefix from some routines on UseDefMap Enable `--document-private-items` for `ruff_python_formatter` (#21903) Remove `BackwardsTokenizer` based `parenthesized_range` references in `ruff_linter` (#21836) [ty] Revert "Do not infer types for invalid binary expressions in annotations" (#21914) Skip over trivia tokens after re-lexing (#21895) [ty] Avoid inferring types for invalid binary expressions in string annotations (#21911) [ty] Improve overload call resolution tracing (#21913) ...
This commit is contained in:
commit
a892be3124
|
|
@ -298,7 +298,7 @@ jobs:
|
|||
# sync, not just public items. Eventually we should do this for all
|
||||
# crates; for now add crates here as they are warning-clean to prevent
|
||||
# regression.
|
||||
- run: cargo doc --no-deps -p ty_python_semantic -p ty -p ty_test -p ruff_db --document-private-items
|
||||
- run: cargo doc --no-deps -p ty_python_semantic -p ty -p ty_test -p ruff_db -p ruff_python_formatter --document-private-items
|
||||
env:
|
||||
# Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025).
|
||||
RUSTDOCFLAGS: "-D warnings"
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ jobs:
|
|||
|
||||
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
|
||||
with:
|
||||
shared-key: "mypy-primer"
|
||||
workspaces: "ruff"
|
||||
|
||||
- name: Install Rust toolchain
|
||||
|
|
@ -86,6 +87,7 @@ jobs:
|
|||
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
|
||||
with:
|
||||
workspaces: "ruff"
|
||||
shared-key: "mypy-primer"
|
||||
|
||||
- name: Install Rust toolchain
|
||||
run: rustup show
|
||||
|
|
@ -105,3 +107,54 @@ jobs:
|
|||
with:
|
||||
name: mypy_primer_memory_diff
|
||||
path: mypy_primer_memory.diff
|
||||
|
||||
# Runs mypy twice against the same ty version to catch any non-deterministic behavior (ideally).
|
||||
# The job is disabled for now because there are some non-deterministic diagnostics.
|
||||
mypy_primer_same_revision:
|
||||
name: Run mypy_primer on same revision
|
||||
runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-32' || 'ubuntu-latest' }}
|
||||
timeout-minutes: 20
|
||||
# TODO: Enable once we fixed the non-deterministic diagnostics
|
||||
if: false
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
path: ruff
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@1e862dfacbd1d6d858c55d9b792c756523627244 # v7.1.4
|
||||
|
||||
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
|
||||
with:
|
||||
workspaces: "ruff"
|
||||
shared-key: "mypy-primer"
|
||||
|
||||
- name: Install Rust toolchain
|
||||
run: rustup show
|
||||
|
||||
- name: Run determinism check
|
||||
env:
|
||||
BASE_REVISION: ${{ github.event.pull_request.head.sha }}
|
||||
PRIMER_SELECTOR: crates/ty_python_semantic/resources/primer/good.txt
|
||||
CLICOLOR_FORCE: "1"
|
||||
DIFF_FILE: mypy_primer_determinism.diff
|
||||
run: |
|
||||
cd ruff
|
||||
scripts/mypy_primer.sh
|
||||
|
||||
- name: Check for non-determinism
|
||||
run: |
|
||||
# Remove ANSI color codes for checking
|
||||
sed -e 's/\x1b\[[0-9;]*m//g' mypy_primer_determinism.diff > mypy_primer_determinism_clean.diff
|
||||
|
||||
# Check if there are any differences (non-determinism)
|
||||
if [ -s mypy_primer_determinism_clean.diff ]; then
|
||||
echo "ERROR: Non-deterministic output detected!"
|
||||
echo "The following differences were found when running ty twice on the same commit:"
|
||||
cat mypy_primer_determinism_clean.diff
|
||||
exit 1
|
||||
else
|
||||
echo "✓ Output is deterministic"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1016,7 +1016,7 @@ dependencies = [
|
|||
"libc",
|
||||
"option-ext",
|
||||
"redox_users",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1108,7 +1108,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1238,9 +1238,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "get-size-derive2"
|
||||
version = "0.7.2"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff47daa61505c85af126e9dd64af6a342a33dc0cccfe1be74ceadc7d352e6efd"
|
||||
checksum = "ab21d7bd2c625f2064f04ce54bcb88bc57c45724cde45cba326d784e22d3f71a"
|
||||
dependencies = [
|
||||
"attribute-derive",
|
||||
"quote",
|
||||
|
|
@ -1249,14 +1249,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "get-size2"
|
||||
version = "0.7.2"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac7bb8710e1f09672102be7ddf39f764d8440ae74a9f4e30aaa4820dcdffa4af"
|
||||
checksum = "879272b0de109e2b67b39fcfe3d25fdbba96ac07e44a254f5a0b4d7ff55340cb"
|
||||
dependencies = [
|
||||
"compact_str",
|
||||
"get-size-derive2",
|
||||
"hashbrown 0.16.1",
|
||||
"indexmap",
|
||||
"ordermap",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
|
|
@ -1763,7 +1764,7 @@ dependencies = [
|
|||
"portable-atomic",
|
||||
"portable-atomic-util",
|
||||
"serde_core",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2233,9 +2234,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
|||
|
||||
[[package]]
|
||||
name = "ordermap"
|
||||
version = "0.5.12"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b100f7dd605611822d30e182214d3c02fdefce2d801d23993f6b6ba6ca1392af"
|
||||
checksum = "ed637741ced8fb240855d22a2b4f208dab7a06bcce73380162e5253000c16758"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
|
|
@ -3348,6 +3349,7 @@ dependencies = [
|
|||
"compact_str",
|
||||
"get-size2",
|
||||
"insta",
|
||||
"itertools 0.14.0",
|
||||
"memchr",
|
||||
"ruff_annotate_snippets",
|
||||
"ruff_python_ast",
|
||||
|
|
@ -3571,7 +3573,7 @@ dependencies = [
|
|||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3589,7 +3591,7 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
|||
[[package]]
|
||||
name = "salsa"
|
||||
version = "0.24.0"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=59aa1075e837f5deb0d6ffb24b68fedc0f4bc5e0#59aa1075e837f5deb0d6ffb24b68fedc0f4bc5e0"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=55e5e7d32fa3fc189276f35bb04c9438f9aedbd1#55e5e7d32fa3fc189276f35bb04c9438f9aedbd1"
|
||||
dependencies = [
|
||||
"boxcar",
|
||||
"compact_str",
|
||||
|
|
@ -3600,6 +3602,7 @@ dependencies = [
|
|||
"indexmap",
|
||||
"intrusive-collections",
|
||||
"inventory",
|
||||
"ordermap",
|
||||
"parking_lot",
|
||||
"portable-atomic",
|
||||
"rustc-hash",
|
||||
|
|
@ -3613,12 +3616,12 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "salsa-macro-rules"
|
||||
version = "0.24.0"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=59aa1075e837f5deb0d6ffb24b68fedc0f4bc5e0#59aa1075e837f5deb0d6ffb24b68fedc0f4bc5e0"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=55e5e7d32fa3fc189276f35bb04c9438f9aedbd1#55e5e7d32fa3fc189276f35bb04c9438f9aedbd1"
|
||||
|
||||
[[package]]
|
||||
name = "salsa-macros"
|
||||
version = "0.24.0"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=59aa1075e837f5deb0d6ffb24b68fedc0f4bc5e0#59aa1075e837f5deb0d6ffb24b68fedc0f4bc5e0"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=55e5e7d32fa3fc189276f35bb04c9438f9aedbd1#55e5e7d32fa3fc189276f35bb04c9438f9aedbd1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -3972,7 +3975,7 @@ dependencies = [
|
|||
"getrandom 0.3.4",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5026,7 +5029,7 @@ version = "0.1.11"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ etcetera = { version = "0.11.0" }
|
|||
fern = { version = "0.7.0" }
|
||||
filetime = { version = "0.2.23" }
|
||||
getrandom = { version = "0.3.1" }
|
||||
get-size2 = { version = "0.7.0", features = [
|
||||
get-size2 = { version = "0.7.3", features = [
|
||||
"derive",
|
||||
"smallvec",
|
||||
"hashbrown",
|
||||
|
|
@ -129,7 +129,7 @@ memchr = { version = "2.7.1" }
|
|||
mimalloc = { version = "0.1.39" }
|
||||
natord = { version = "1.0.9" }
|
||||
notify = { version = "8.0.0" }
|
||||
ordermap = { version = "0.5.0" }
|
||||
ordermap = { version = "1.0.0" }
|
||||
path-absolutize = { version = "3.1.1" }
|
||||
path-slash = { version = "0.2.1" }
|
||||
pathdiff = { version = "0.2.1" }
|
||||
|
|
@ -146,7 +146,7 @@ regex-automata = { version = "0.4.9" }
|
|||
rustc-hash = { version = "2.0.0" }
|
||||
rustc-stable-hash = { version = "0.1.2" }
|
||||
# When updating salsa, make sure to also update the revision in `fuzz/Cargo.toml`
|
||||
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "59aa1075e837f5deb0d6ffb24b68fedc0f4bc5e0", default-features = false, features = [
|
||||
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "55e5e7d32fa3fc189276f35bb04c9438f9aedbd1", default-features = false, features = [
|
||||
"compact_str",
|
||||
"macros",
|
||||
"salsa_unstable",
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ static SYMPY: Benchmark = Benchmark::new(
|
|||
max_dep_date: "2025-06-17",
|
||||
python_version: PythonVersion::PY312,
|
||||
},
|
||||
13000,
|
||||
13030,
|
||||
);
|
||||
|
||||
static TANJUN: Benchmark = Benchmark::new(
|
||||
|
|
|
|||
|
|
@ -437,6 +437,15 @@ impl<'a> Checker<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the [`Tokens`] for the parsed source file.
|
||||
///
|
||||
///
|
||||
/// Unlike [`Self::tokens`], this method always returns
|
||||
/// the tokens for the current file, even when within a parsed type annotation.
|
||||
pub(crate) fn source_tokens(&self) -> &'a Tokens {
|
||||
self.parsed.tokens()
|
||||
}
|
||||
|
||||
/// The [`Locator`] for the current file, which enables extraction of source code from byte
|
||||
/// offsets.
|
||||
pub(crate) const fn locator(&self) -> &'a Locator<'a> {
|
||||
|
|
|
|||
|
|
@ -3,14 +3,13 @@
|
|||
use anyhow::{Context, Result};
|
||||
|
||||
use ruff_python_ast::AnyNodeRef;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::{self, Tokens, parenthesized_range};
|
||||
use ruff_python_ast::{self as ast, Arguments, ExceptHandler, Expr, ExprList, Parameters, Stmt};
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_python_trivia::textwrap::dedent_to;
|
||||
use ruff_python_trivia::{
|
||||
CommentRanges, PythonWhitespace, SimpleTokenKind, SimpleTokenizer, has_leading_content,
|
||||
is_python_whitespace,
|
||||
PythonWhitespace, SimpleTokenKind, SimpleTokenizer, has_leading_content, is_python_whitespace,
|
||||
};
|
||||
use ruff_source_file::{LineRanges, NewlineWithTrailingNewline, UniversalNewlines};
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
|
@ -209,7 +208,7 @@ pub(crate) fn remove_argument<T: Ranged>(
|
|||
arguments: &Arguments,
|
||||
parentheses: Parentheses,
|
||||
source: &str,
|
||||
comment_ranges: &CommentRanges,
|
||||
tokens: &Tokens,
|
||||
) -> Result<Edit> {
|
||||
// Partition into arguments before and after the argument to remove.
|
||||
let (before, after): (Vec<_>, Vec<_>) = arguments
|
||||
|
|
@ -224,7 +223,7 @@ pub(crate) fn remove_argument<T: Ranged>(
|
|||
.context("Unable to find argument")?;
|
||||
|
||||
let parenthesized_range =
|
||||
parenthesized_range(arg.value().into(), arguments.into(), comment_ranges, source)
|
||||
token::parenthesized_range(arg.value().into(), arguments.into(), tokens)
|
||||
.unwrap_or(arg.range());
|
||||
|
||||
if !after.is_empty() {
|
||||
|
|
@ -270,25 +269,14 @@ pub(crate) fn remove_argument<T: Ranged>(
|
|||
///
|
||||
/// The new argument will be inserted before the first existing keyword argument in `arguments`, if
|
||||
/// there are any present. Otherwise, the new argument is added to the end of the argument list.
|
||||
pub(crate) fn add_argument(
|
||||
argument: &str,
|
||||
arguments: &Arguments,
|
||||
comment_ranges: &CommentRanges,
|
||||
source: &str,
|
||||
) -> Edit {
|
||||
pub(crate) fn add_argument(argument: &str, arguments: &Arguments, tokens: &Tokens) -> Edit {
|
||||
if let Some(ast::Keyword { range, value, .. }) = arguments.keywords.first() {
|
||||
let keyword = parenthesized_range(value.into(), arguments.into(), comment_ranges, source)
|
||||
.unwrap_or(*range);
|
||||
let keyword = parenthesized_range(value.into(), arguments.into(), tokens).unwrap_or(*range);
|
||||
Edit::insertion(format!("{argument}, "), keyword.start())
|
||||
} else if let Some(last) = arguments.arguments_source_order().last() {
|
||||
// Case 1: existing arguments, so append after the last argument.
|
||||
let last = parenthesized_range(
|
||||
last.value().into(),
|
||||
arguments.into(),
|
||||
comment_ranges,
|
||||
source,
|
||||
)
|
||||
.unwrap_or(last.range());
|
||||
let last = parenthesized_range(last.value().into(), arguments.into(), tokens)
|
||||
.unwrap_or(last.range());
|
||||
Edit::insertion(format!(", {argument}"), last.end())
|
||||
} else {
|
||||
// Case 2: no arguments. Add argument, without any trailing comma.
|
||||
|
|
|
|||
|
|
@ -91,8 +91,8 @@ pub(crate) fn fastapi_redundant_response_model(checker: &Checker, function_def:
|
|||
response_model_arg,
|
||||
&call.arguments,
|
||||
Parentheses::Preserve,
|
||||
checker.locator().contents(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.map(Fix::unsafe_edit)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -74,12 +74,7 @@ pub(crate) fn map_without_explicit_strict(checker: &Checker, call: &ast::ExprCal
|
|||
checker
|
||||
.report_diagnostic(MapWithoutExplicitStrict, call.range())
|
||||
.set_fix(Fix::applicable_edit(
|
||||
add_argument(
|
||||
"strict=False",
|
||||
&call.arguments,
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
),
|
||||
add_argument("strict=False", &call.arguments, checker.tokens()),
|
||||
Applicability::Unsafe,
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::fmt::Write;
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::helpers::is_docstring_stmt;
|
||||
use ruff_python_ast::name::QualifiedName;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{self as ast, Expr, ParameterWithDefault};
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
use ruff_python_semantic::analyze::function_type::is_stub;
|
||||
|
|
@ -166,12 +166,7 @@ fn move_initialization(
|
|||
return None;
|
||||
}
|
||||
|
||||
let range = match parenthesized_range(
|
||||
default.into(),
|
||||
parameter.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
) {
|
||||
let range = match parenthesized_range(default.into(), parameter.into(), checker.tokens()) {
|
||||
Some(range) => range,
|
||||
None => default.range(),
|
||||
};
|
||||
|
|
@ -194,13 +189,8 @@ fn move_initialization(
|
|||
"{} = {}",
|
||||
parameter.parameter.name(),
|
||||
locator.slice(
|
||||
parenthesized_range(
|
||||
default.into(),
|
||||
parameter.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source()
|
||||
)
|
||||
.unwrap_or(default.range())
|
||||
parenthesized_range(default.into(), parameter.into(), checker.tokens())
|
||||
.unwrap_or(default.range())
|
||||
)
|
||||
);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -92,12 +92,7 @@ pub(crate) fn no_explicit_stacklevel(checker: &Checker, call: &ast::ExprCall) {
|
|||
}
|
||||
let mut diagnostic = checker.report_diagnostic(NoExplicitStacklevel, call.func.range());
|
||||
|
||||
let edit = add_argument(
|
||||
"stacklevel=2",
|
||||
&call.arguments,
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
);
|
||||
let edit = add_argument("stacklevel=2", &call.arguments, checker.tokens());
|
||||
|
||||
diagnostic.set_fix(Fix::unsafe_edit(edit));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,12 +70,7 @@ pub(crate) fn zip_without_explicit_strict(checker: &Checker, call: &ast::ExprCal
|
|||
checker
|
||||
.report_diagnostic(ZipWithoutExplicitStrict, call.range())
|
||||
.set_fix(Fix::applicable_edit(
|
||||
add_argument(
|
||||
"strict=False",
|
||||
&call.arguments,
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
),
|
||||
add_argument("strict=False", &call.arguments, checker.tokens()),
|
||||
Applicability::Unsafe,
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ use ruff_macros::{ViolationMetadata, derive_message_formats};
|
|||
use ruff_python_ast as ast;
|
||||
use ruff_python_ast::ExprGenerator;
|
||||
use ruff_python_ast::comparable::ComparableExpr;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::TokenKind;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
|
@ -142,13 +142,9 @@ pub(crate) fn unnecessary_generator_list(checker: &Checker, call: &ast::ExprCall
|
|||
if *parenthesized {
|
||||
// The generator's range will include the innermost parentheses, but it could be
|
||||
// surrounded by additional parentheses.
|
||||
let range = parenthesized_range(
|
||||
argument.into(),
|
||||
(&call.arguments).into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
)
|
||||
.unwrap_or(argument.range());
|
||||
let range =
|
||||
parenthesized_range(argument.into(), (&call.arguments).into(), checker.tokens())
|
||||
.unwrap_or(argument.range());
|
||||
|
||||
// The generator always parenthesizes the expression; trim the parentheses.
|
||||
let generator = checker.generator().expr(argument);
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ use ruff_macros::{ViolationMetadata, derive_message_formats};
|
|||
use ruff_python_ast as ast;
|
||||
use ruff_python_ast::ExprGenerator;
|
||||
use ruff_python_ast::comparable::ComparableExpr;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::TokenKind;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
|
@ -147,13 +147,9 @@ pub(crate) fn unnecessary_generator_set(checker: &Checker, call: &ast::ExprCall)
|
|||
if *parenthesized {
|
||||
// The generator's range will include the innermost parentheses, but it could be
|
||||
// surrounded by additional parentheses.
|
||||
let range = parenthesized_range(
|
||||
argument.into(),
|
||||
(&call.arguments).into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
)
|
||||
.unwrap_or(argument.range());
|
||||
let range =
|
||||
parenthesized_range(argument.into(), (&call.arguments).into(), checker.tokens())
|
||||
.unwrap_or(argument.range());
|
||||
|
||||
// The generator always parenthesizes the expression; trim the parentheses.
|
||||
let generator = checker.generator().expr(argument);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast as ast;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::TokenKind;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
|
@ -89,13 +89,9 @@ pub(crate) fn unnecessary_list_comprehension_set(checker: &Checker, call: &ast::
|
|||
|
||||
// If the list comprehension is parenthesized, remove the parentheses in addition to
|
||||
// removing the brackets.
|
||||
let replacement_range = parenthesized_range(
|
||||
argument.into(),
|
||||
(&call.arguments).into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
)
|
||||
.unwrap_or_else(|| argument.range());
|
||||
let replacement_range =
|
||||
parenthesized_range(argument.into(), (&call.arguments).into(), checker.tokens())
|
||||
.unwrap_or_else(|| argument.range());
|
||||
|
||||
let span = argument.range().add_start(one).sub_end(one);
|
||||
let replacement =
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{self as ast, Expr, Operator};
|
||||
use ruff_python_trivia::is_python_whitespace;
|
||||
use ruff_source_file::LineRanges;
|
||||
|
|
@ -88,13 +88,7 @@ pub(crate) fn explicit(checker: &Checker, expr: &Expr) {
|
|||
checker.report_diagnostic(ExplicitStringConcatenation, expr.range());
|
||||
|
||||
let is_parenthesized = |expr: &Expr| {
|
||||
parenthesized_range(
|
||||
expr.into(),
|
||||
bin_op.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
)
|
||||
.is_some()
|
||||
parenthesized_range(expr.into(), bin_op.into(), checker.tokens()).is_some()
|
||||
};
|
||||
// If either `left` or `right` is parenthesized, generating
|
||||
// a fix would be too involved. Just report the diagnostic.
|
||||
|
|
|
|||
|
|
@ -111,7 +111,6 @@ pub(crate) fn exc_info_outside_except_handler(checker: &Checker, call: &ExprCall
|
|||
}
|
||||
|
||||
let arguments = &call.arguments;
|
||||
let source = checker.source();
|
||||
|
||||
let mut diagnostic = checker.report_diagnostic(ExcInfoOutsideExceptHandler, exc_info.range);
|
||||
|
||||
|
|
@ -120,8 +119,8 @@ pub(crate) fn exc_info_outside_except_handler(checker: &Checker, call: &ExprCall
|
|||
exc_info,
|
||||
arguments,
|
||||
Parentheses::Preserve,
|
||||
source,
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
checker.tokens(),
|
||||
)?;
|
||||
Ok(Fix::unsafe_edit(edit))
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use itertools::Itertools;
|
|||
use rustc_hash::{FxBuildHasher, FxHashSet};
|
||||
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{self as ast, Expr};
|
||||
use ruff_python_stdlib::identifiers::is_identifier;
|
||||
use ruff_text_size::Ranged;
|
||||
|
|
@ -129,8 +129,8 @@ pub(crate) fn unnecessary_dict_kwargs(checker: &Checker, call: &ast::ExprCall) {
|
|||
keyword,
|
||||
&call.arguments,
|
||||
Parentheses::Preserve,
|
||||
checker.locator().contents(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.map(Fix::safe_edit)
|
||||
});
|
||||
|
|
@ -158,8 +158,7 @@ pub(crate) fn unnecessary_dict_kwargs(checker: &Checker, call: &ast::ExprCall) {
|
|||
parenthesized_range(
|
||||
value.into(),
|
||||
dict.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
checker.tokens()
|
||||
)
|
||||
.unwrap_or(value.range())
|
||||
)
|
||||
|
|
|
|||
|
|
@ -73,11 +73,11 @@ pub(crate) fn unnecessary_range_start(checker: &Checker, call: &ast::ExprCall) {
|
|||
let mut diagnostic = checker.report_diagnostic(UnnecessaryRangeStart, start.range());
|
||||
diagnostic.try_set_fix(|| {
|
||||
remove_argument(
|
||||
&start,
|
||||
start,
|
||||
&call.arguments,
|
||||
Parentheses::Preserve,
|
||||
checker.locator().contents(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.map(Fix::safe_edit)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -160,20 +160,16 @@ fn generate_fix(
|
|||
) -> anyhow::Result<Fix> {
|
||||
let locator = checker.locator();
|
||||
let source = locator.contents();
|
||||
let tokens = checker.tokens();
|
||||
|
||||
let deletion = remove_argument(
|
||||
generic_base,
|
||||
arguments,
|
||||
Parentheses::Preserve,
|
||||
source,
|
||||
checker.comment_ranges(),
|
||||
tokens,
|
||||
)?;
|
||||
let insertion = add_argument(
|
||||
locator.slice(generic_base),
|
||||
arguments,
|
||||
checker.comment_ranges(),
|
||||
source,
|
||||
);
|
||||
let insertion = add_argument(locator.slice(generic_base), arguments, tokens);
|
||||
|
||||
Ok(Fix::unsafe_edits(deletion, [insertion]))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use ruff_python_ast::{
|
|||
helpers::{pep_604_union, typing_optional},
|
||||
name::Name,
|
||||
operator_precedence::OperatorPrecedence,
|
||||
parenthesize::parenthesized_range,
|
||||
token::{Tokens, parenthesized_range},
|
||||
};
|
||||
use ruff_python_semantic::analyze::typing::{traverse_literal, traverse_union};
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
|
@ -243,16 +243,12 @@ fn create_fix(
|
|||
let union_expr = pep_604_union(&[new_literal_expr, none_expr]);
|
||||
|
||||
// Check if we need parentheses to preserve operator precedence
|
||||
let content = if needs_parentheses_for_precedence(
|
||||
semantic,
|
||||
literal_expr,
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
) {
|
||||
format!("({})", checker.generator().expr(&union_expr))
|
||||
} else {
|
||||
checker.generator().expr(&union_expr)
|
||||
};
|
||||
let content =
|
||||
if needs_parentheses_for_precedence(semantic, literal_expr, checker.tokens()) {
|
||||
format!("({})", checker.generator().expr(&union_expr))
|
||||
} else {
|
||||
checker.generator().expr(&union_expr)
|
||||
};
|
||||
|
||||
let union_edit = Edit::range_replacement(content, literal_expr.range());
|
||||
Fix::applicable_edit(union_edit, applicability)
|
||||
|
|
@ -278,8 +274,7 @@ enum UnionKind {
|
|||
fn needs_parentheses_for_precedence(
|
||||
semantic: &ruff_python_semantic::SemanticModel,
|
||||
literal_expr: &Expr,
|
||||
comment_ranges: &ruff_python_trivia::CommentRanges,
|
||||
source: &str,
|
||||
tokens: &Tokens,
|
||||
) -> bool {
|
||||
// Get the parent expression to check if we're in a context that needs parentheses
|
||||
let Some(parent_expr) = semantic.current_expression_parent() else {
|
||||
|
|
@ -287,14 +282,7 @@ fn needs_parentheses_for_precedence(
|
|||
};
|
||||
|
||||
// Check if the literal expression is already parenthesized
|
||||
if parenthesized_range(
|
||||
literal_expr.into(),
|
||||
parent_expr.into(),
|
||||
comment_ranges,
|
||||
source,
|
||||
)
|
||||
.is_some()
|
||||
{
|
||||
if parenthesized_range(literal_expr.into(), parent_expr.into(), tokens).is_some() {
|
||||
return false; // Already parenthesized, don't add more
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use libcst_native::{
|
|||
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::helpers::Truthiness;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::visitor::Visitor;
|
||||
use ruff_python_ast::{
|
||||
self as ast, AnyNodeRef, Arguments, BoolOp, ExceptHandler, Expr, Keyword, Stmt, UnaryOp,
|
||||
|
|
@ -303,8 +303,7 @@ pub(crate) fn unittest_assertion(
|
|||
parenthesized_range(
|
||||
expr.into(),
|
||||
checker.semantic().current_statement().into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.unwrap_or(expr.range()),
|
||||
)));
|
||||
|
|
|
|||
|
|
@ -768,8 +768,8 @@ fn check_fixture_decorator(checker: &Checker, func_name: &str, decorator: &Decor
|
|||
keyword,
|
||||
arguments,
|
||||
edits::Parentheses::Preserve,
|
||||
checker.locator().contents(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.map(Fix::unsafe_edit)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@ use rustc_hash::{FxBuildHasher, FxHashMap};
|
|||
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::comparable::ComparableExpr;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::{Tokens, parenthesized_range};
|
||||
use ruff_python_ast::{self as ast, Expr, ExprCall, ExprContext, StringLiteralFlags};
|
||||
use ruff_python_codegen::Generator;
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer};
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
|
|
@ -322,18 +321,8 @@ fn elts_to_csv(elts: &[Expr], generator: Generator, flags: StringLiteralFlags) -
|
|||
/// ```
|
||||
///
|
||||
/// This method assumes that the first argument is a string.
|
||||
fn get_parametrize_name_range(
|
||||
call: &ExprCall,
|
||||
expr: &Expr,
|
||||
comment_ranges: &CommentRanges,
|
||||
source: &str,
|
||||
) -> Option<TextRange> {
|
||||
parenthesized_range(
|
||||
expr.into(),
|
||||
(&call.arguments).into(),
|
||||
comment_ranges,
|
||||
source,
|
||||
)
|
||||
fn get_parametrize_name_range(call: &ExprCall, expr: &Expr, tokens: &Tokens) -> Option<TextRange> {
|
||||
parenthesized_range(expr.into(), (&call.arguments).into(), tokens)
|
||||
}
|
||||
|
||||
/// PT006
|
||||
|
|
@ -349,13 +338,8 @@ fn check_names(checker: &Checker, call: &ExprCall, expr: &Expr, argvalues: &Expr
|
|||
if names.len() > 1 {
|
||||
match names_type {
|
||||
types::ParametrizeNameType::Tuple => {
|
||||
let name_range = get_parametrize_name_range(
|
||||
call,
|
||||
expr,
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
)
|
||||
.unwrap_or(expr.range());
|
||||
let name_range = get_parametrize_name_range(call, expr, checker.tokens())
|
||||
.unwrap_or(expr.range());
|
||||
let mut diagnostic = checker.report_diagnostic(
|
||||
PytestParametrizeNamesWrongType {
|
||||
single_argument: false,
|
||||
|
|
@ -386,13 +370,8 @@ fn check_names(checker: &Checker, call: &ExprCall, expr: &Expr, argvalues: &Expr
|
|||
)));
|
||||
}
|
||||
types::ParametrizeNameType::List => {
|
||||
let name_range = get_parametrize_name_range(
|
||||
call,
|
||||
expr,
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
)
|
||||
.unwrap_or(expr.range());
|
||||
let name_range = get_parametrize_name_range(call, expr, checker.tokens())
|
||||
.unwrap_or(expr.range());
|
||||
let mut diagnostic = checker.report_diagnostic(
|
||||
PytestParametrizeNamesWrongType {
|
||||
single_argument: false,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use ruff_macros::{ViolationMetadata, derive_message_formats};
|
|||
use ruff_python_ast::comparable::ComparableExpr;
|
||||
use ruff_python_ast::helpers::{Truthiness, contains_effect};
|
||||
use ruff_python_ast::name::Name;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_codegen::Generator;
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
|
||||
|
|
@ -800,14 +800,9 @@ fn is_short_circuit(
|
|||
edit = Some(get_short_circuit_edit(
|
||||
value,
|
||||
TextRange::new(
|
||||
parenthesized_range(
|
||||
furthest.into(),
|
||||
expr.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
)
|
||||
.unwrap_or(furthest.range())
|
||||
.start(),
|
||||
parenthesized_range(furthest.into(), expr.into(), checker.tokens())
|
||||
.unwrap_or(furthest.range())
|
||||
.start(),
|
||||
expr.end(),
|
||||
),
|
||||
short_circuit_truthiness,
|
||||
|
|
@ -828,14 +823,9 @@ fn is_short_circuit(
|
|||
edit = Some(get_short_circuit_edit(
|
||||
next_value,
|
||||
TextRange::new(
|
||||
parenthesized_range(
|
||||
furthest.into(),
|
||||
expr.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
)
|
||||
.unwrap_or(furthest.range())
|
||||
.start(),
|
||||
parenthesized_range(furthest.into(), expr.into(), checker.tokens())
|
||||
.unwrap_or(furthest.range())
|
||||
.start(),
|
||||
expr.end(),
|
||||
),
|
||||
short_circuit_truthiness,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use ruff_text_size::{Ranged, TextRange};
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
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::token::parenthesized_range;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::{AlwaysFixableViolation, Edit, Fix, FixAvailability, Violation};
|
||||
|
|
@ -171,13 +171,8 @@ pub(crate) fn if_expr_with_true_false(
|
|||
checker
|
||||
.locator()
|
||||
.slice(
|
||||
parenthesized_range(
|
||||
test.into(),
|
||||
expr.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
)
|
||||
.unwrap_or(test.range()),
|
||||
parenthesized_range(test.into(), expr.into(), checker.tokens())
|
||||
.unwrap_or(test.range()),
|
||||
)
|
||||
.to_string(),
|
||||
expr.range(),
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ use anyhow::Result;
|
|||
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::comparable::ComparableStmt;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::stmt_if::{IfElifBranch, if_elif_branches};
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{self as ast, Expr};
|
||||
use ruff_python_trivia::{CommentRanges, SimpleTokenKind, SimpleTokenizer};
|
||||
use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer};
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ pub(crate) fn if_with_same_arms(checker: &Checker, stmt_if: &ast::StmtIf) {
|
|||
¤t_branch,
|
||||
following_branch,
|
||||
checker.locator(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
)
|
||||
});
|
||||
}
|
||||
|
|
@ -111,7 +111,7 @@ fn merge_branches(
|
|||
current_branch: &IfElifBranch,
|
||||
following_branch: &IfElifBranch,
|
||||
locator: &Locator,
|
||||
comment_ranges: &CommentRanges,
|
||||
tokens: &ruff_python_ast::token::Tokens,
|
||||
) -> Result<Fix> {
|
||||
// Identify the colon (`:`) at the end of the current branch's test.
|
||||
let Some(current_branch_colon) =
|
||||
|
|
@ -127,12 +127,9 @@ fn merge_branches(
|
|||
);
|
||||
|
||||
// If the following test isn't parenthesized, consider parenthesizing it.
|
||||
let following_branch_test = if let Some(range) = parenthesized_range(
|
||||
following_branch.test.into(),
|
||||
stmt_if.into(),
|
||||
comment_ranges,
|
||||
locator.contents(),
|
||||
) {
|
||||
let following_branch_test = if let Some(range) =
|
||||
parenthesized_range(following_branch.test.into(), stmt_if.into(), tokens)
|
||||
{
|
||||
Cow::Borrowed(locator.slice(range))
|
||||
} else if matches!(
|
||||
following_branch.test,
|
||||
|
|
@ -153,24 +150,19 @@ fn merge_branches(
|
|||
//
|
||||
// For example, if the current test is `x if x else y`, we should parenthesize it to
|
||||
// `(x if x else y) or ...`.
|
||||
let parenthesize_edit = if matches!(
|
||||
current_branch.test,
|
||||
Expr::Lambda(_) | Expr::Named(_) | Expr::If(_)
|
||||
) && parenthesized_range(
|
||||
current_branch.test.into(),
|
||||
stmt_if.into(),
|
||||
comment_ranges,
|
||||
locator.contents(),
|
||||
)
|
||||
.is_none()
|
||||
{
|
||||
Some(Edit::range_replacement(
|
||||
format!("({})", locator.slice(current_branch.test)),
|
||||
current_branch.test.range(),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let parenthesize_edit =
|
||||
if matches!(
|
||||
current_branch.test,
|
||||
Expr::Lambda(_) | Expr::Named(_) | Expr::If(_)
|
||||
) && parenthesized_range(current_branch.test.into(), stmt_if.into(), tokens).is_none()
|
||||
{
|
||||
Some(Edit::range_replacement(
|
||||
format!("({})", locator.slice(current_branch.test)),
|
||||
current_branch.test.range(),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(Fix::safe_edits(
|
||||
deletion_edit,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::AnyNodeRef;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{self as ast, Arguments, CmpOp, Comprehension, Expr};
|
||||
use ruff_python_semantic::analyze::typing;
|
||||
use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer};
|
||||
|
|
@ -90,20 +90,10 @@ fn key_in_dict(checker: &Checker, left: &Expr, right: &Expr, operator: CmpOp, pa
|
|||
}
|
||||
|
||||
// Extract the exact range of the left and right expressions.
|
||||
let left_range = parenthesized_range(
|
||||
left.into(),
|
||||
parent,
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
)
|
||||
.unwrap_or(left.range());
|
||||
let right_range = parenthesized_range(
|
||||
right.into(),
|
||||
parent,
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
)
|
||||
.unwrap_or(right.range());
|
||||
let left_range =
|
||||
parenthesized_range(left.into(), parent, checker.tokens()).unwrap_or(left.range());
|
||||
let right_range =
|
||||
parenthesized_range(right.into(), parent, checker.tokens()).unwrap_or(right.range());
|
||||
|
||||
let mut diagnostic = checker.report_diagnostic(
|
||||
InDictKeys {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use crate::registry::Rule;
|
|||
use crate::rules::flake8_type_checking::helpers::quote_type_expression;
|
||||
use crate::{AlwaysFixableViolation, Edit, Fix, FixAvailability, Violation};
|
||||
use ruff_python_ast::PythonVersion;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks if [PEP 613] explicit type aliases contain references to
|
||||
|
|
@ -295,21 +295,20 @@ pub(crate) fn quoted_type_alias(
|
|||
let range = annotation_expr.range();
|
||||
let mut diagnostic = checker.report_diagnostic(QuotedTypeAlias, range);
|
||||
let fix_string = annotation_expr.value.to_string();
|
||||
|
||||
let fix_string = if (fix_string.contains('\n') || fix_string.contains('\r'))
|
||||
&& parenthesized_range(
|
||||
// Check for parenthesis outside string ("""...""")
|
||||
// Check for parentheses outside the string ("""...""")
|
||||
annotation_expr.into(),
|
||||
checker.semantic().current_statement().into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
checker.source_tokens(),
|
||||
)
|
||||
.is_none()
|
||||
&& parenthesized_range(
|
||||
// Check for parenthesis inside string """(...)"""
|
||||
// Check for parentheses inside the string """(...)"""
|
||||
expr.into(),
|
||||
annotation_expr.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.is_none()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
use std::ops::Range;
|
||||
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{Expr, ExprBinOp, ExprCall, Operator};
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
|
@ -89,11 +88,7 @@ pub(crate) fn path_constructor_current_directory(
|
|||
|
||||
let mut diagnostic = checker.report_diagnostic(PathConstructorCurrentDirectory, arg.range());
|
||||
|
||||
match parent_and_next_path_fragment_range(
|
||||
checker.semantic(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
) {
|
||||
match parent_and_next_path_fragment_range(checker.semantic(), checker.tokens()) {
|
||||
Some((parent_range, next_fragment_range)) => {
|
||||
let next_fragment_expr = checker.locator().slice(next_fragment_range);
|
||||
let call_expr = checker.locator().slice(call.range());
|
||||
|
|
@ -116,7 +111,7 @@ pub(crate) fn path_constructor_current_directory(
|
|||
arguments,
|
||||
Parentheses::Preserve,
|
||||
checker.source(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
)?;
|
||||
Ok(Fix::applicable_edit(edit, applicability(call.range())))
|
||||
}),
|
||||
|
|
@ -125,8 +120,7 @@ pub(crate) fn path_constructor_current_directory(
|
|||
|
||||
fn parent_and_next_path_fragment_range(
|
||||
semantic: &SemanticModel,
|
||||
comment_ranges: &CommentRanges,
|
||||
source: &str,
|
||||
tokens: &ruff_python_ast::token::Tokens,
|
||||
) -> Option<(TextRange, TextRange)> {
|
||||
let parent = semantic.current_expression_parent()?;
|
||||
|
||||
|
|
@ -142,6 +136,6 @@ fn parent_and_next_path_fragment_range(
|
|||
|
||||
Some((
|
||||
parent.range(),
|
||||
parenthesized_range(right.into(), parent.into(), comment_ranges, source).unwrap_or(range),
|
||||
parenthesized_range(right.into(), parent.into(), tokens).unwrap_or(range),
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::helpers::is_const_true;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::{Tokens, parenthesized_range};
|
||||
use ruff_python_ast::{self as ast, Keyword, Stmt};
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::Locator;
|
||||
|
|
@ -91,7 +90,7 @@ pub(crate) fn inplace_argument(checker: &Checker, call: &ast::ExprCall) {
|
|||
call,
|
||||
keyword,
|
||||
statement,
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
checker.locator(),
|
||||
) {
|
||||
diagnostic.set_fix(fix);
|
||||
|
|
@ -111,21 +110,16 @@ fn convert_inplace_argument_to_assignment(
|
|||
call: &ast::ExprCall,
|
||||
keyword: &Keyword,
|
||||
statement: &Stmt,
|
||||
comment_ranges: &CommentRanges,
|
||||
tokens: &Tokens,
|
||||
locator: &Locator,
|
||||
) -> Option<Fix> {
|
||||
// Add the assignment.
|
||||
let attr = call.func.as_attribute_expr()?;
|
||||
let insert_assignment = Edit::insertion(
|
||||
format!("{name} = ", name = locator.slice(attr.value.range())),
|
||||
parenthesized_range(
|
||||
call.into(),
|
||||
statement.into(),
|
||||
comment_ranges,
|
||||
locator.contents(),
|
||||
)
|
||||
.unwrap_or(call.range())
|
||||
.start(),
|
||||
parenthesized_range(call.into(), statement.into(), tokens)
|
||||
.unwrap_or(call.range())
|
||||
.start(),
|
||||
);
|
||||
|
||||
// Remove the `inplace` argument.
|
||||
|
|
@ -134,7 +128,7 @@ fn convert_inplace_argument_to_assignment(
|
|||
&call.arguments,
|
||||
Parentheses::Preserve,
|
||||
locator.contents(),
|
||||
comment_ranges,
|
||||
tokens,
|
||||
)
|
||||
.ok()?;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{
|
||||
self as ast, Expr, ExprEllipsisLiteral, ExprLambda, Identifier, Parameter,
|
||||
ParameterWithDefault, Parameters, Stmt,
|
||||
|
|
@ -265,29 +265,19 @@ fn replace_trailing_ellipsis_with_original_expr(
|
|||
stmt: &Stmt,
|
||||
checker: &Checker,
|
||||
) -> String {
|
||||
let original_expr_range = parenthesized_range(
|
||||
(&lambda.body).into(),
|
||||
lambda.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
)
|
||||
.unwrap_or(lambda.body.range());
|
||||
let original_expr_range =
|
||||
parenthesized_range((&lambda.body).into(), lambda.into(), checker.tokens())
|
||||
.unwrap_or(lambda.body.range());
|
||||
|
||||
// This prevents the autofix of introducing a syntax error if the lambda's body is an
|
||||
// expression spanned across multiple lines. To avoid the syntax error we preserve
|
||||
// the parenthesis around the body.
|
||||
let original_expr_in_source = if parenthesized_range(
|
||||
lambda.into(),
|
||||
stmt.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
)
|
||||
.is_some()
|
||||
{
|
||||
format!("({})", checker.locator().slice(original_expr_range))
|
||||
} else {
|
||||
checker.locator().slice(original_expr_range).to_string()
|
||||
};
|
||||
let original_expr_in_source =
|
||||
if parenthesized_range(lambda.into(), stmt.into(), checker.tokens()).is_some() {
|
||||
format!("({})", checker.locator().slice(original_expr_range))
|
||||
} else {
|
||||
checker.locator().slice(original_expr_range).to_string()
|
||||
};
|
||||
|
||||
let placeholder_ellipsis_start = generated.rfind("...").unwrap();
|
||||
let placeholder_ellipsis_end = placeholder_ellipsis_start + "...".len();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::{Tokens, parenthesized_range};
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
|
|
@ -179,15 +179,14 @@ fn is_redundant_boolean_comparison(op: CmpOp, comparator: &Expr) -> Option<bool>
|
|||
|
||||
fn generate_redundant_comparison(
|
||||
compare: &ast::ExprCompare,
|
||||
comment_ranges: &ruff_python_trivia::CommentRanges,
|
||||
tokens: &Tokens,
|
||||
source: &str,
|
||||
comparator: &Expr,
|
||||
kind: bool,
|
||||
needs_wrap: bool,
|
||||
) -> String {
|
||||
let comparator_range =
|
||||
parenthesized_range(comparator.into(), compare.into(), comment_ranges, source)
|
||||
.unwrap_or(comparator.range());
|
||||
let comparator_range = parenthesized_range(comparator.into(), compare.into(), tokens)
|
||||
.unwrap_or(comparator.range());
|
||||
|
||||
let comparator_str = &source[comparator_range];
|
||||
|
||||
|
|
@ -379,7 +378,7 @@ pub(crate) fn literal_comparisons(checker: &Checker, compare: &ast::ExprCompare)
|
|||
.copied()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let comment_ranges = checker.comment_ranges();
|
||||
let tokens = checker.tokens();
|
||||
let source = checker.source();
|
||||
|
||||
let content = match (&*compare.ops, &*compare.comparators) {
|
||||
|
|
@ -387,18 +386,13 @@ pub(crate) fn literal_comparisons(checker: &Checker, compare: &ast::ExprCompare)
|
|||
if let Some(kind) = is_redundant_boolean_comparison(*op, &compare.left) {
|
||||
let needs_wrap = compare.left.range().start() != compare.range().start();
|
||||
generate_redundant_comparison(
|
||||
compare,
|
||||
comment_ranges,
|
||||
source,
|
||||
comparator,
|
||||
kind,
|
||||
needs_wrap,
|
||||
compare, tokens, source, comparator, kind, needs_wrap,
|
||||
)
|
||||
} else if let Some(kind) = is_redundant_boolean_comparison(*op, comparator) {
|
||||
let needs_wrap = comparator.range().end() != compare.range().end();
|
||||
generate_redundant_comparison(
|
||||
compare,
|
||||
comment_ranges,
|
||||
tokens,
|
||||
source,
|
||||
&compare.left,
|
||||
kind,
|
||||
|
|
@ -410,7 +404,7 @@ pub(crate) fn literal_comparisons(checker: &Checker, compare: &ast::ExprCompare)
|
|||
&ops,
|
||||
&compare.comparators,
|
||||
compare.into(),
|
||||
comment_ranges,
|
||||
tokens,
|
||||
source,
|
||||
)
|
||||
}
|
||||
|
|
@ -420,7 +414,7 @@ pub(crate) fn literal_comparisons(checker: &Checker, compare: &ast::ExprCompare)
|
|||
&ops,
|
||||
&compare.comparators,
|
||||
compare.into(),
|
||||
comment_ranges,
|
||||
tokens,
|
||||
source,
|
||||
),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ pub(crate) fn not_tests(checker: &Checker, unary_op: &ast::ExprUnaryOp) {
|
|||
&[CmpOp::NotIn],
|
||||
comparators,
|
||||
unary_op.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
checker.source(),
|
||||
),
|
||||
unary_op.range(),
|
||||
|
|
@ -127,7 +127,7 @@ pub(crate) fn not_tests(checker: &Checker, unary_op: &ast::ExprUnaryOp) {
|
|||
&[CmpOp::IsNot],
|
||||
comparators,
|
||||
unary_op.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
checker.source(),
|
||||
),
|
||||
unary_op.range(),
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::collections::hash_map::Entry;
|
|||
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::comparable::{ComparableExpr, HashableExpr};
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{self as ast, Expr};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
|
|
@ -193,16 +193,14 @@ pub(crate) fn repeated_keys(checker: &Checker, dict: &ast::ExprDict) {
|
|||
parenthesized_range(
|
||||
dict.value(i - 1).into(),
|
||||
dict.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.unwrap_or_else(|| dict.value(i - 1).range())
|
||||
.end(),
|
||||
parenthesized_range(
|
||||
dict.value(i).into(),
|
||||
dict.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.unwrap_or_else(|| dict.value(i).range())
|
||||
.end(),
|
||||
|
|
@ -224,16 +222,14 @@ pub(crate) fn repeated_keys(checker: &Checker, dict: &ast::ExprDict) {
|
|||
parenthesized_range(
|
||||
dict.value(i - 1).into(),
|
||||
dict.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.unwrap_or_else(|| dict.value(i - 1).range())
|
||||
.end(),
|
||||
parenthesized_range(
|
||||
dict.value(i).into(),
|
||||
dict.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.unwrap_or_else(|| dict.value(i).range())
|
||||
.end(),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use itertools::Itertools;
|
|||
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::helpers::contains_effect;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::token::{TokenKind, Tokens};
|
||||
use ruff_python_ast::{self as ast, Stmt};
|
||||
use ruff_python_semantic::Binding;
|
||||
|
|
@ -172,14 +172,10 @@ fn remove_unused_variable(binding: &Binding, checker: &Checker) -> Option<Fix> {
|
|||
{
|
||||
// If the expression is complex (`x = foo()`), remove the assignment,
|
||||
// but preserve the right-hand side.
|
||||
let start = parenthesized_range(
|
||||
target.into(),
|
||||
statement.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
)
|
||||
.unwrap_or(target.range())
|
||||
.start();
|
||||
let start =
|
||||
parenthesized_range(target.into(), statement.into(), checker.tokens())
|
||||
.unwrap_or(target.range())
|
||||
.start();
|
||||
let end = match_token_after(checker.tokens(), target.end(), |token| {
|
||||
token == TokenKind::Equal
|
||||
})?
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use itertools::Itertools;
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::{
|
||||
BoolOp, CmpOp, Expr, ExprBoolOp, ExprCompare,
|
||||
parenthesize::{parentheses_iterator, parenthesized_range},
|
||||
token::{parentheses_iterator, parenthesized_range},
|
||||
};
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ pub(crate) fn boolean_chained_comparison(checker: &Checker, expr_bool_op: &ExprB
|
|||
}
|
||||
|
||||
let locator = checker.locator();
|
||||
let comment_ranges = checker.comment_ranges();
|
||||
let tokens = checker.tokens();
|
||||
|
||||
// retrieve all compare expressions from boolean expression
|
||||
let compare_expressions = expr_bool_op
|
||||
|
|
@ -89,40 +89,22 @@ pub(crate) fn boolean_chained_comparison(checker: &Checker, expr_bool_op: &ExprB
|
|||
continue;
|
||||
}
|
||||
|
||||
let left_paren_count = parentheses_iterator(
|
||||
left_compare.into(),
|
||||
Some(expr_bool_op.into()),
|
||||
comment_ranges,
|
||||
locator.contents(),
|
||||
)
|
||||
.count();
|
||||
let left_paren_count =
|
||||
parentheses_iterator(left_compare.into(), Some(expr_bool_op.into()), tokens).count();
|
||||
|
||||
let right_paren_count = parentheses_iterator(
|
||||
right_compare.into(),
|
||||
Some(expr_bool_op.into()),
|
||||
comment_ranges,
|
||||
locator.contents(),
|
||||
)
|
||||
.count();
|
||||
let right_paren_count =
|
||||
parentheses_iterator(right_compare.into(), Some(expr_bool_op.into()), tokens).count();
|
||||
|
||||
// Create the edit that removes the comparison operator
|
||||
|
||||
// In `a<(b) and ((b))<c`, we need to handle the
|
||||
// parentheses when specifying the fix range.
|
||||
let left_compare_right_range = parenthesized_range(
|
||||
left_compare_right.into(),
|
||||
left_compare.into(),
|
||||
comment_ranges,
|
||||
locator.contents(),
|
||||
)
|
||||
.unwrap_or(left_compare_right.range());
|
||||
let right_compare_left_range = parenthesized_range(
|
||||
right_compare_left.into(),
|
||||
right_compare.into(),
|
||||
comment_ranges,
|
||||
locator.contents(),
|
||||
)
|
||||
.unwrap_or(right_compare_left.range());
|
||||
let left_compare_right_range =
|
||||
parenthesized_range(left_compare_right.into(), left_compare.into(), tokens)
|
||||
.unwrap_or(left_compare_right.range());
|
||||
let right_compare_left_range =
|
||||
parenthesized_range(right_compare_left.into(), right_compare.into(), tokens)
|
||||
.unwrap_or(right_compare_left.range());
|
||||
let edit = Edit::range_replacement(
|
||||
locator.slice(left_compare_right_range).to_string(),
|
||||
TextRange::new(
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ pub(crate) fn duplicate_bases(checker: &Checker, name: &str, arguments: Option<&
|
|||
arguments,
|
||||
Parentheses::Remove,
|
||||
checker.locator().contents(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.map(|edit| {
|
||||
Fix::applicable_edit(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::comparable::ComparableExpr;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{self as ast, CmpOp, Stmt};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
|
|
@ -166,13 +166,8 @@ pub(crate) fn if_stmt_min_max(checker: &Checker, stmt_if: &ast::StmtIf) {
|
|||
let replacement = format!(
|
||||
"{} = {min_max}({}, {})",
|
||||
checker.locator().slice(
|
||||
parenthesized_range(
|
||||
body_target.into(),
|
||||
body.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents()
|
||||
)
|
||||
.unwrap_or(body_target.range())
|
||||
parenthesized_range(body_target.into(), body.into(), checker.tokens())
|
||||
.unwrap_or(body_target.range())
|
||||
),
|
||||
checker.locator().slice(arg1),
|
||||
checker.locator().slice(arg2),
|
||||
|
|
|
|||
|
|
@ -174,12 +174,8 @@ pub(crate) fn missing_maxsplit_arg(checker: &Checker, value: &Expr, slice: &Expr
|
|||
SliceBoundary::Last => "rsplit",
|
||||
};
|
||||
|
||||
let maxsplit_argument_edit = fix::edits::add_argument(
|
||||
"maxsplit=1",
|
||||
arguments,
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
);
|
||||
let maxsplit_argument_edit =
|
||||
fix::edits::add_argument("maxsplit=1", arguments, checker.tokens());
|
||||
|
||||
// Only change `actual_split_type` if it doesn't match `suggested_split_type`
|
||||
let split_type_edit: Option<Edit> = if actual_split_type == suggested_split_type {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use ast::Expr;
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast as ast;
|
||||
use ruff_python_ast::comparable::ComparableExpr;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{ExprBinOp, ExprRef, Operator};
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
|
|
@ -150,12 +150,10 @@ fn augmented_assignment(
|
|||
|
||||
let right_operand_ref = ExprRef::from(right_operand);
|
||||
let parent = original_expr.into();
|
||||
let comment_ranges = checker.comment_ranges();
|
||||
let source = checker.source();
|
||||
let tokens = checker.tokens();
|
||||
|
||||
let right_operand_range =
|
||||
parenthesized_range(right_operand_ref, parent, comment_ranges, source)
|
||||
.unwrap_or(right_operand.range());
|
||||
parenthesized_range(right_operand_ref, parent, tokens).unwrap_or(right_operand.range());
|
||||
let right_operand_expr = locator.slice(right_operand_range);
|
||||
|
||||
let target_expr = locator.slice(target);
|
||||
|
|
|
|||
|
|
@ -75,12 +75,7 @@ pub(crate) fn subprocess_run_without_check(checker: &Checker, call: &ast::ExprCa
|
|||
let mut diagnostic =
|
||||
checker.report_diagnostic(SubprocessRunWithoutCheck, call.func.range());
|
||||
diagnostic.set_fix(Fix::applicable_edit(
|
||||
add_argument(
|
||||
"check=False",
|
||||
&call.arguments,
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
),
|
||||
add_argument("check=False", &call.arguments, checker.tokens()),
|
||||
// If the function call contains `**kwargs`, mark the fix as unsafe.
|
||||
if call
|
||||
.arguments
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::name::QualifiedName;
|
||||
use ruff_python_ast::{self as ast, Expr};
|
||||
use ruff_python_ast::{self as ast, Expr, name::QualifiedName};
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
use ruff_python_semantic::analyze::typing;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
|
@ -193,8 +192,7 @@ fn generate_keyword_fix(checker: &Checker, call: &ast::ExprCall) -> Fix {
|
|||
}))
|
||||
),
|
||||
&call.arguments,
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
checker.tokens(),
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ pub(crate) fn non_pep695_generic_class(checker: &Checker, class_def: &StmtClassD
|
|||
arguments,
|
||||
Parentheses::Remove,
|
||||
checker.source(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
)?;
|
||||
Ok(Fix::unsafe_edits(
|
||||
Edit::insertion(type_params.to_string(), name.end()),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use itertools::Itertools;
|
|||
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::name::Name;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::visitor::Visitor;
|
||||
use ruff_python_ast::{Expr, ExprCall, ExprName, Keyword, StmtAnnAssign, StmtAssign, StmtRef};
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
|
@ -261,11 +261,11 @@ fn create_diagnostic(
|
|||
type_alias_kind: TypeAliasKind,
|
||||
) {
|
||||
let source = checker.source();
|
||||
let tokens = checker.tokens();
|
||||
let comment_ranges = checker.comment_ranges();
|
||||
|
||||
let range_with_parentheses =
|
||||
parenthesized_range(value.into(), stmt.into(), comment_ranges, source)
|
||||
.unwrap_or(value.range());
|
||||
parenthesized_range(value.into(), stmt.into(), tokens).unwrap_or(value.range());
|
||||
|
||||
let content = format!(
|
||||
"type {name}{type_params} = {value}",
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
use anyhow::Result;
|
||||
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::{self as ast, Keyword};
|
||||
use ruff_python_ast::{self as ast, Keyword, token::Tokens};
|
||||
use ruff_python_semantic::Modules;
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
|
@ -104,7 +103,7 @@ pub(crate) fn replace_stdout_stderr(checker: &Checker, call: &ast::ExprCall) {
|
|||
stderr,
|
||||
call,
|
||||
checker.locator().contents(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
)
|
||||
});
|
||||
}
|
||||
|
|
@ -117,7 +116,7 @@ fn generate_fix(
|
|||
stderr: &Keyword,
|
||||
call: &ast::ExprCall,
|
||||
source: &str,
|
||||
comment_ranges: &CommentRanges,
|
||||
tokens: &Tokens,
|
||||
) -> Result<Fix> {
|
||||
let (first, second) = if stdout.start() < stderr.start() {
|
||||
(stdout, stderr)
|
||||
|
|
@ -132,7 +131,7 @@ fn generate_fix(
|
|||
&call.arguments,
|
||||
Parentheses::Preserve,
|
||||
source,
|
||||
comment_ranges,
|
||||
tokens,
|
||||
)?],
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ pub(crate) fn replace_universal_newlines(checker: &Checker, call: &ast::ExprCall
|
|||
&call.arguments,
|
||||
Parentheses::Preserve,
|
||||
checker.locator().contents(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.map(Fix::safe_edit)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ pub(crate) fn unnecessary_encode_utf8(checker: &Checker, call: &ast::ExprCall) {
|
|||
&call.arguments,
|
||||
Parentheses::Preserve,
|
||||
checker.locator().contents(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.map(Fix::safe_edit)
|
||||
});
|
||||
|
|
@ -206,7 +206,7 @@ pub(crate) fn unnecessary_encode_utf8(checker: &Checker, call: &ast::ExprCall) {
|
|||
&call.arguments,
|
||||
Parentheses::Preserve,
|
||||
checker.locator().contents(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.map(Fix::safe_edit)
|
||||
});
|
||||
|
|
@ -231,7 +231,7 @@ pub(crate) fn unnecessary_encode_utf8(checker: &Checker, call: &ast::ExprCall) {
|
|||
&call.arguments,
|
||||
Parentheses::Preserve,
|
||||
checker.locator().contents(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.map(Fix::safe_edit)
|
||||
});
|
||||
|
|
@ -249,7 +249,7 @@ pub(crate) fn unnecessary_encode_utf8(checker: &Checker, call: &ast::ExprCall) {
|
|||
&call.arguments,
|
||||
Parentheses::Preserve,
|
||||
checker.locator().contents(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.map(Fix::safe_edit)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ pub(crate) fn useless_class_metaclass_type(checker: &Checker, class_def: &StmtCl
|
|||
arguments,
|
||||
Parentheses::Remove,
|
||||
checker.locator().contents(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
)?;
|
||||
|
||||
let range = edit.range();
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ pub(crate) fn useless_object_inheritance(checker: &Checker, class_def: &ast::Stm
|
|||
arguments,
|
||||
Parentheses::Remove,
|
||||
checker.locator().contents(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
)?;
|
||||
|
||||
let range = edit.range();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{self as ast, Expr, Stmt};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
|
|
@ -139,13 +139,8 @@ pub(crate) fn yield_in_for_loop(checker: &Checker, stmt_for: &ast::StmtFor) {
|
|||
let mut diagnostic = checker.report_diagnostic(YieldInForLoop, stmt_for.range());
|
||||
|
||||
let contents = checker.locator().slice(
|
||||
parenthesized_range(
|
||||
iter.as_ref().into(),
|
||||
stmt_for.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
)
|
||||
.unwrap_or(iter.range()),
|
||||
parenthesized_range(iter.as_ref().into(), stmt_for.into(), checker.tokens())
|
||||
.unwrap_or(iter.range()),
|
||||
);
|
||||
let contents = if iter.as_tuple_expr().is_some_and(|it| !it.parenthesized) {
|
||||
format!("yield from ({contents})")
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use ruff_python_ast::PythonVersion;
|
||||
use ruff_python_ast::{self as ast, Expr, name::Name, parenthesize::parenthesized_range};
|
||||
use ruff_python_ast::{self as ast, Expr, name::Name, token::parenthesized_range};
|
||||
use ruff_python_codegen::Generator;
|
||||
use ruff_python_semantic::{BindingId, ResolvedReference, SemanticModel};
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
|
@ -330,12 +330,8 @@ pub(super) fn parenthesize_loop_iter_if_necessary<'a>(
|
|||
let locator = checker.locator();
|
||||
let iter = for_stmt.iter.as_ref();
|
||||
|
||||
let original_parenthesized_range = parenthesized_range(
|
||||
iter.into(),
|
||||
for_stmt.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
);
|
||||
let original_parenthesized_range =
|
||||
parenthesized_range(iter.into(), for_stmt.into(), checker.tokens());
|
||||
|
||||
if let Some(range) = original_parenthesized_range {
|
||||
return Cow::Borrowed(locator.slice(range));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{
|
||||
Expr, ExprAttribute, ExprBinOp, ExprCall, ExprStringLiteral, ExprSubscript, ExprUnaryOp,
|
||||
Number, Operator, PythonVersion, UnaryOp,
|
||||
|
|
@ -112,8 +112,7 @@ pub(crate) fn fromisoformat_replace_z(checker: &Checker, call: &ExprCall) {
|
|||
let value_full_range = parenthesized_range(
|
||||
replace_time_zone.date.into(),
|
||||
replace_time_zone.parent.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.unwrap_or(replace_time_zone.date.range());
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ use ruff_python_ast as ast;
|
|||
use ruff_python_ast::Expr;
|
||||
use ruff_python_ast::comparable::ComparableExpr;
|
||||
use ruff_python_ast::helpers::contains_effect;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_python_ast::token::{Tokens, parenthesized_range};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::Locator;
|
||||
|
|
@ -76,8 +75,8 @@ pub(crate) fn if_exp_instead_of_or_operator(checker: &Checker, if_expr: &ast::Ex
|
|||
Edit::range_replacement(
|
||||
format!(
|
||||
"{} or {}",
|
||||
parenthesize_test(test, if_expr, checker.comment_ranges(), checker.locator()),
|
||||
parenthesize_test(orelse, if_expr, checker.comment_ranges(), checker.locator()),
|
||||
parenthesize_test(test, if_expr, checker.tokens(), checker.locator()),
|
||||
parenthesize_test(orelse, if_expr, checker.tokens(), checker.locator()),
|
||||
),
|
||||
if_expr.range(),
|
||||
),
|
||||
|
|
@ -99,15 +98,10 @@ pub(crate) fn if_exp_instead_of_or_operator(checker: &Checker, if_expr: &ast::Ex
|
|||
fn parenthesize_test<'a>(
|
||||
expr: &Expr,
|
||||
if_expr: &ast::ExprIf,
|
||||
comment_ranges: &CommentRanges,
|
||||
tokens: &Tokens,
|
||||
locator: &Locator<'a>,
|
||||
) -> Cow<'a, str> {
|
||||
if let Some(range) = parenthesized_range(
|
||||
expr.into(),
|
||||
if_expr.into(),
|
||||
comment_ranges,
|
||||
locator.contents(),
|
||||
) {
|
||||
if let Some(range) = parenthesized_range(expr.into(), if_expr.into(), tokens) {
|
||||
Cow::Borrowed(locator.slice(range))
|
||||
} else if matches!(expr, Expr::If(_) | Expr::Lambda(_) | Expr::Named(_)) {
|
||||
Cow::Owned(format!("({})", locator.slice(expr.range())))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use ruff_diagnostics::Applicability;
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{Comprehension, Expr, StmtFor};
|
||||
use ruff_python_semantic::analyze::typing;
|
||||
use ruff_python_semantic::analyze::typing::is_io_base_expr;
|
||||
|
|
@ -104,8 +104,7 @@ fn readlines_in_iter(checker: &Checker, iter_expr: &Expr) {
|
|||
let deletion_range = if let Some(parenthesized_range) = parenthesized_range(
|
||||
expr_attr.value.as_ref().into(),
|
||||
expr_attr.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
checker.tokens(),
|
||||
) {
|
||||
expr_call.range().add_start(parenthesized_range.len())
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use anyhow::Result;
|
||||
use ruff_diagnostics::Applicability;
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{self as ast, Expr, Number};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
|
|
@ -152,13 +152,8 @@ fn generate_fix(checker: &Checker, call: &ast::ExprCall, base: Base, arg: &Expr)
|
|||
checker.semantic(),
|
||||
)?;
|
||||
|
||||
let arg_range = parenthesized_range(
|
||||
arg.into(),
|
||||
call.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
)
|
||||
.unwrap_or(arg.range());
|
||||
let arg_range =
|
||||
parenthesized_range(arg.into(), call.into(), checker.tokens()).unwrap_or(arg.range());
|
||||
let arg_str = checker.locator().slice(arg_range);
|
||||
|
||||
Ok(Fix::applicable_edits(
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ pub(crate) fn single_item_membership_test(
|
|||
&[membership_test.replacement_op()],
|
||||
std::slice::from_ref(item),
|
||||
expr.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
checker.source(),
|
||||
),
|
||||
expr.range(),
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ fn convert_type_vars(
|
|||
class_arguments,
|
||||
Parentheses::Remove,
|
||||
source,
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
)?;
|
||||
let replace_type_params =
|
||||
Edit::range_replacement(new_type_params.to_string(), type_params.range);
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ use anyhow::Result;
|
|||
use ast::Keyword;
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::helpers::is_constant;
|
||||
use ruff_python_ast::token::Tokens;
|
||||
use ruff_python_ast::{self as ast, Expr};
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::Locator;
|
||||
|
|
@ -108,9 +108,8 @@ pub(crate) fn default_factory_kwarg(checker: &Checker, call: &ast::ExprCall) {
|
|||
},
|
||||
call.range(),
|
||||
);
|
||||
diagnostic.try_set_fix(|| {
|
||||
convert_to_positional(call, keyword, checker.locator(), checker.comment_ranges())
|
||||
});
|
||||
diagnostic
|
||||
.try_set_fix(|| convert_to_positional(call, keyword, checker.locator(), checker.tokens()));
|
||||
}
|
||||
|
||||
/// Returns `true` if a value is definitively not callable (e.g., `1` or `[]`).
|
||||
|
|
@ -136,7 +135,7 @@ fn convert_to_positional(
|
|||
call: &ast::ExprCall,
|
||||
default_factory: &Keyword,
|
||||
locator: &Locator,
|
||||
comment_ranges: &CommentRanges,
|
||||
tokens: &Tokens,
|
||||
) -> Result<Fix> {
|
||||
if call.arguments.len() == 1 {
|
||||
// Ex) `defaultdict(default_factory=list)`
|
||||
|
|
@ -153,7 +152,7 @@ fn convert_to_positional(
|
|||
&call.arguments,
|
||||
Parentheses::Preserve,
|
||||
locator.contents(),
|
||||
comment_ranges,
|
||||
tokens,
|
||||
)?;
|
||||
|
||||
// Second, insert the value as the first positional argument.
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ pub(crate) fn falsy_dict_get_fallback(checker: &Checker, expr: &Expr) {
|
|||
&call.arguments,
|
||||
Parentheses::Preserve,
|
||||
checker.locator().contents(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.map(|edit| Fix::applicable_edit(edit, applicability))
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast as ast;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
|
@ -77,14 +77,7 @@ pub(crate) fn parenthesize_chained_logical_operators(checker: &Checker, expr: &a
|
|||
) => {
|
||||
let locator = checker.locator();
|
||||
let source_range = bool_op.range();
|
||||
if parenthesized_range(
|
||||
bool_op.into(),
|
||||
expr.into(),
|
||||
checker.comment_ranges(),
|
||||
locator.contents(),
|
||||
)
|
||||
.is_none()
|
||||
{
|
||||
if parenthesized_range(bool_op.into(), expr.into(), checker.tokens()).is_none() {
|
||||
let new_source = format!("({})", locator.slice(source_range));
|
||||
let edit = Edit::range_replacement(new_source, source_range);
|
||||
checker
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use anyhow::Context;
|
|||
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast as ast;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_semantic::{Scope, ScopeKind};
|
||||
use ruff_python_trivia::{indentation_at_offset, textwrap};
|
||||
use ruff_source_file::LineRanges;
|
||||
|
|
@ -159,8 +159,7 @@ fn use_initvar(
|
|||
let default_loc = parenthesized_range(
|
||||
default.into(),
|
||||
parameter_with_default.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
checker.tokens(),
|
||||
)
|
||||
.unwrap_or(default.range());
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use anyhow::Result;
|
|||
use itertools::Itertools;
|
||||
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{self as ast, Arguments, Expr};
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
use ruff_text_size::Ranged;
|
||||
|
|
@ -116,13 +116,8 @@ fn convert_to_reduce(iterable: &Expr, call: &ast::ExprCall, checker: &Checker) -
|
|||
)?;
|
||||
|
||||
let iterable = checker.locator().slice(
|
||||
parenthesized_range(
|
||||
iterable.into(),
|
||||
(&call.arguments).into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
)
|
||||
.unwrap_or(iterable.range()),
|
||||
parenthesized_range(iterable.into(), (&call.arguments).into(), checker.tokens())
|
||||
.unwrap_or(iterable.range()),
|
||||
);
|
||||
|
||||
Ok(Fix::unsafe_edits(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::PythonVersion;
|
||||
use ruff_python_ast::token::TokenKind;
|
||||
use ruff_python_ast::{Expr, ExprCall, parenthesize::parenthesized_range};
|
||||
use ruff_python_ast::{Expr, ExprCall, token::parenthesized_range};
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
|
@ -124,13 +124,8 @@ fn replace_with_map(starmap: &ExprCall, zip: &ExprCall, checker: &Checker) -> Op
|
|||
|
||||
let mut remove_zip = vec![];
|
||||
|
||||
let full_zip_range = parenthesized_range(
|
||||
zip.into(),
|
||||
starmap.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
)
|
||||
.unwrap_or(zip.range());
|
||||
let full_zip_range =
|
||||
parenthesized_range(zip.into(), starmap.into(), checker.tokens()).unwrap_or(zip.range());
|
||||
|
||||
// Delete any parentheses around the `zip` call to prevent that the argument turns into a tuple.
|
||||
remove_zip.push(Edit::range_deletion(TextRange::new(
|
||||
|
|
@ -138,13 +133,8 @@ fn replace_with_map(starmap: &ExprCall, zip: &ExprCall, checker: &Checker) -> Op
|
|||
zip.start(),
|
||||
)));
|
||||
|
||||
let full_zip_func_range = parenthesized_range(
|
||||
(&zip.func).into(),
|
||||
zip.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
)
|
||||
.unwrap_or(zip.func.range());
|
||||
let full_zip_func_range = parenthesized_range((&zip.func).into(), zip.into(), checker.tokens())
|
||||
.unwrap_or(zip.func.range());
|
||||
|
||||
// Delete the `zip` callee
|
||||
remove_zip.push(Edit::range_deletion(full_zip_func_range));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::{Tokens, parenthesized_range};
|
||||
use ruff_python_ast::{Arguments, Expr, ExprCall};
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
use ruff_python_semantic::analyze::type_inference::{NumberLike, PythonType, ResolvedPythonType};
|
||||
|
|
@ -86,6 +86,7 @@ pub(crate) fn unnecessary_cast_to_int(checker: &Checker, call: &ExprCall) {
|
|||
applicability,
|
||||
checker.semantic(),
|
||||
checker.locator(),
|
||||
checker.tokens(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
);
|
||||
|
|
@ -95,27 +96,26 @@ pub(crate) fn unnecessary_cast_to_int(checker: &Checker, call: &ExprCall) {
|
|||
}
|
||||
|
||||
/// Creates a fix that replaces `int(expression)` with `expression`.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn unwrap_int_expression(
|
||||
call: &ExprCall,
|
||||
argument: &Expr,
|
||||
applicability: Applicability,
|
||||
semantic: &SemanticModel,
|
||||
locator: &Locator,
|
||||
tokens: &Tokens,
|
||||
comment_ranges: &CommentRanges,
|
||||
source: &str,
|
||||
) -> Fix {
|
||||
let content = if let Some(range) = parenthesized_range(
|
||||
argument.into(),
|
||||
(&call.arguments).into(),
|
||||
comment_ranges,
|
||||
source,
|
||||
) {
|
||||
let content = if let Some(range) =
|
||||
parenthesized_range(argument.into(), (&call.arguments).into(), tokens)
|
||||
{
|
||||
locator.slice(range).to_string()
|
||||
} else {
|
||||
let parenthesize = semantic.current_expression_parent().is_some()
|
||||
|| argument.is_named_expr()
|
||||
|| locator.count_lines(argument.range()) > 0;
|
||||
if parenthesize && !has_own_parentheses(argument, comment_ranges, source) {
|
||||
if parenthesize && !has_own_parentheses(argument, tokens, source) {
|
||||
format!("({})", locator.slice(argument.range()))
|
||||
} else {
|
||||
locator.slice(argument.range()).to_string()
|
||||
|
|
@ -255,7 +255,7 @@ fn round_applicability(arguments: &Arguments, semantic: &SemanticModel) -> Optio
|
|||
}
|
||||
|
||||
/// Returns `true` if the given [`Expr`] has its own parentheses (e.g., `()`, `[]`, `{}`).
|
||||
fn has_own_parentheses(expr: &Expr, comment_ranges: &CommentRanges, source: &str) -> bool {
|
||||
fn has_own_parentheses(expr: &Expr, tokens: &Tokens, source: &str) -> bool {
|
||||
match expr {
|
||||
Expr::ListComp(_)
|
||||
| Expr::SetComp(_)
|
||||
|
|
@ -276,14 +276,10 @@ fn has_own_parentheses(expr: &Expr, comment_ranges: &CommentRanges, source: &str
|
|||
// f
|
||||
// (10)
|
||||
// ```
|
||||
let func_end = parenthesized_range(
|
||||
call_expr.func.as_ref().into(),
|
||||
call_expr.into(),
|
||||
comment_ranges,
|
||||
source,
|
||||
)
|
||||
.unwrap_or(call_expr.func.range())
|
||||
.end();
|
||||
let func_end =
|
||||
parenthesized_range(call_expr.func.as_ref().into(), call_expr.into(), tokens)
|
||||
.unwrap_or(call_expr.func.range())
|
||||
.end();
|
||||
lines_after_ignoring_trivia(func_end, source) == 0
|
||||
}
|
||||
Expr::Subscript(subscript_expr) => {
|
||||
|
|
@ -291,8 +287,7 @@ fn has_own_parentheses(expr: &Expr, comment_ranges: &CommentRanges, source: &str
|
|||
let subscript_end = parenthesized_range(
|
||||
subscript_expr.value.as_ref().into(),
|
||||
subscript_expr.into(),
|
||||
comment_ranges,
|
||||
source,
|
||||
tokens,
|
||||
)
|
||||
.unwrap_or(subscript_expr.value.range())
|
||||
.end();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use ruff_python_ast::{self as ast, BoolOp, CmpOp, Expr};
|
|||
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::helpers::contains_effect;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
|
@ -108,22 +108,12 @@ pub(crate) fn unnecessary_key_check(checker: &Checker, expr: &Expr) {
|
|||
format!(
|
||||
"{}.get({})",
|
||||
checker.locator().slice(
|
||||
parenthesized_range(
|
||||
obj_right.into(),
|
||||
right.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
)
|
||||
.unwrap_or(obj_right.range())
|
||||
parenthesized_range(obj_right.into(), right.into(), checker.tokens(),)
|
||||
.unwrap_or(obj_right.range())
|
||||
),
|
||||
checker.locator().slice(
|
||||
parenthesized_range(
|
||||
key_right.into(),
|
||||
right.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator().contents(),
|
||||
)
|
||||
.unwrap_or(key_right.range())
|
||||
parenthesized_range(key_right.into(), right.into(), checker.tokens(),)
|
||||
.unwrap_or(key_right.range())
|
||||
),
|
||||
),
|
||||
expr.range(),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use ruff_diagnostics::{Applicability, Edit};
|
|||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
|
||||
use ruff_python_ast::helpers::is_empty_f_string;
|
||||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::token::parenthesized_range;
|
||||
use ruff_python_ast::{self as ast, Expr};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
|
|
@ -140,31 +140,19 @@ fn fix_unnecessary_literal_in_deque(
|
|||
// call. otherwise, we only delete the `iterable` argument and leave the others untouched.
|
||||
let edit = if let Some(maxlen) = maxlen {
|
||||
let deque_name = checker.locator().slice(
|
||||
parenthesized_range(
|
||||
deque.func.as_ref().into(),
|
||||
deque.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
)
|
||||
.unwrap_or(deque.func.range()),
|
||||
parenthesized_range(deque.func.as_ref().into(), deque.into(), checker.tokens())
|
||||
.unwrap_or(deque.func.range()),
|
||||
);
|
||||
let len_str = checker.locator().slice(maxlen);
|
||||
let deque_str = format!("{deque_name}(maxlen={len_str})");
|
||||
Edit::range_replacement(deque_str, deque.range)
|
||||
} else {
|
||||
let range = parenthesized_range(
|
||||
iterable.value().into(),
|
||||
(&deque.arguments).into(),
|
||||
checker.comment_ranges(),
|
||||
checker.source(),
|
||||
)
|
||||
.unwrap_or(iterable.range());
|
||||
remove_argument(
|
||||
&range,
|
||||
&iterable,
|
||||
&deque.arguments,
|
||||
Parentheses::Preserve,
|
||||
checker.source(),
|
||||
checker.comment_ranges(),
|
||||
checker.tokens(),
|
||||
)?
|
||||
};
|
||||
let has_comments = checker.comment_ranges().intersects(edit.range());
|
||||
|
|
|
|||
|
|
@ -490,8 +490,10 @@ impl<'src> SuppressionParser<'src> {
|
|||
} else if self.cursor.as_str().starts_with("enable") {
|
||||
self.cursor.skip_bytes("enable".len());
|
||||
Ok(SuppressionAction::Enable)
|
||||
} else if self.cursor.as_str().starts_with("noqa") {
|
||||
// file-level "noqa" variant, ignore for now
|
||||
} else if self.cursor.as_str().starts_with("noqa")
|
||||
|| self.cursor.as_str().starts_with("isort")
|
||||
{
|
||||
// alternate suppression variants, ignore for now
|
||||
self.error(ParseErrorKind::NotASuppression)
|
||||
} else {
|
||||
self.error(ParseErrorKind::UnknownAction)
|
||||
|
|
|
|||
|
|
@ -3,13 +3,14 @@ use std::path::Path;
|
|||
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use ruff_python_trivia::{CommentRanges, SimpleTokenKind, SimpleTokenizer, indentation_at_offset};
|
||||
use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer, indentation_at_offset};
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
||||
use crate::name::{Name, QualifiedName, QualifiedNameBuilder};
|
||||
use crate::parenthesize::parenthesized_range;
|
||||
use crate::statement_visitor::StatementVisitor;
|
||||
use crate::token::Tokens;
|
||||
use crate::token::parenthesized_range;
|
||||
use crate::visitor::Visitor;
|
||||
use crate::{
|
||||
self as ast, Arguments, AtomicNodeIndex, CmpOp, DictItem, ExceptHandler, Expr, ExprNoneLiteral,
|
||||
|
|
@ -1474,7 +1475,7 @@ pub fn generate_comparison(
|
|||
ops: &[CmpOp],
|
||||
comparators: &[Expr],
|
||||
parent: AnyNodeRef,
|
||||
comment_ranges: &CommentRanges,
|
||||
tokens: &Tokens,
|
||||
source: &str,
|
||||
) -> String {
|
||||
let start = left.start();
|
||||
|
|
@ -1483,8 +1484,7 @@ pub fn generate_comparison(
|
|||
|
||||
// Add the left side of the comparison.
|
||||
contents.push_str(
|
||||
&source[parenthesized_range(left.into(), parent, comment_ranges, source)
|
||||
.unwrap_or(left.range())],
|
||||
&source[parenthesized_range(left.into(), parent, tokens).unwrap_or(left.range())],
|
||||
);
|
||||
|
||||
for (op, comparator) in ops.iter().zip(comparators) {
|
||||
|
|
@ -1504,7 +1504,7 @@ pub fn generate_comparison(
|
|||
|
||||
// Add the right side of the comparison.
|
||||
contents.push_str(
|
||||
&source[parenthesized_range(comparator.into(), parent, comment_ranges, source)
|
||||
&source[parenthesized_range(comparator.into(), parent, tokens)
|
||||
.unwrap_or(comparator.range())],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ impl Debug for DebugComment<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Pretty-printed debug representation of [`Comments`].
|
||||
/// Pretty-printed debug representation of [`Comments`](super::Comments).
|
||||
pub(crate) struct DebugComments<'a> {
|
||||
comments: &'a CommentsMap<'a>,
|
||||
source_code: SourceCode<'a>,
|
||||
|
|
|
|||
|
|
@ -504,7 +504,7 @@ impl InOrderEntry {
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
struct OutOfOrderEntry {
|
||||
/// Index into the [`MultiMap::out_of_order`] vector at which offset the leading vec is stored.
|
||||
/// Index into the [`MultiMap::out_of_order_parts`] vector at which offset the leading vec is stored.
|
||||
leading_index: usize,
|
||||
_count: Count<OutOfOrderEntry>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ use ruff_python_ast::AnyNodeRef;
|
|||
use std::fmt::{Debug, Formatter};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
/// Used as key into the [`MultiMap`] storing the comments per node by [`Comments`].
|
||||
/// Used as key into the [`MultiMap`](super::MultiMap) storing the comments per node by
|
||||
/// [`Comments`](super::Comments).
|
||||
///
|
||||
/// Implements equality and hashing based on the address of the [`AnyNodeRef`] to get fast and cheap
|
||||
/// hashing/equality comparison.
|
||||
|
|
|
|||
|
|
@ -1974,8 +1974,8 @@ fn handle_unary_op_comment<'a>(
|
|||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// The comment will be attached to the [`Arguments`] node as a dangling comment, to ensure
|
||||
/// that it remains on the same line as open parenthesis.
|
||||
/// The comment will be attached to the [`Arguments`](ast::Arguments) node as a dangling comment, to
|
||||
/// ensure that it remains on the same line as open parenthesis.
|
||||
///
|
||||
/// Similarly, given:
|
||||
/// ```python
|
||||
|
|
@ -1984,8 +1984,8 @@ fn handle_unary_op_comment<'a>(
|
|||
/// ] = ...
|
||||
/// ```
|
||||
///
|
||||
/// The comment will be attached to the [`TypeParams`] node as a dangling comment, to ensure
|
||||
/// that it remains on the same line as open bracket.
|
||||
/// The comment will be attached to the [`TypeParams`](ast::TypeParams) node as a dangling comment,
|
||||
/// to ensure that it remains on the same line as open bracket.
|
||||
fn handle_bracketed_end_of_line_comment<'a>(
|
||||
comment: DecoratedComment<'a>,
|
||||
source: &str,
|
||||
|
|
|
|||
|
|
@ -174,7 +174,8 @@ impl<'ast> SourceOrderVisitor<'ast> for CommentsVisitor<'ast, '_> {
|
|||
|
||||
/// A comment decorated with additional information about its surrounding context in the source document.
|
||||
///
|
||||
/// Used by [`CommentStyle::place_comment`] to determine if this should become a [leading](self#leading-comments), [dangling](self#dangling-comments), or [trailing](self#trailing-comments) comment.
|
||||
/// Used by [`place_comment`] to determine if this should become a [leading](self#leading-comments),
|
||||
/// [dangling](self#dangling-comments), or [trailing](self#trailing-comments) comment.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct DecoratedComment<'a> {
|
||||
enclosing: AnyNodeRef<'a>,
|
||||
|
|
@ -465,7 +466,7 @@ pub(super) enum CommentPlacement<'a> {
|
|||
///
|
||||
/// [`preceding_node`]: DecoratedComment::preceding_node
|
||||
/// [`following_node`]: DecoratedComment::following_node
|
||||
/// [`enclosing_node`]: DecoratedComment::enclosing_node_id
|
||||
/// [`enclosing_node`]: DecoratedComment::enclosing_node
|
||||
/// [trailing comment]: self#trailing-comments
|
||||
/// [leading comment]: self#leading-comments
|
||||
/// [dangling comment]: self#dangling-comments
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ impl InterpolatedStringState {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the interpolated string state is [`NestedInterpolatedElement`].
|
||||
/// Returns `true` if the interpolated string state is [`Self::NestedInterpolatedElement`].
|
||||
pub(crate) fn is_nested(self) -> bool {
|
||||
matches!(self, Self::NestedInterpolatedElement(..))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1095,9 +1095,9 @@ impl OperandIndex {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the index of the operand's right operator. The method always returns an index
|
||||
/// even if the operand has no right operator. Use [`BinaryCallChain::get_operator`] to test if
|
||||
/// the operand has a right operator.
|
||||
/// Returns the index of the operand's right operator. The method always returns an index even
|
||||
/// if the operand has no right operator. Use [`FlatBinaryExpressionSlice::get_operator`] to
|
||||
/// test if the operand has a right operator.
|
||||
fn right_operator(self) -> OperatorIndex {
|
||||
OperatorIndex::new(self.0 + 1)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,18 +56,20 @@ pub(crate) enum Parenthesize {
|
|||
/// Adding parentheses is desired to prevent the comments from wandering.
|
||||
IfRequired,
|
||||
|
||||
/// Same as [`Self::IfBreaks`] except that it uses [`parenthesize_if_expands`] for expressions
|
||||
/// with the layout [`NeedsParentheses::BestFit`] which is used by non-splittable
|
||||
/// expressions like literals, name, and strings.
|
||||
/// Same as [`Self::IfBreaks`] except that it uses
|
||||
/// [`parenthesize_if_expands`](crate::builders::parenthesize_if_expands) for expressions with
|
||||
/// the layout [`OptionalParentheses::BestFit`] which is used by non-splittable expressions like
|
||||
/// literals, name, and strings.
|
||||
///
|
||||
/// Use this layout over `IfBreaks` when there's a sequence of `maybe_parenthesize_expression`
|
||||
/// in a single logical-line and you want to break from right-to-left. Use `IfBreaks` for the
|
||||
/// first expression and `IfBreaksParenthesized` for the rest.
|
||||
IfBreaksParenthesized,
|
||||
|
||||
/// Same as [`Self::IfBreaksParenthesized`] but uses [`parenthesize_if_expands`] for nested
|
||||
/// [`maybe_parenthesized_expression`] calls unlike other layouts that always omit parentheses
|
||||
/// when outer parentheses are present.
|
||||
/// Same as [`Self::IfBreaksParenthesized`] but uses
|
||||
/// [`parenthesize_if_expands`](crate::builders::parenthesize_if_expands) for nested
|
||||
/// [`maybe_parenthesized_expression`](crate::expression::maybe_parenthesize_expression) calls
|
||||
/// unlike other layouts that always omit parentheses when outer parentheses are present.
|
||||
IfBreaksParenthesizedNested,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -214,8 +214,9 @@ impl Format<PyFormatContext<'_>> for MaybeParenthesizePattern<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// This function is very similar to [`can_omit_optional_parentheses`] with the only difference that it is for patterns
|
||||
/// and not expressions.
|
||||
/// This function is very similar to
|
||||
/// [`can_omit_optional_parentheses`](crate::expression::can_omit_optional_parentheses)
|
||||
/// with the only difference that it is for patterns and not expressions.
|
||||
///
|
||||
/// The base idea of the omit optional parentheses layout is to prefer using parentheses of sub-patterns
|
||||
/// when splitting the pattern over introducing new patterns. For example, prefer splitting the sequence pattern in
|
||||
|
|
|
|||
|
|
@ -72,8 +72,9 @@ impl FormatNodeRule<PatternArguments> for FormatPatternArguments {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the pattern (which is the only argument to a [`PatternMatchClass`]) is
|
||||
/// parenthesized. Used to avoid falsely assuming that `x` is parenthesized in cases like:
|
||||
/// Returns `true` if the pattern (which is the only argument to a
|
||||
/// [`PatternMatchClass`](ruff_python_ast::PatternMatchClass)) is parenthesized.
|
||||
/// Used to avoid falsely assuming that `x` is parenthesized in cases like:
|
||||
/// ```python
|
||||
/// case Point2D(x): ...
|
||||
/// ```
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ use crate::{FormatModuleError, PyFormatOptions, format_module_source};
|
|||
///
|
||||
/// The returned formatted range guarantees to cover at least `range` (excluding whitespace), but the range might be larger.
|
||||
/// Some cases in which the returned range is larger than `range` are:
|
||||
/// * The logical lines in `range` use a indentation different from the configured [`IndentStyle`] and [`IndentWidth`].
|
||||
/// * The logical lines in `range` use a indentation different from the configured [`IndentStyle`]
|
||||
/// and [`IndentWidth`](ruff_formatter::IndentWidth).
|
||||
/// * `range` is smaller than a logical lines and the formatter needs to format the entire logical line.
|
||||
/// * `range` falls on a single line body.
|
||||
///
|
||||
|
|
@ -129,16 +130,19 @@ pub fn format_range(
|
|||
/// b) formatting a sub-expression has fewer split points than formatting the entire expressions.
|
||||
///
|
||||
/// ### Possible docstrings
|
||||
/// Strings that are suspected to be docstrings are excluded from the search to format the enclosing suite instead
|
||||
/// so that the formatter's docstring detection in [`FormatSuite`] correctly detects and formats the docstrings.
|
||||
/// Strings that are suspected to be docstrings are excluded from the search to format the enclosing
|
||||
/// suite instead so that the formatter's docstring detection in
|
||||
/// [`FormatSuite`](crate::statement::suite::FormatSuite) correctly detects and formats the
|
||||
/// docstrings.
|
||||
///
|
||||
/// ### Compound statements with a simple statement body
|
||||
/// Don't include simple-statement bodies of compound statements `if True: pass` because the formatter
|
||||
/// must run [`FormatClauseBody`] to determine if the body should be collapsed or not.
|
||||
/// must run `FormatClauseBody` to determine if the body should be collapsed or not.
|
||||
///
|
||||
/// ### Incorrectly indented code
|
||||
/// Code that uses indentations that don't match the configured [`IndentStyle`] and [`IndentWidth`] are excluded from the search,
|
||||
/// because formatting such nodes on their own can lead to indentation mismatch with its sibling nodes.
|
||||
/// Code that uses indentations that don't match the configured [`IndentStyle`] and
|
||||
/// [`IndentWidth`](ruff_formatter::IndentWidth) are excluded from the search, because formatting
|
||||
/// such nodes on their own can lead to indentation mismatch with its sibling nodes.
|
||||
///
|
||||
/// ## Suppression comments
|
||||
/// The search ends when `range` falls into a suppressed range because there's nothing to format. It also avoids that the
|
||||
|
|
@ -279,13 +283,15 @@ enum EnclosingNode<'a> {
|
|||
///
|
||||
/// ## Compound statements with simple statement bodies
|
||||
/// Similar to [`find_enclosing_node`], exclude the compound statement's body if it is a simple statement (not a suite) from the search to format the entire clause header
|
||||
/// with the body. This ensures that the formatter runs [`FormatClauseBody`] that determines if the body should be indented.s
|
||||
/// with the body. This ensures that the formatter runs `FormatClauseBody` that determines if the body should be indented.
|
||||
///
|
||||
/// ## Non-standard indentation
|
||||
/// Node's that use an indentation that doesn't match the configured [`IndentStyle`] and [`IndentWidth`] are excluded from the search.
|
||||
/// This is because the formatter always uses the configured [`IndentStyle`] and [`IndentWidth`], resulting in the
|
||||
/// formatted nodes using a different indentation than the unformatted sibling nodes. This would be tolerable
|
||||
/// in non whitespace sensitive languages like JavaScript but results in lexical errors in Python.
|
||||
/// Nodes that use an indentation that doesn't match the configured [`IndentStyle`] and
|
||||
/// [`IndentWidth`](ruff_formatter::IndentWidth) are excluded from the search. This is because the
|
||||
/// formatter always uses the configured [`IndentStyle`] and
|
||||
/// [`IndentWidth`](ruff_formatter::IndentWidth), resulting in the formatted nodes using a different
|
||||
/// indentation than the unformatted sibling nodes. This would be tolerable in non whitespace
|
||||
/// sensitive languages like JavaScript but results in lexical errors in Python.
|
||||
///
|
||||
/// ## Implementation
|
||||
/// It would probably be possible to merge this visitor with [`FindEnclosingNode`] but they are separate because
|
||||
|
|
@ -713,9 +719,11 @@ impl Format<PyFormatContext<'_>> for FormatEnclosingNode<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Computes the level of indentation for `indentation` when using the configured [`IndentStyle`] and [`IndentWidth`].
|
||||
/// Computes the level of indentation for `indentation` when using the configured [`IndentStyle`]
|
||||
/// and [`IndentWidth`](ruff_formatter::IndentWidth).
|
||||
///
|
||||
/// Returns `None` if the indentation doesn't conform to the configured [`IndentStyle`] and [`IndentWidth`].
|
||||
/// Returns `None` if the indentation doesn't conform to the configured [`IndentStyle`] and
|
||||
/// [`IndentWidth`](ruff_formatter::IndentWidth).
|
||||
///
|
||||
/// # Panics
|
||||
/// If `offset` is outside of `source`.
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ impl Format<PyFormatContext<'_>> for FormatTargetWithEqualOperator<'_> {
|
|||
/// No parentheses are added for `short` because it fits into the configured line length, regardless of whether
|
||||
/// the comment exceeds the line width or not.
|
||||
///
|
||||
/// This logic isn't implemented in [`place_comment`] by associating trailing statement comments to the expression because
|
||||
/// This logic isn't implemented in `place_comment` by associating trailing statement comments to the expression because
|
||||
/// doing so breaks the suite empty lines formatting that relies on trailing comments to be stored on the statement.
|
||||
#[derive(Debug)]
|
||||
pub(super) enum FormatStatementsLastExpression<'a> {
|
||||
|
|
@ -202,8 +202,8 @@ pub(super) enum FormatStatementsLastExpression<'a> {
|
|||
/// ] = some_long_value
|
||||
/// ```
|
||||
///
|
||||
/// This layout is preferred over [`RightToLeft`] if the left is unsplittable (single keyword like `return` or a Name)
|
||||
/// because it has better performance characteristics.
|
||||
/// This layout is preferred over [`Self::RightToLeft`] if the left is unsplittable (single
|
||||
/// keyword like `return` or a Name) because it has better performance characteristics.
|
||||
LeftToRight {
|
||||
/// The right side of an assignment or the value returned in a return statement.
|
||||
value: &'a Expr,
|
||||
|
|
@ -1083,11 +1083,10 @@ impl Format<PyFormatContext<'_>> for InterpolatedString<'_> {
|
|||
/// For legibility, we discuss only the case of f-strings below, but the
|
||||
/// same comments apply to t-strings.
|
||||
///
|
||||
/// This is just a wrapper around [`FormatFString`] while considering a special
|
||||
/// case when the f-string is at an assignment statement's value position.
|
||||
/// This is necessary to prevent an instability where an f-string contains a
|
||||
/// multiline expression and the f-string fits on the line, but only when it's
|
||||
/// surrounded by parentheses.
|
||||
/// This is just a wrapper around [`FormatFString`](crate::other::f_string::FormatFString) while
|
||||
/// considering a special case when the f-string is at an assignment statement's value position.
|
||||
/// This is necessary to prevent an instability where an f-string contains a multiline expression
|
||||
/// and the f-string fits on the line, but only when it's surrounded by parentheses.
|
||||
///
|
||||
/// ```python
|
||||
/// aaaaaaaaaaaaaaaaaa = f"testeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee{
|
||||
|
|
|
|||
|
|
@ -177,8 +177,10 @@ enum WithItemsLayout<'a> {
|
|||
/// ...
|
||||
/// ```
|
||||
///
|
||||
/// In this case, use [`maybe_parenthesize_expression`] to format the context expression
|
||||
/// to get the exact same formatting as when formatting an expression in any other clause header.
|
||||
/// In this case, use
|
||||
/// [`maybe_parenthesize_expression`](crate::expression::maybe_parenthesize_expression) to
|
||||
/// format the context expression to get the exact same formatting as when formatting an
|
||||
/// expression in any other clause header.
|
||||
///
|
||||
/// Only used for Python 3.9+
|
||||
///
|
||||
|
|
|
|||
|
|
@ -783,7 +783,7 @@ enum CodeExampleKind<'src> {
|
|||
///
|
||||
/// Documentation describing doctests and how they're recognized can be
|
||||
/// found as part of the Python standard library:
|
||||
/// https://docs.python.org/3/library/doctest.html.
|
||||
/// <https://docs.python.org/3/library/doctest.html>.
|
||||
///
|
||||
/// (You'll likely need to read the [regex matching] used internally by the
|
||||
/// doctest module to determine more precisely how it works.)
|
||||
|
|
|
|||
|
|
@ -38,8 +38,9 @@ impl<'a, 'src> StringNormalizer<'a, 'src> {
|
|||
/// it can't because the string contains the preferred quotes OR
|
||||
/// it leads to more escaping.
|
||||
///
|
||||
/// Note: If you add more cases here where we return `QuoteStyle::Preserve`,
|
||||
/// make sure to also add them to [`FormatImplicitConcatenatedStringFlat::new`].
|
||||
/// Note: If you add more cases here where we return `QuoteStyle::Preserve`, make sure to also
|
||||
/// add them to
|
||||
/// [`FormatImplicitConcatenatedStringFlat::new`](crate::string::implicit::FormatImplicitConcatenatedStringFlat::new).
|
||||
pub(super) fn preferred_quote_style(&self, string: StringLikePart) -> QuoteStyle {
|
||||
let preferred_quote_style = self
|
||||
.preferred_quote_style
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use crate::prelude::*;
|
|||
#[derive(Default)]
|
||||
pub struct FormatTypeParams;
|
||||
|
||||
/// Formats a sequence of [`TypeParam`] nodes.
|
||||
/// Formats a sequence of [`TypeParam`](ruff_python_ast::TypeParam) nodes.
|
||||
impl FormatNodeRule<TypeParams> for FormatTypeParams {
|
||||
fn fmt_fields(&self, item: &TypeParams, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
// A dangling comment indicates a comment on the same line as the opening bracket, e.g.:
|
||||
|
|
|
|||
|
|
@ -679,8 +679,9 @@ impl Indentation {
|
|||
|
||||
/// Returns `true` for a space or tab character.
|
||||
///
|
||||
/// This is different than [`is_python_whitespace`] in that it returns `false` for a form feed character.
|
||||
/// Form feed characters are excluded because they should be preserved in the suppressed output.
|
||||
/// This is different than [`is_python_whitespace`](ruff_python_trivia::is_python_whitespace) in
|
||||
/// that it returns `false` for a form feed character. Form feed characters are excluded because
|
||||
/// they should be preserved in the suppressed output.
|
||||
const fn is_indent_whitespace(c: char) -> bool {
|
||||
matches!(c, ' ' | '\t')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ ruff_source_file = { workspace = true }
|
|||
|
||||
anyhow = { workspace = true }
|
||||
insta = { workspace = true, features = ["glob"] }
|
||||
itertools = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
walkdir = { workspace = true }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
# Regression test for https://github.com/astral-sh/ty/issues/1828
|
||||
(c: int = 1,f"""{d=[
|
||||
def a(
|
||||
class A:
|
||||
pass
|
||||
|
|
@ -67,26 +67,59 @@ impl<'src> TokenSource<'src> {
|
|||
///
|
||||
/// [`re_lex_logical_token`]: Lexer::re_lex_logical_token
|
||||
pub(crate) fn re_lex_logical_token(&mut self) {
|
||||
let mut non_logical_newline_start = None;
|
||||
for token in self.tokens.iter().rev() {
|
||||
let mut non_logical_newline = None;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
let last_non_trivia_end_before = {
|
||||
self.tokens
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|tok| !tok.kind().is_trivia())
|
||||
.map(ruff_text_size::Ranged::end)
|
||||
};
|
||||
|
||||
for (index, token) in self.tokens.iter().enumerate().rev() {
|
||||
match token.kind() {
|
||||
TokenKind::NonLogicalNewline => {
|
||||
non_logical_newline_start = Some(token.start());
|
||||
non_logical_newline = Some((index, token.start()));
|
||||
}
|
||||
TokenKind::Comment => continue,
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
|
||||
if self.lexer.re_lex_logical_token(non_logical_newline_start) {
|
||||
let current_start = self.current_range().start();
|
||||
while self
|
||||
.tokens
|
||||
.last()
|
||||
.is_some_and(|last| last.start() >= current_start)
|
||||
{
|
||||
self.tokens.pop();
|
||||
}
|
||||
if !self
|
||||
.lexer
|
||||
.re_lex_logical_token(non_logical_newline.map(|(_, start)| start))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let non_logical_line_index = non_logical_newline
|
||||
.expect(
|
||||
"`re_lex_logical_token` should only return `true` if `non_logical_line` is `Some`",
|
||||
)
|
||||
.0;
|
||||
|
||||
// Trim the already bumped logical line token (and comments coming after it) as it might now have become a logical line token
|
||||
self.tokens.truncate(non_logical_line_index);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
let last_non_trivia_end_now = {
|
||||
self.tokens
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|tok| !tok.kind().is_trivia())
|
||||
.map(ruff_text_size::Ranged::end)
|
||||
};
|
||||
|
||||
assert_eq!(last_non_trivia_end_before, last_non_trivia_end_now);
|
||||
}
|
||||
|
||||
// Ensure `current` is positioned at a non-trivia token.
|
||||
if self.current_kind().is_trivia() {
|
||||
self.bump(self.current_kind());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,15 +4,16 @@ use std::fmt::{Formatter, Write};
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use itertools::Itertools;
|
||||
use ruff_annotate_snippets::{Level, Renderer, Snippet};
|
||||
use ruff_python_ast::token::Token;
|
||||
use ruff_python_ast::token::{Token, Tokens};
|
||||
use ruff_python_ast::visitor::Visitor;
|
||||
use ruff_python_ast::visitor::source_order::{SourceOrderVisitor, TraversalSignal, walk_module};
|
||||
use ruff_python_ast::{self as ast, AnyNodeRef, Mod, PythonVersion};
|
||||
use ruff_python_parser::semantic_errors::{
|
||||
SemanticSyntaxChecker, SemanticSyntaxContext, SemanticSyntaxError,
|
||||
};
|
||||
use ruff_python_parser::{Mode, ParseErrorType, ParseOptions, parse_unchecked};
|
||||
use ruff_python_parser::{Mode, ParseErrorType, ParseOptions, Parsed, parse_unchecked};
|
||||
use ruff_source_file::{LineIndex, OneIndexed, SourceCode};
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
||||
|
|
@ -81,7 +82,7 @@ fn test_valid_syntax(input_path: &Path) {
|
|||
}
|
||||
|
||||
validate_tokens(parsed.tokens(), source.text_len(), input_path);
|
||||
validate_ast(parsed.syntax(), source.text_len(), input_path);
|
||||
validate_ast(&parsed, source.text_len(), input_path);
|
||||
|
||||
let mut output = String::new();
|
||||
writeln!(&mut output, "## AST").unwrap();
|
||||
|
|
@ -139,7 +140,7 @@ fn test_invalid_syntax(input_path: &Path) {
|
|||
let parsed = parse_unchecked(&source, options.clone());
|
||||
|
||||
validate_tokens(parsed.tokens(), source.text_len(), input_path);
|
||||
validate_ast(parsed.syntax(), source.text_len(), input_path);
|
||||
validate_ast(&parsed, source.text_len(), input_path);
|
||||
|
||||
let mut output = String::new();
|
||||
writeln!(&mut output, "## AST").unwrap();
|
||||
|
|
@ -402,12 +403,16 @@ Tokens: {tokens:#?}
|
|||
/// * the range of the parent node fully encloses all its child nodes
|
||||
/// * the ranges are strictly increasing when traversing the nodes in pre-order.
|
||||
/// * all ranges are within the length of the source code.
|
||||
fn validate_ast(root: &Mod, source_len: TextSize, test_path: &Path) {
|
||||
walk_module(&mut ValidateAstVisitor::new(source_len, test_path), root);
|
||||
fn validate_ast(parsed: &Parsed<Mod>, source_len: TextSize, test_path: &Path) {
|
||||
walk_module(
|
||||
&mut ValidateAstVisitor::new(parsed.tokens(), source_len, test_path),
|
||||
parsed.syntax(),
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ValidateAstVisitor<'a> {
|
||||
tokens: std::iter::Peekable<std::slice::Iter<'a, Token>>,
|
||||
parents: Vec<AnyNodeRef<'a>>,
|
||||
previous: Option<AnyNodeRef<'a>>,
|
||||
source_length: TextSize,
|
||||
|
|
@ -415,8 +420,9 @@ struct ValidateAstVisitor<'a> {
|
|||
}
|
||||
|
||||
impl<'a> ValidateAstVisitor<'a> {
|
||||
fn new(source_length: TextSize, test_path: &'a Path) -> Self {
|
||||
fn new(tokens: &'a Tokens, source_length: TextSize, test_path: &'a Path) -> Self {
|
||||
Self {
|
||||
tokens: tokens.iter().peekable(),
|
||||
parents: Vec::new(),
|
||||
previous: None,
|
||||
source_length,
|
||||
|
|
@ -425,6 +431,47 @@ impl<'a> ValidateAstVisitor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateAstVisitor<'_> {
|
||||
/// Check that the node's start doesn't fall within a token.
|
||||
/// Called in `enter_node` before visiting children.
|
||||
fn assert_start_boundary(&mut self, node: AnyNodeRef<'_>) {
|
||||
// Skip tokens that end at or before the node starts.
|
||||
self.tokens
|
||||
.peeking_take_while(|t| t.end() <= node.start())
|
||||
.last();
|
||||
|
||||
if let Some(next) = self.tokens.peek() {
|
||||
// At this point, next_token.end() > node.start()
|
||||
assert!(
|
||||
next.start() >= node.start(),
|
||||
"{path}: The start of the node falls within a token.\nNode: {node:#?}\n\nToken: {next:#?}\n\nRoot: {root:#?}",
|
||||
path = self.test_path.display(),
|
||||
root = self.parents.first()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that the node's end doesn't fall within a token.
|
||||
/// Called in `leave_node` after visiting children, so all tokens
|
||||
/// within the node have been consumed.
|
||||
fn assert_end_boundary(&mut self, node: AnyNodeRef<'_>) {
|
||||
// Skip tokens that end at or before the node ends.
|
||||
self.tokens
|
||||
.peeking_take_while(|t| t.end() <= node.end())
|
||||
.last();
|
||||
|
||||
if let Some(next) = self.tokens.peek() {
|
||||
// At this point, `next_token.end() > node.end()`
|
||||
assert!(
|
||||
next.start() >= node.end(),
|
||||
"{path}: The end of the node falls within a token.\nNode: {node:#?}\n\nToken: {next:#?}\n\nRoot: {root:#?}",
|
||||
path = self.test_path.display(),
|
||||
root = self.parents.first()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> SourceOrderVisitor<'ast> for ValidateAstVisitor<'ast> {
|
||||
fn enter_node(&mut self, node: AnyNodeRef<'ast>) -> TraversalSignal {
|
||||
assert!(
|
||||
|
|
@ -452,12 +499,16 @@ impl<'ast> SourceOrderVisitor<'ast> for ValidateAstVisitor<'ast> {
|
|||
);
|
||||
}
|
||||
|
||||
self.assert_start_boundary(node);
|
||||
|
||||
self.parents.push(node);
|
||||
|
||||
TraversalSignal::Traverse
|
||||
}
|
||||
|
||||
fn leave_node(&mut self, node: AnyNodeRef<'ast>) {
|
||||
self.assert_end_boundary(node);
|
||||
|
||||
self.parents.pop().expect("Expected tree to be balanced");
|
||||
|
||||
self.previous = Some(node);
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ Module(
|
|||
test: Call(
|
||||
ExprCall {
|
||||
node_index: NodeIndex(None),
|
||||
range: 456..472,
|
||||
range: 456..471,
|
||||
func: Name(
|
||||
ExprName {
|
||||
node_index: NodeIndex(None),
|
||||
|
|
@ -306,7 +306,7 @@ Module(
|
|||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 460..472,
|
||||
range: 460..471,
|
||||
node_index: NodeIndex(None),
|
||||
args: [
|
||||
Name(
|
||||
|
|
@ -581,7 +581,7 @@ Module(
|
|||
test: Call(
|
||||
ExprCall {
|
||||
node_index: NodeIndex(None),
|
||||
range: 890..906,
|
||||
range: 890..905,
|
||||
func: Name(
|
||||
ExprName {
|
||||
node_index: NodeIndex(None),
|
||||
|
|
@ -591,7 +591,7 @@ Module(
|
|||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 894..906,
|
||||
range: 894..905,
|
||||
node_index: NodeIndex(None),
|
||||
args: [
|
||||
FString(
|
||||
|
|
@ -832,7 +832,16 @@ Module(
|
|||
|
|
||||
28 | # The lexer is nested with multiple levels of parentheses
|
||||
29 | if call(foo, [a, b
|
||||
| ^ Syntax Error: Expected `]`, found NonLogicalNewline
|
||||
30 | def bar():
|
||||
| ^^^ Syntax Error: Expected `]`, found `def`
|
||||
31 | pass
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
28 | # The lexer is nested with multiple levels of parentheses
|
||||
29 | if call(foo, [a, b
|
||||
| ^ Syntax Error: Expected `)`, found newline
|
||||
30 | def bar():
|
||||
31 | pass
|
||||
|
|
||||
|
|
@ -857,11 +866,10 @@ Module(
|
|||
|
||||
|
||||
|
|
||||
41 | # test is to make sure it emits a `NonLogicalNewline` token after `b`.
|
||||
42 | if call(foo, [a,
|
||||
43 | b
|
||||
| ^ Syntax Error: Expected `]`, found NonLogicalNewline
|
||||
44 | )
|
||||
| ^ Syntax Error: Expected `]`, found `)`
|
||||
45 | def bar():
|
||||
46 | pass
|
||||
|
|
||||
|
|
@ -898,7 +906,7 @@ Module(
|
|||
|
|
||||
49 | # F-strings uses normal list parsing, so test those as well
|
||||
50 | if call(f"hello {x
|
||||
| ^ Syntax Error: Expected FStringEnd, found NonLogicalNewline
|
||||
| ^ Syntax Error: Expected `)`, found newline
|
||||
51 | def bar():
|
||||
52 | pass
|
||||
|
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ Module(
|
|||
test: Call(
|
||||
ExprCall {
|
||||
node_index: NodeIndex(None),
|
||||
range: 3..19,
|
||||
range: 3..18,
|
||||
func: Name(
|
||||
ExprName {
|
||||
node_index: NodeIndex(None),
|
||||
|
|
@ -27,7 +27,7 @@ Module(
|
|||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 7..19,
|
||||
range: 7..18,
|
||||
node_index: NodeIndex(None),
|
||||
args: [
|
||||
Name(
|
||||
|
|
@ -113,5 +113,11 @@ Module(
|
|||
|
||||
|
|
||||
1 | if call(foo, [a, b
def bar():
pass
|
||||
| ^ Syntax Error: Expected `]`, found NonLogicalNewline
|
||||
| ^^^ Syntax Error: Expected `]`, found `def`
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
1 | if call(foo, [a, b
def bar():
pass
|
||||
| ^ Syntax Error: Expected `)`, found newline
|
||||
|
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ Module(
|
|||
test: Call(
|
||||
ExprCall {
|
||||
node_index: NodeIndex(None),
|
||||
range: 3..20,
|
||||
range: 3..18,
|
||||
func: Name(
|
||||
ExprName {
|
||||
node_index: NodeIndex(None),
|
||||
|
|
@ -27,7 +27,7 @@ Module(
|
|||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 7..20,
|
||||
range: 7..18,
|
||||
node_index: NodeIndex(None),
|
||||
args: [
|
||||
Name(
|
||||
|
|
@ -113,7 +113,15 @@ Module(
|
|||
|
||||
|
|
||||
1 | if call(foo, [a, b
|
||||
| ^ Syntax Error: Expected `]`, found NonLogicalNewline
|
||||
2 | def bar():
|
||||
| ^^^ Syntax Error: Expected `]`, found `def`
|
||||
3 | pass
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
1 | if call(foo, [a, b
|
||||
| ^ Syntax Error: Expected `)`, found newline
|
||||
2 | def bar():
|
||||
3 | pass
|
||||
|
|
||||
|
|
|
|||
|
|
@ -0,0 +1,227 @@
|
|||
---
|
||||
source: crates/ruff_python_parser/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_parser/resources/invalid/re_lexing/ty_1828.py
|
||||
---
|
||||
## AST
|
||||
|
||||
```
|
||||
Module(
|
||||
ModModule {
|
||||
node_index: NodeIndex(None),
|
||||
range: 0..112,
|
||||
body: [
|
||||
AnnAssign(
|
||||
StmtAnnAssign {
|
||||
node_index: NodeIndex(None),
|
||||
range: 66..93,
|
||||
target: Name(
|
||||
ExprName {
|
||||
node_index: NodeIndex(None),
|
||||
range: 67..68,
|
||||
id: Name("c"),
|
||||
ctx: Store,
|
||||
},
|
||||
),
|
||||
annotation: Name(
|
||||
ExprName {
|
||||
node_index: NodeIndex(None),
|
||||
range: 70..73,
|
||||
id: Name("int"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
value: Some(
|
||||
Tuple(
|
||||
ExprTuple {
|
||||
node_index: NodeIndex(None),
|
||||
range: 76..93,
|
||||
elts: [
|
||||
NumberLiteral(
|
||||
ExprNumberLiteral {
|
||||
node_index: NodeIndex(None),
|
||||
range: 76..77,
|
||||
value: Int(
|
||||
1,
|
||||
),
|
||||
},
|
||||
),
|
||||
Subscript(
|
||||
ExprSubscript {
|
||||
node_index: NodeIndex(None),
|
||||
range: 78..90,
|
||||
value: FString(
|
||||
ExprFString {
|
||||
node_index: NodeIndex(None),
|
||||
range: 78..85,
|
||||
value: FStringValue {
|
||||
inner: Single(
|
||||
FString(
|
||||
FString {
|
||||
range: 78..85,
|
||||
node_index: NodeIndex(None),
|
||||
elements: [
|
||||
Interpolation(
|
||||
InterpolatedElement {
|
||||
range: 82..85,
|
||||
node_index: NodeIndex(None),
|
||||
expression: Name(
|
||||
ExprName {
|
||||
node_index: NodeIndex(None),
|
||||
range: 83..84,
|
||||
id: Name("d"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
debug_text: Some(
|
||||
DebugText {
|
||||
leading: "",
|
||||
trailing: "=",
|
||||
},
|
||||
),
|
||||
conversion: None,
|
||||
format_spec: None,
|
||||
},
|
||||
),
|
||||
],
|
||||
flags: FStringFlags {
|
||||
quote_style: Double,
|
||||
prefix: Regular,
|
||||
triple_quoted: true,
|
||||
unclosed: true,
|
||||
},
|
||||
},
|
||||
),
|
||||
),
|
||||
},
|
||||
},
|
||||
),
|
||||
slice: Slice(
|
||||
ExprSlice {
|
||||
node_index: NodeIndex(None),
|
||||
range: 87..90,
|
||||
lower: None,
|
||||
upper: Some(
|
||||
Name(
|
||||
ExprName {
|
||||
node_index: NodeIndex(None),
|
||||
range: 87..90,
|
||||
id: Name("def"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
),
|
||||
step: None,
|
||||
},
|
||||
),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
Call(
|
||||
ExprCall {
|
||||
node_index: NodeIndex(None),
|
||||
range: 91..93,
|
||||
func: Name(
|
||||
ExprName {
|
||||
node_index: NodeIndex(None),
|
||||
range: 91..92,
|
||||
id: Name("a"),
|
||||
ctx: Load,
|
||||
},
|
||||
),
|
||||
arguments: Arguments {
|
||||
range: 92..93,
|
||||
node_index: NodeIndex(None),
|
||||
args: [],
|
||||
keywords: [],
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
ctx: Load,
|
||||
parenthesized: false,
|
||||
},
|
||||
),
|
||||
),
|
||||
simple: false,
|
||||
},
|
||||
),
|
||||
],
|
||||
},
|
||||
)
|
||||
```
|
||||
## Errors
|
||||
|
||||
|
|
||||
1 | # Regression test for https://github.com/astral-sh/ty/issues/1828
|
||||
2 | (c: int = 1,f"""{d=[
|
||||
| ^ Syntax Error: Expected `)`, found `:`
|
||||
3 | def a(
|
||||
4 | class A:
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
1 | # Regression test for https://github.com/astral-sh/ty/issues/1828
|
||||
2 | (c: int = 1,f"""{d=[
|
||||
| ^ Syntax Error: f-string: expecting `}`
|
||||
3 | def a(
|
||||
4 | class A:
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
1 | # Regression test for https://github.com/astral-sh/ty/issues/1828
|
||||
2 | (c: int = 1,f"""{d=[
|
||||
3 | def a(
|
||||
| ^^^ Syntax Error: Expected `:`, found `def`
|
||||
4 | class A:
|
||||
5 | pass
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
1 | # Regression test for https://github.com/astral-sh/ty/issues/1828
|
||||
2 | (c: int = 1,f"""{d=[
|
||||
3 | def a(
|
||||
| ^ Syntax Error: Expected `]`, found name
|
||||
4 | class A:
|
||||
5 | pass
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
1 | # Regression test for https://github.com/astral-sh/ty/issues/1828
|
||||
2 | (c: int = 1,f"""{d=[
|
||||
3 | def a(
|
||||
| _______^
|
||||
4 | | class A:
|
||||
5 | | pass
|
||||
| |_________^ Syntax Error: f-string: unterminated triple-quoted string
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
2 | (c: int = 1,f"""{d=[
|
||||
3 | def a(
|
||||
4 | class A:
|
||||
| ^^^^^ Syntax Error: Expected `)`, found `class`
|
||||
5 | pass
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
1 | # Regression test for https://github.com/astral-sh/ty/issues/1828
|
||||
2 | (c: int = 1,f"""{d=[
|
||||
3 | def a(
|
||||
| _______^
|
||||
4 | | class A:
|
||||
5 | | pass
|
||||
| |_________^ Syntax Error: Expected a statement
|
||||
|
|
||||
|
||||
|
||||
|
|
||||
4 | class A:
|
||||
5 | pass
|
||||
| ^ Syntax Error: unexpected EOF while parsing
|
||||
|
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
# ty
|
||||
|
||||
ty is an extremely fast type checker.
|
||||
Currently, it is a work-in-progress and not ready for production use.
|
||||
|
||||
The Rust code for ty lives in this repository; see [CONTRIBUTING.md](CONTRIBUTING.md) for more
|
||||
information on contributing to ty.
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ def test(): -> "int":
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20call-non-callable" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L135" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L134" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ Calling a non-callable object will raise a `TypeError` at runtime.
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20conflicting-argument-forms" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L179" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L178" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ f(int) # error
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20conflicting-declarations" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L205" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L204" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ a = 1
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20conflicting-metaclass" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L230" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L229" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -158,7 +158,7 @@ class C(A, B): ...
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20cyclic-class-definition" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L256" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L255" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -190,7 +190,7 @@ class B(A): ...
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Preview (since <a href="https://github.com/astral-sh/ty/releases/tag/1.0.0">1.0.0</a>) ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20cyclic-type-alias-definition" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L282" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L281" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -218,7 +218,7 @@ type B = A
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20duplicate-base" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L343" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L342" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -245,7 +245,7 @@ class B(A, A): ...
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.12">0.0.1-alpha.12</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20duplicate-kw-only" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L364" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L363" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -357,7 +357,7 @@ def test(): -> "Literal[5]":
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20inconsistent-mro" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L590" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L589" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -387,7 +387,7 @@ class C(A, B): ...
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20index-out-of-bounds" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L614" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L613" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -413,7 +413,7 @@ t[3] # IndexError: tuple index out of range
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.12">0.0.1-alpha.12</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20instance-layout-conflict" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L396" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L395" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -502,7 +502,7 @@ an atypical memory layout.
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-argument-type" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L668" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L667" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -529,7 +529,7 @@ func("foo") # error: [invalid-argument-type]
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-assignment" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L708" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L707" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -557,7 +557,7 @@ a: int = ''
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-attribute-access" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1998" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1997" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -591,7 +591,7 @@ C.instance_var = 3 # error: Cannot assign to instance variable
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.19">0.0.1-alpha.19</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-await" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L730" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L729" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -627,7 +627,7 @@ asyncio.run(main())
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-base" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L760" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L759" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -651,7 +651,7 @@ class A(42): ... # error: [invalid-base]
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-context-manager" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L811" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L810" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -678,7 +678,7 @@ with 1:
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-declaration" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L832" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L831" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -707,7 +707,7 @@ a: str
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-exception-caught" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L855" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L854" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -751,7 +751,7 @@ except ZeroDivisionError:
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.28">0.0.1-alpha.28</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-explicit-override" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1668" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1667" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -793,7 +793,7 @@ class D(A):
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-generic-class" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L891" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L890" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -826,7 +826,7 @@ class C[U](Generic[T]): ...
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.17">0.0.1-alpha.17</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-key" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L635" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L634" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -865,7 +865,7 @@ carol = Person(name="Carol", age=25) # typo!
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-legacy-type-variable" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L917" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L916" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -900,7 +900,7 @@ def f(t: TypeVar("U")): ...
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-metaclass" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1014" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1013" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -934,7 +934,7 @@ class B(metaclass=f): ...
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.20">0.0.1-alpha.20</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-method-override" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2126" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2125" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1041,7 +1041,7 @@ Correct use of `@override` is enforced by ty's `invalid-explicit-override` rule.
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.19">0.0.1-alpha.19</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-named-tuple" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L542" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L541" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1095,7 +1095,7 @@ AttributeError: Cannot overwrite NamedTuple attribute _asdict
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Preview (since <a href="https://github.com/astral-sh/ty/releases/tag/1.0.0">1.0.0</a>) ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-newtype" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L990" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L989" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1125,7 +1125,7 @@ Baz = NewType("Baz", int | str) # error: invalid base for `typing.NewType`
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-overload" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1041" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1040" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1175,7 +1175,7 @@ def foo(x: int) -> int: ...
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-parameter-default" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1140" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1139" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1201,7 +1201,7 @@ def f(a: int = ''): ...
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-paramspec" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L945" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L944" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1232,7 +1232,7 @@ P2 = ParamSpec("S2") # error: ParamSpec name must match the variable it's assig
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-protocol" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L478" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L477" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1266,7 +1266,7 @@ TypeError: Protocols can only inherit from other protocols, got <class 'int'>
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-raise" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1160" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1159" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1315,7 +1315,7 @@ def g():
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-return-type" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L689" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L688" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1340,7 +1340,7 @@ def func() -> int:
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-super-argument" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1203" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1202" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1398,7 +1398,7 @@ TODO #14889
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.6">0.0.1-alpha.6</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-alias-type" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L969" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L968" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1425,7 +1425,7 @@ NewAlias = TypeAliasType(get_name(), int) # error: TypeAliasType name mus
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.29">0.0.1-alpha.29</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-arguments" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1435" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1434" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1472,7 +1472,7 @@ Bar[int] # error: too few arguments
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-checking-constant" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1242" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1241" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1502,7 +1502,7 @@ TYPE_CHECKING = ''
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-form" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1266" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1265" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1532,7 +1532,7 @@ b: Annotated[int] # `Annotated` expects at least two arguments
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.11">0.0.1-alpha.11</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-guard-call" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1318" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1317" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1566,7 +1566,7 @@ f(10) # Error
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.11">0.0.1-alpha.11</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-guard-definition" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1290" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1289" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1600,7 +1600,7 @@ class C:
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20invalid-type-variable-constraints" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1346" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1345" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1635,7 +1635,7 @@ T = TypeVar('T', bound=str) # valid bound TypeVar
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20missing-argument" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1375" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1374" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1660,7 +1660,7 @@ func() # TypeError: func() missing 1 required positional argument: 'x'
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.20">0.0.1-alpha.20</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20missing-typed-dict-key" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2099" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2098" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1693,7 +1693,7 @@ alice["age"] # KeyError
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20no-matching-overload" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1394" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1393" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1722,7 +1722,7 @@ func("string") # error: [no-matching-overload]
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20non-subscriptable" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1417" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1416" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1746,7 +1746,7 @@ Subscripting an object that does not support it will raise a `TypeError` at runt
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20not-iterable" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1476" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1475" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1772,7 +1772,7 @@ for i in 34: # TypeError: 'int' object is not iterable
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.29">0.0.1-alpha.29</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20override-of-final-method" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1641" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1640" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1805,7 +1805,7 @@ class B(A):
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20parameter-already-assigned" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1527" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1526" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1832,7 +1832,7 @@ f(1, x=2) # Error raised here
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.22">0.0.1-alpha.22</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20positional-only-parameter-as-kwarg" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1852" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1851" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1890,7 +1890,7 @@ def test(): -> "int":
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20static-assert-error" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1974" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1973" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1920,7 +1920,7 @@ static_assert(int(2.0 * 3.0) == 6) # error: does not have a statically known tr
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20subclass-of-final-class" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1618" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1617" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1949,7 +1949,7 @@ class B(A): ... # Error raised here
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Preview (since <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.30">0.0.1-alpha.30</a>) ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20super-call-in-named-tuple-method" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1786" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1785" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -1983,7 +1983,7 @@ class F(NamedTuple):
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20too-many-positional-arguments" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1726" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1725" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2010,7 +2010,7 @@ f("foo") # Error raised here
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20type-assertion-failure" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1704" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1703" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2038,7 +2038,7 @@ def _(x: int):
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unavailable-implicit-super-arguments" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1747" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1746" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2084,7 +2084,7 @@ class A:
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unknown-argument" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1831" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1830" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2111,7 +2111,7 @@ f(x=1, y=2) # Error raised here
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-attribute" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1873" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1872" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2139,7 +2139,7 @@ A().foo # AttributeError: 'A' object has no attribute 'foo'
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-import" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1895" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1894" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2164,7 +2164,7 @@ import foo # ModuleNotFoundError: No module named 'foo'
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-reference" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1914" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1913" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2189,7 +2189,7 @@ print(x) # NameError: name 'x' is not defined
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-bool-conversion" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1496" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1495" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2226,7 +2226,7 @@ b1 < b2 < b1 # exception raised here
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-operator" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1933" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1932" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2254,7 +2254,7 @@ A() + A() # TypeError: unsupported operand type(s) for +: 'A' and 'A'
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20zero-stepsize-in-slice" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1955" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1954" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2279,7 +2279,7 @@ l[1:10:0] # ValueError: slice step cannot be zero
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.20">0.0.1-alpha.20</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20ambiguous-protocol-member" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L507" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L506" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2320,7 +2320,7 @@ class SubProto(BaseProto, Protocol):
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.16">0.0.1-alpha.16</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20deprecated" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L322" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L321" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2408,7 +2408,7 @@ a = 20 / 0 # type: ignore
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.22">0.0.1-alpha.22</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-missing-attribute" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1548" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1547" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2436,7 +2436,7 @@ A.c # AttributeError: type object 'A' has no attribute 'c'
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.22">0.0.1-alpha.22</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-missing-implicit-call" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L153" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L152" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2468,7 +2468,7 @@ A()[0] # TypeError: 'A' object is not subscriptable
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.22">0.0.1-alpha.22</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-missing-import" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1570" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1569" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2500,7 +2500,7 @@ from module import a # ImportError: cannot import name 'a' from 'module'
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20redundant-cast" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2026" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2025" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2527,7 +2527,7 @@ cast(int, f()) # Redundant
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20undefined-reveal" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1813" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1812" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2551,7 +2551,7 @@ reveal_type(1) # NameError: name 'reveal_type' is not defined
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.15">0.0.1-alpha.15</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unresolved-global" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2047" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L2046" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2609,7 +2609,7 @@ def g():
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.7">0.0.1-alpha.7</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20unsupported-base" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L778" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L777" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2648,7 +2648,7 @@ class D(C): ... # error: [unsupported-base]
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'warn'."><code>warn</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.22">0.0.1-alpha.22</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20useless-overload-body" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1084" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1083" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2711,7 +2711,7 @@ def foo(x: int | str) -> int | str:
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'ignore'."><code>ignore</code></a> ·
|
||||
Preview (since <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a>) ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20division-by-zero" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L304" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L303" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
@ -2735,7 +2735,7 @@ Dividing by zero raises a `ZeroDivisionError` at runtime.
|
|||
Default level: <a href="../rules.md#rule-levels" title="This lint has a default level of 'ignore'."><code>ignore</code></a> ·
|
||||
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
|
||||
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20possibly-unresolved-reference" target="_blank">Related issues</a> ·
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1596" target="_blank">View source</a>
|
||||
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1595" target="_blank">View source</a>
|
||||
</small>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -580,6 +580,53 @@ fn check_non_existing_path() -> anyhow::Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_file_without_extension() -> anyhow::Result<()> {
|
||||
let case = CliTest::with_file("main", "a = b")?;
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
case.command().arg("main"),
|
||||
@r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
error[unresolved-reference]: Name `b` used when not defined
|
||||
--> main:1:5
|
||||
|
|
||||
1 | a = b
|
||||
| ^
|
||||
|
|
||||
info: rule `unresolved-reference` is enabled by default
|
||||
|
||||
Found 1 diagnostic
|
||||
|
||||
----- stderr -----
|
||||
"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_file_without_extension_in_subfolder() -> anyhow::Result<()> {
|
||||
let case = CliTest::with_file("src/main", "a = b")?;
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
case.command().arg("src"),
|
||||
@r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
All checks passed!
|
||||
|
||||
----- stderr -----
|
||||
WARN No python files found under the given path(s)
|
||||
"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn concise_diagnostics() -> anyhow::Result<()> {
|
||||
let case = CliTest::with_file(
|
||||
|
|
|
|||
|
|
@ -6433,6 +6433,155 @@ collabc<CURSOR>
|
|||
assert_snapshot!(snapshot, @"collections.abc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn local_function_variable_with_return() {
|
||||
let builder = completion_test_builder(
|
||||
"\
|
||||
variable_global = 1
|
||||
def foo():
|
||||
variable_local = 1
|
||||
variable_<CURSOR>
|
||||
return
|
||||
",
|
||||
);
|
||||
assert_snapshot!(
|
||||
builder.skip_auto_import().build().snapshot(),
|
||||
@r"
|
||||
variable_global
|
||||
variable_local
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nested_scopes_with_return() {
|
||||
let builder = completion_test_builder(
|
||||
"\
|
||||
variable_1 = 1
|
||||
def fun1():
|
||||
variable_2 = 1
|
||||
def fun2():
|
||||
variable_3 = 1
|
||||
def fun3():
|
||||
variable_4 = 1
|
||||
variable_<CURSOR>
|
||||
return
|
||||
return
|
||||
return
|
||||
",
|
||||
);
|
||||
assert_snapshot!(
|
||||
builder.skip_auto_import().build().snapshot(),
|
||||
@r"
|
||||
variable_1
|
||||
variable_2
|
||||
variable_3
|
||||
variable_4
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_declarations_global_scope1() {
|
||||
let builder = completion_test_builder(
|
||||
"\
|
||||
zqzqzq: int = 1
|
||||
zqzqzq: str = 'foo'
|
||||
zqzq<CURSOR>
|
||||
",
|
||||
);
|
||||
// The type for `zqzqzq` *should* be `str`, but we consider all
|
||||
// reachable declarations and bindings, which means we get a
|
||||
// union of `int` and `str` here even though the `int` binding
|
||||
// isn't live at the cursor position.
|
||||
assert_snapshot!(
|
||||
builder.skip_auto_import().type_signatures().build().snapshot(),
|
||||
@"zqzqzq :: int | str",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_declarations_global_scope2() {
|
||||
let builder = completion_test_builder(
|
||||
"\
|
||||
zqzqzq: int = 1
|
||||
zqzq<CURSOR>
|
||||
zqzqzq: str = 'foo'
|
||||
",
|
||||
);
|
||||
// The type for `zqzqzq` *should* be `int`, but we consider all
|
||||
// reachable declarations and bindings, which means we get a
|
||||
// union of `int` and `str` here even though the `str` binding
|
||||
// doesn't exist at the cursor position.
|
||||
assert_snapshot!(
|
||||
builder.skip_auto_import().type_signatures().build().snapshot(),
|
||||
@"zqzqzq :: int | str",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_declarations_function_scope1() {
|
||||
let builder = completion_test_builder(
|
||||
"\
|
||||
def foo():
|
||||
zqzqzq: int = 1
|
||||
zqzqzq: str = 'foo'
|
||||
zqzq<CURSOR>
|
||||
return
|
||||
",
|
||||
);
|
||||
// The type for `zqzqzq` *should* be `str`, but we consider all
|
||||
// reachable declarations and bindings, which means we get a
|
||||
// union of `int` and `str` here even though the `int` binding
|
||||
// isn't live at the cursor position.
|
||||
assert_snapshot!(
|
||||
builder.skip_auto_import().type_signatures().build().snapshot(),
|
||||
@"zqzqzq :: int | str",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_declarations_function_scope2() {
|
||||
let builder = completion_test_builder(
|
||||
"\
|
||||
def foo():
|
||||
zqzqzq: int = 1
|
||||
zqzq<CURSOR>
|
||||
zqzqzq: str = 'foo'
|
||||
return
|
||||
",
|
||||
);
|
||||
// The type for `zqzqzq` *should* be `int`, but we consider all
|
||||
// reachable declarations and bindings, which means we get a
|
||||
// union of `int` and `str` here even though the `str` binding
|
||||
// doesn't exist at the cursor position.
|
||||
assert_snapshot!(
|
||||
builder.skip_auto_import().type_signatures().build().snapshot(),
|
||||
@"zqzqzq :: int | str",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_declarations_function_parameter() {
|
||||
let builder = completion_test_builder(
|
||||
"\
|
||||
from pathlib import Path
|
||||
def f(zqzqzq: str):
|
||||
zqzqzq: Path = Path(zqzqzq)
|
||||
zqzq<CURSOR>
|
||||
return
|
||||
",
|
||||
);
|
||||
// The type for `zqzqzq` *should* be `Path`, but we consider all
|
||||
// reachable declarations and bindings, which means we get a
|
||||
// union of `str` and `Path` here even though the `str` binding
|
||||
// isn't live at the cursor position.
|
||||
assert_snapshot!(
|
||||
builder.skip_auto_import().type_signatures().build().snapshot(),
|
||||
@"zqzqzq :: str | Path",
|
||||
);
|
||||
}
|
||||
|
||||
/// A way to create a simple single-file (named `main.py`) completion test
|
||||
/// builder.
|
||||
///
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -295,7 +295,7 @@ impl<'db> Definitions<'db> {
|
|||
|
||||
impl GotoTarget<'_> {
|
||||
pub(crate) fn inferred_type<'db>(&self, model: &SemanticModel<'db>) -> Option<Type<'db>> {
|
||||
let ty = match self {
|
||||
match self {
|
||||
GotoTarget::Expression(expression) => expression.inferred_type(model),
|
||||
GotoTarget::FunctionDef(function) => function.inferred_type(model),
|
||||
GotoTarget::ClassDef(class) => class.inferred_type(model),
|
||||
|
|
@ -317,7 +317,7 @@ impl GotoTarget<'_> {
|
|||
} => {
|
||||
// We don't currently support hovering the bare `.` so there is always a name
|
||||
let module = import_name(module_name, *component_index);
|
||||
model.resolve_module_type(Some(module), *level)?
|
||||
model.resolve_module_type(Some(module), *level)
|
||||
}
|
||||
GotoTarget::StringAnnotationSubexpr {
|
||||
string_expr,
|
||||
|
|
@ -334,16 +334,16 @@ impl GotoTarget<'_> {
|
|||
} else {
|
||||
// TODO: force the typechecker to tell us its secrets
|
||||
// (it computes but then immediately discards these types)
|
||||
return None;
|
||||
None
|
||||
}
|
||||
}
|
||||
GotoTarget::BinOp { expression, .. } => {
|
||||
let (_, ty) = ty_python_semantic::definitions_for_bin_op(model, expression)?;
|
||||
ty
|
||||
Some(ty)
|
||||
}
|
||||
GotoTarget::UnaryOp { expression, .. } => {
|
||||
let (_, ty) = ty_python_semantic::definitions_for_unary_op(model, expression)?;
|
||||
ty
|
||||
Some(ty)
|
||||
}
|
||||
// TODO: Support identifier targets
|
||||
GotoTarget::PatternMatchRest(_)
|
||||
|
|
@ -353,10 +353,8 @@ impl GotoTarget<'_> {
|
|||
| GotoTarget::TypeParamParamSpecName(_)
|
||||
| GotoTarget::TypeParamTypeVarTupleName(_)
|
||||
| GotoTarget::NonLocal { .. }
|
||||
| GotoTarget::Globals { .. } => return None,
|
||||
};
|
||||
|
||||
Some(ty)
|
||||
| GotoTarget::Globals { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to get a simplified display of this callable type by resolving overloads
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue