mirror of https://github.com/astral-sh/ruff
[red-knot] Do not attach diagnostics to wrong file (#14337)
## Summary Avoid attaching diagnostics to the wrong file. See related issue for details. Closes #14334 ## Test Plan New regression test.
This commit is contained in:
parent
ec2c7cad0e
commit
9a3001b571
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Regression test for #14334
|
||||||
|
|
||||||
|
Regression test for [this issue](https://github.com/astral-sh/ruff/issues/14334).
|
||||||
|
|
||||||
|
```py path=base.py
|
||||||
|
# error: [invalid-base]
|
||||||
|
class Base(2): ...
|
||||||
|
```
|
||||||
|
|
||||||
|
```py path=a.py
|
||||||
|
# No error here
|
||||||
|
from base import Base
|
||||||
|
```
|
||||||
|
|
@ -469,16 +469,22 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
let class_definitions = self
|
let class_definitions = self
|
||||||
.types
|
.types
|
||||||
.declarations
|
.declarations
|
||||||
.values()
|
.iter()
|
||||||
.filter_map(|ty| ty.into_class_literal())
|
.filter_map(|(definition, ty)| {
|
||||||
.map(|class_ty| class_ty.class);
|
// Filter out class literals that result from imports
|
||||||
|
if let DefinitionKind::Class(class) = definition.kind(self.db) {
|
||||||
|
ty.into_class_literal().map(|ty| (ty.class, class.node()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Iterate through all class definitions in this scope.
|
// Iterate through all class definitions in this scope.
|
||||||
for class in class_definitions {
|
for (class, class_node) in class_definitions {
|
||||||
// (1) Check that the class does not have a cyclic definition
|
// (1) Check that the class does not have a cyclic definition
|
||||||
if class.is_cyclically_defined(self.db) {
|
if class.is_cyclically_defined(self.db) {
|
||||||
self.diagnostics.add(
|
self.diagnostics.add(
|
||||||
class.node(self.db).into(),
|
class_node.into(),
|
||||||
"cyclic-class-def",
|
"cyclic-class-def",
|
||||||
format_args!(
|
format_args!(
|
||||||
"Cyclic definition of `{}` or bases of `{}` (class cannot inherit from itself)",
|
"Cyclic definition of `{}` or bases of `{}` (class cannot inherit from itself)",
|
||||||
|
|
@ -495,7 +501,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
if let Err(mro_error) = class.try_mro(self.db).as_ref() {
|
if let Err(mro_error) = class.try_mro(self.db).as_ref() {
|
||||||
match mro_error.reason() {
|
match mro_error.reason() {
|
||||||
MroErrorKind::DuplicateBases(duplicates) => {
|
MroErrorKind::DuplicateBases(duplicates) => {
|
||||||
let base_nodes = class.node(self.db).bases();
|
let base_nodes = class_node.bases();
|
||||||
for (index, duplicate) in duplicates {
|
for (index, duplicate) in duplicates {
|
||||||
self.diagnostics.add(
|
self.diagnostics.add(
|
||||||
(&base_nodes[*index]).into(),
|
(&base_nodes[*index]).into(),
|
||||||
|
|
@ -505,7 +511,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MroErrorKind::InvalidBases(bases) => {
|
MroErrorKind::InvalidBases(bases) => {
|
||||||
let base_nodes = class.node(self.db).bases();
|
let base_nodes = class_node.bases();
|
||||||
for (index, base_ty) in bases {
|
for (index, base_ty) in bases {
|
||||||
self.diagnostics.add(
|
self.diagnostics.add(
|
||||||
(&base_nodes[*index]).into(),
|
(&base_nodes[*index]).into(),
|
||||||
|
|
@ -518,7 +524,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MroErrorKind::UnresolvableMro { bases_list } => self.diagnostics.add(
|
MroErrorKind::UnresolvableMro { bases_list } => self.diagnostics.add(
|
||||||
class.node(self.db).into(),
|
class_node.into(),
|
||||||
"inconsistent-mro",
|
"inconsistent-mro",
|
||||||
format_args!(
|
format_args!(
|
||||||
"Cannot create a consistent method resolution order (MRO) for class `{}` with bases list `[{}]`",
|
"Cannot create a consistent method resolution order (MRO) for class `{}` with bases list `[{}]`",
|
||||||
|
|
@ -545,7 +551,7 @@ impl<'db> TypeInferenceBuilder<'db> {
|
||||||
},
|
},
|
||||||
candidate1_is_base_class,
|
candidate1_is_base_class,
|
||||||
} => {
|
} => {
|
||||||
let node = class.node(self.db).into();
|
let node = class_node.into();
|
||||||
if *candidate1_is_base_class {
|
if *candidate1_is_base_class {
|
||||||
self.diagnostics.add(
|
self.diagnostics.add(
|
||||||
node,
|
node,
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,6 @@ static EXPECTED_DIAGNOSTICS: &[&str] = &[
|
||||||
"error[possibly-unresolved-reference] /src/tomllib/_parser.py:580:63 Name `char` used when possibly not defined",
|
"error[possibly-unresolved-reference] /src/tomllib/_parser.py:580:63 Name `char` used when possibly not defined",
|
||||||
"error[conflicting-declarations] /src/tomllib/_parser.py:590:9 Conflicting declared types for `char`: Unknown, str | None",
|
"error[conflicting-declarations] /src/tomllib/_parser.py:590:9 Conflicting declared types for `char`: Unknown, str | None",
|
||||||
"error[possibly-unresolved-reference] /src/tomllib/_parser.py:629:38 Name `datetime_obj` used when possibly not defined",
|
"error[possibly-unresolved-reference] /src/tomllib/_parser.py:629:38 Name `datetime_obj` used when possibly not defined",
|
||||||
"error[invalid-base] /src/tomllib/_parser.py:692:8354 Invalid class base with type `GenericAlias` (all bases must be a class, `Any`, `Unknown` or `Todo`)",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
fn get_test_file(name: &str) -> TestFile {
|
fn get_test_file(name: &str) -> TestFile {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue