mirror of https://github.com/astral-sh/ruff
[ty] Switch the error code from `unresolved-attribute` to `possibly-missing-attribute` for submodules that may not be available (#21618)
This commit is contained in:
parent
03fe560164
commit
0c6d652b5f
|
|
@ -2711,9 +2711,9 @@ We give special diagnostics for this common case too:
|
||||||
import foo
|
import foo
|
||||||
import baz
|
import baz
|
||||||
|
|
||||||
# error: [unresolved-attribute]
|
# error: [possibly-missing-attribute]
|
||||||
reveal_type(foo.bar) # revealed: Unknown
|
reveal_type(foo.bar) # revealed: Unknown
|
||||||
# error: [unresolved-attribute]
|
# error: [possibly-missing-attribute]
|
||||||
reveal_type(baz.bar) # revealed: Unknown
|
reveal_type(baz.bar) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ Y: int = 47
|
||||||
import mypackage
|
import mypackage
|
||||||
|
|
||||||
reveal_type(mypackage.imported.X) # revealed: int
|
reveal_type(mypackage.imported.X) # revealed: int
|
||||||
# error: [unresolved-attribute] "Submodule `fails` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `fails` may not be available"
|
||||||
reveal_type(mypackage.fails.Y) # revealed: Unknown
|
reveal_type(mypackage.fails.Y) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@ Y: int = 47
|
||||||
import mypackage
|
import mypackage
|
||||||
|
|
||||||
reveal_type(mypackage.imported.X) # revealed: int
|
reveal_type(mypackage.imported.X) # revealed: int
|
||||||
# error: [unresolved-attribute] "Submodule `fails` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `fails` may not be available"
|
||||||
reveal_type(mypackage.fails.Y) # revealed: Unknown
|
reveal_type(mypackage.fails.Y) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -125,7 +125,7 @@ Y: int = 47
|
||||||
import mypackage
|
import mypackage
|
||||||
|
|
||||||
reveal_type(mypackage.imported.X) # revealed: int
|
reveal_type(mypackage.imported.X) # revealed: int
|
||||||
# error: [unresolved-attribute] "Submodule `fails` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `fails` may not be available"
|
||||||
reveal_type(mypackage.fails.Y) # revealed: Unknown
|
reveal_type(mypackage.fails.Y) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -155,7 +155,7 @@ Y: int = 47
|
||||||
import mypackage
|
import mypackage
|
||||||
|
|
||||||
reveal_type(mypackage.imported.X) # revealed: int
|
reveal_type(mypackage.imported.X) # revealed: int
|
||||||
# error: [unresolved-attribute] "Submodule `fails` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `fails` may not be available"
|
||||||
reveal_type(mypackage.fails.Y) # revealed: Unknown
|
reveal_type(mypackage.fails.Y) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -184,7 +184,7 @@ X: int = 42
|
||||||
import mypackage
|
import mypackage
|
||||||
|
|
||||||
# TODO: this could work and would be nice to have?
|
# TODO: this could work and would be nice to have?
|
||||||
# error: [unresolved-attribute] "Submodule `imported` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `imported` may not be available"
|
||||||
reveal_type(mypackage.imported.X) # revealed: Unknown
|
reveal_type(mypackage.imported.X) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -208,7 +208,7 @@ X: int = 42
|
||||||
import mypackage
|
import mypackage
|
||||||
|
|
||||||
# TODO: this could work and would be nice to have
|
# TODO: this could work and would be nice to have
|
||||||
# error: [unresolved-attribute] "Submodule `imported` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `imported` may not be available"
|
||||||
reveal_type(mypackage.imported.X) # revealed: Unknown
|
reveal_type(mypackage.imported.X) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -242,9 +242,9 @@ X: int = 42
|
||||||
import mypackage
|
import mypackage
|
||||||
|
|
||||||
reveal_type(mypackage.submodule) # revealed: <module 'mypackage.submodule'>
|
reveal_type(mypackage.submodule) # revealed: <module 'mypackage.submodule'>
|
||||||
# error: [unresolved-attribute] "Submodule `nested` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `nested` may not be available"
|
||||||
reveal_type(mypackage.submodule.nested) # revealed: Unknown
|
reveal_type(mypackage.submodule.nested) # revealed: Unknown
|
||||||
# error: [unresolved-attribute] "Submodule `nested` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `nested` may not be available"
|
||||||
reveal_type(mypackage.submodule.nested.X) # revealed: Unknown
|
reveal_type(mypackage.submodule.nested.X) # revealed: Unknown
|
||||||
# error: [unresolved-attribute] "has no member `nested`"
|
# error: [unresolved-attribute] "has no member `nested`"
|
||||||
reveal_type(mypackage.nested) # revealed: Unknown
|
reveal_type(mypackage.nested) # revealed: Unknown
|
||||||
|
|
@ -280,9 +280,9 @@ import mypackage
|
||||||
|
|
||||||
reveal_type(mypackage.submodule) # revealed: <module 'mypackage.submodule'>
|
reveal_type(mypackage.submodule) # revealed: <module 'mypackage.submodule'>
|
||||||
# TODO: this would be nice to support
|
# TODO: this would be nice to support
|
||||||
# error: [unresolved-attribute] "Submodule `nested` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `nested` may not be available"
|
||||||
reveal_type(mypackage.submodule.nested) # revealed: Unknown
|
reveal_type(mypackage.submodule.nested) # revealed: Unknown
|
||||||
# error: [unresolved-attribute] "Submodule `nested` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `nested` may not be available"
|
||||||
reveal_type(mypackage.submodule.nested.X) # revealed: Unknown
|
reveal_type(mypackage.submodule.nested.X) # revealed: Unknown
|
||||||
reveal_type(mypackage.nested) # revealed: <module 'mypackage.submodule.nested'>
|
reveal_type(mypackage.nested) # revealed: <module 'mypackage.submodule.nested'>
|
||||||
reveal_type(mypackage.nested.X) # revealed: int
|
reveal_type(mypackage.nested.X) # revealed: int
|
||||||
|
|
@ -318,9 +318,9 @@ X: int = 42
|
||||||
import mypackage
|
import mypackage
|
||||||
|
|
||||||
reveal_type(mypackage.submodule) # revealed: <module 'mypackage.submodule'>
|
reveal_type(mypackage.submodule) # revealed: <module 'mypackage.submodule'>
|
||||||
# error: [unresolved-attribute] "Submodule `nested` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `nested` may not be available"
|
||||||
reveal_type(mypackage.submodule.nested) # revealed: Unknown
|
reveal_type(mypackage.submodule.nested) # revealed: Unknown
|
||||||
# error: [unresolved-attribute] "Submodule `nested` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `nested` may not be available"
|
||||||
reveal_type(mypackage.submodule.nested.X) # revealed: Unknown
|
reveal_type(mypackage.submodule.nested.X) # revealed: Unknown
|
||||||
# error: [unresolved-attribute] "has no member `nested`"
|
# error: [unresolved-attribute] "has no member `nested`"
|
||||||
reveal_type(mypackage.nested) # revealed: Unknown
|
reveal_type(mypackage.nested) # revealed: Unknown
|
||||||
|
|
@ -356,9 +356,9 @@ import mypackage
|
||||||
|
|
||||||
reveal_type(mypackage.submodule) # revealed: <module 'mypackage.submodule'>
|
reveal_type(mypackage.submodule) # revealed: <module 'mypackage.submodule'>
|
||||||
# TODO: this would be nice to support
|
# TODO: this would be nice to support
|
||||||
# error: [unresolved-attribute] "Submodule `nested` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `nested` may not be available"
|
||||||
reveal_type(mypackage.submodule.nested) # revealed: Unknown
|
reveal_type(mypackage.submodule.nested) # revealed: Unknown
|
||||||
# error: [unresolved-attribute] "Submodule `nested` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `nested` may not be available"
|
||||||
reveal_type(mypackage.submodule.nested.X) # revealed: Unknown
|
reveal_type(mypackage.submodule.nested.X) # revealed: Unknown
|
||||||
reveal_type(mypackage.nested) # revealed: <module 'mypackage.submodule.nested'>
|
reveal_type(mypackage.nested) # revealed: <module 'mypackage.submodule.nested'>
|
||||||
reveal_type(mypackage.nested.X) # revealed: int
|
reveal_type(mypackage.nested.X) # revealed: int
|
||||||
|
|
@ -393,11 +393,11 @@ X: int = 42
|
||||||
```py
|
```py
|
||||||
import mypackage
|
import mypackage
|
||||||
|
|
||||||
# error: [unresolved-attribute] "Submodule `submodule` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `submodule` may not be available"
|
||||||
reveal_type(mypackage.submodule) # revealed: Unknown
|
reveal_type(mypackage.submodule) # revealed: Unknown
|
||||||
# error: [unresolved-attribute] "Submodule `submodule` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `submodule` may not be available"
|
||||||
reveal_type(mypackage.submodule.nested) # revealed: Unknown
|
reveal_type(mypackage.submodule.nested) # revealed: Unknown
|
||||||
# error: [unresolved-attribute] "Submodule `submodule` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `submodule` may not be available"
|
||||||
reveal_type(mypackage.submodule.nested.X) # revealed: Unknown
|
reveal_type(mypackage.submodule.nested.X) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -429,11 +429,11 @@ X: int = 42
|
||||||
import mypackage
|
import mypackage
|
||||||
|
|
||||||
# TODO: this would be nice to support
|
# TODO: this would be nice to support
|
||||||
# error: [unresolved-attribute] "Submodule `submodule` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `submodule` may not be available"
|
||||||
reveal_type(mypackage.submodule) # revealed: Unknown
|
reveal_type(mypackage.submodule) # revealed: Unknown
|
||||||
# error: [unresolved-attribute] "Submodule `submodule` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `submodule` may not be available"
|
||||||
reveal_type(mypackage.submodule.nested) # revealed: Unknown
|
reveal_type(mypackage.submodule.nested) # revealed: Unknown
|
||||||
# error: [unresolved-attribute] "Submodule `submodule` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `submodule` may not be available"
|
||||||
reveal_type(mypackage.submodule.nested.X) # revealed: Unknown
|
reveal_type(mypackage.submodule.nested.X) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -460,7 +460,7 @@ X: int = 42
|
||||||
```py
|
```py
|
||||||
import mypackage
|
import mypackage
|
||||||
|
|
||||||
# error: [unresolved-attribute] "Submodule `imported` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `imported` may not be available"
|
||||||
reveal_type(mypackage.imported.X) # revealed: Unknown
|
reveal_type(mypackage.imported.X) # revealed: Unknown
|
||||||
# error: [unresolved-attribute] "has no member `imported_m`"
|
# error: [unresolved-attribute] "has no member `imported_m`"
|
||||||
reveal_type(mypackage.imported_m.X) # revealed: Unknown
|
reveal_type(mypackage.imported_m.X) # revealed: Unknown
|
||||||
|
|
@ -486,7 +486,7 @@ X: int = 42
|
||||||
import mypackage
|
import mypackage
|
||||||
|
|
||||||
# TODO: this would be nice to support, as it works at runtime
|
# TODO: this would be nice to support, as it works at runtime
|
||||||
# error: [unresolved-attribute] "Submodule `imported` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `imported` may not be available"
|
||||||
reveal_type(mypackage.imported.X) # revealed: Unknown
|
reveal_type(mypackage.imported.X) # revealed: Unknown
|
||||||
reveal_type(mypackage.imported_m.X) # revealed: int
|
reveal_type(mypackage.imported_m.X) # revealed: int
|
||||||
```
|
```
|
||||||
|
|
@ -673,7 +673,7 @@ reveal_type(imported.X) # revealed: int
|
||||||
|
|
||||||
# TODO: this would be nice to support, but it's dangerous with available_submodule_attributes
|
# TODO: this would be nice to support, but it's dangerous with available_submodule_attributes
|
||||||
# for details, see: https://github.com/astral-sh/ty/issues/1488
|
# for details, see: https://github.com/astral-sh/ty/issues/1488
|
||||||
# error: [unresolved-attribute] "Submodule `imported` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `imported` may not be available"
|
||||||
reveal_type(mypackage.imported.X) # revealed: Unknown
|
reveal_type(mypackage.imported.X) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -699,7 +699,7 @@ from mypackage import imported
|
||||||
reveal_type(imported.X) # revealed: int
|
reveal_type(imported.X) # revealed: int
|
||||||
|
|
||||||
# TODO: this would be nice to support, as it works at runtime
|
# TODO: this would be nice to support, as it works at runtime
|
||||||
# error: [unresolved-attribute] "Submodule `imported` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `imported` may not be available"
|
||||||
reveal_type(mypackage.imported.X) # revealed: Unknown
|
reveal_type(mypackage.imported.X) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -737,7 +737,7 @@ from mypackage import imported
|
||||||
reveal_type(imported.X) # revealed: int
|
reveal_type(imported.X) # revealed: int
|
||||||
# error: [unresolved-attribute] "has no member `fails`"
|
# error: [unresolved-attribute] "has no member `fails`"
|
||||||
reveal_type(imported.fails.Y) # revealed: Unknown
|
reveal_type(imported.fails.Y) # revealed: Unknown
|
||||||
# error: [unresolved-attribute] "Submodule `fails` may not be available"
|
# error: [possibly-missing-attribute] "Submodule `fails` may not be available"
|
||||||
reveal_type(mypackage.fails.Y) # revealed: Unknown
|
reveal_type(mypackage.fails.Y) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -770,7 +770,7 @@ from mypackage import imported
|
||||||
|
|
||||||
reveal_type(imported.X) # revealed: int
|
reveal_type(imported.X) # revealed: int
|
||||||
reveal_type(imported.fails.Y) # revealed: int
|
reveal_type(imported.fails.Y) # revealed: int
|
||||||
# error: [unresolved-attribute] "Submodule `fails`"
|
# error: [possibly-missing-attribute] "Submodule `fails`"
|
||||||
reveal_type(mypackage.fails.Y) # revealed: Unknown
|
reveal_type(mypackage.fails.Y) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -247,7 +247,7 @@ X: int = 42
|
||||||
from . import foo
|
from . import foo
|
||||||
import package
|
import package
|
||||||
|
|
||||||
# error: [unresolved-attribute]
|
# error: [possibly-missing-attribute]
|
||||||
reveal_type(package.foo.X) # revealed: Unknown
|
reveal_type(package.foo.X) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,39 +30,39 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/attributes.md
|
||||||
1 | import foo
|
1 | import foo
|
||||||
2 | import baz
|
2 | import baz
|
||||||
3 |
|
3 |
|
||||||
4 | # error: [unresolved-attribute]
|
4 | # error: [possibly-missing-attribute]
|
||||||
5 | reveal_type(foo.bar) # revealed: Unknown
|
5 | reveal_type(foo.bar) # revealed: Unknown
|
||||||
6 | # error: [unresolved-attribute]
|
6 | # error: [possibly-missing-attribute]
|
||||||
7 | reveal_type(baz.bar) # revealed: Unknown
|
7 | reveal_type(baz.bar) # revealed: Unknown
|
||||||
```
|
```
|
||||||
|
|
||||||
# Diagnostics
|
# Diagnostics
|
||||||
|
|
||||||
```
|
```
|
||||||
error[unresolved-attribute]: Submodule `bar` may not be available as an attribute on module `foo`
|
warning[possibly-missing-attribute]: Submodule `bar` may not be available as an attribute on module `foo`
|
||||||
--> src/main.py:5:13
|
--> src/main.py:5:13
|
||||||
|
|
|
|
||||||
4 | # error: [unresolved-attribute]
|
4 | # error: [possibly-missing-attribute]
|
||||||
5 | reveal_type(foo.bar) # revealed: Unknown
|
5 | reveal_type(foo.bar) # revealed: Unknown
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
6 | # error: [unresolved-attribute]
|
6 | # error: [possibly-missing-attribute]
|
||||||
7 | reveal_type(baz.bar) # revealed: Unknown
|
7 | reveal_type(baz.bar) # revealed: Unknown
|
||||||
|
|
|
|
||||||
help: Consider explicitly importing `foo.bar`
|
help: Consider explicitly importing `foo.bar`
|
||||||
info: rule `unresolved-attribute` is enabled by default
|
info: rule `possibly-missing-attribute` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
error[unresolved-attribute]: Submodule `bar` may not be available as an attribute on module `baz`
|
warning[possibly-missing-attribute]: Submodule `bar` may not be available as an attribute on module `baz`
|
||||||
--> src/main.py:7:13
|
--> src/main.py:7:13
|
||||||
|
|
|
|
||||||
5 | reveal_type(foo.bar) # revealed: Unknown
|
5 | reveal_type(foo.bar) # revealed: Unknown
|
||||||
6 | # error: [unresolved-attribute]
|
6 | # error: [possibly-missing-attribute]
|
||||||
7 | reveal_type(baz.bar) # revealed: Unknown
|
7 | reveal_type(baz.bar) # revealed: Unknown
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
|
|
|
||||||
help: Consider explicitly importing `baz.bar`
|
help: Consider explicitly importing `baz.bar`
|
||||||
info: rule `unresolved-attribute` is enabled by default
|
info: rule `possibly-missing-attribute` is enabled by default
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -628,7 +628,7 @@ import imported
|
||||||
from module2 import imported as other_imported
|
from module2 import imported as other_imported
|
||||||
from ty_extensions import TypeOf, static_assert, is_equivalent_to
|
from ty_extensions import TypeOf, static_assert, is_equivalent_to
|
||||||
|
|
||||||
# error: [unresolved-attribute]
|
# error: [possibly-missing-attribute]
|
||||||
reveal_type(imported.abc) # revealed: Unknown
|
reveal_type(imported.abc) # revealed: Unknown
|
||||||
|
|
||||||
reveal_type(other_imported.abc) # revealed: <module 'imported.abc'>
|
reveal_type(other_imported.abc) # revealed: <module 'imported.abc'>
|
||||||
|
|
|
||||||
|
|
@ -62,9 +62,9 @@ use crate::types::diagnostic::{
|
||||||
INVALID_NAMED_TUPLE, INVALID_NEWTYPE, INVALID_OVERLOAD, INVALID_PARAMETER_DEFAULT,
|
INVALID_NAMED_TUPLE, INVALID_NEWTYPE, INVALID_OVERLOAD, INVALID_PARAMETER_DEFAULT,
|
||||||
INVALID_PARAMSPEC, INVALID_PROTOCOL, INVALID_TYPE_FORM, INVALID_TYPE_GUARD_CALL,
|
INVALID_PARAMSPEC, INVALID_PROTOCOL, INVALID_TYPE_FORM, INVALID_TYPE_GUARD_CALL,
|
||||||
INVALID_TYPE_VARIABLE_CONSTRAINTS, IncompatibleBases, NON_SUBSCRIPTABLE,
|
INVALID_TYPE_VARIABLE_CONSTRAINTS, IncompatibleBases, NON_SUBSCRIPTABLE,
|
||||||
POSSIBLY_MISSING_IMPLICIT_CALL, POSSIBLY_MISSING_IMPORT, SUBCLASS_OF_FINAL_CLASS,
|
POSSIBLY_MISSING_ATTRIBUTE, POSSIBLY_MISSING_IMPLICIT_CALL, POSSIBLY_MISSING_IMPORT,
|
||||||
UNDEFINED_REVEAL, UNRESOLVED_ATTRIBUTE, UNRESOLVED_GLOBAL, UNRESOLVED_IMPORT,
|
SUBCLASS_OF_FINAL_CLASS, UNDEFINED_REVEAL, UNRESOLVED_ATTRIBUTE, UNRESOLVED_GLOBAL,
|
||||||
UNRESOLVED_REFERENCE, UNSUPPORTED_OPERATOR, USELESS_OVERLOAD_BODY,
|
UNRESOLVED_IMPORT, UNRESOLVED_REFERENCE, UNSUPPORTED_OPERATOR, USELESS_OVERLOAD_BODY,
|
||||||
hint_if_stdlib_attribute_exists_on_other_versions,
|
hint_if_stdlib_attribute_exists_on_other_versions,
|
||||||
hint_if_stdlib_submodule_exists_on_other_versions, report_attempted_protocol_instantiation,
|
hint_if_stdlib_submodule_exists_on_other_versions, report_attempted_protocol_instantiation,
|
||||||
report_bad_dunder_set_call, report_cannot_pop_required_field_on_typed_dict,
|
report_bad_dunder_set_call, report_cannot_pop_required_field_on_typed_dict,
|
||||||
|
|
@ -9083,6 +9083,32 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let Type::ModuleLiteral(module) = value_type {
|
||||||
|
let module = module.module(db);
|
||||||
|
let module_name = module.name(db);
|
||||||
|
if module.kind(db).is_package()
|
||||||
|
&& let Some(relative_submodule) = ModuleName::new(attr_name)
|
||||||
|
{
|
||||||
|
let mut maybe_submodule_name = module_name.clone();
|
||||||
|
maybe_submodule_name.extend(&relative_submodule);
|
||||||
|
if resolve_module(db, &maybe_submodule_name).is_some() {
|
||||||
|
if let Some(builder) = self
|
||||||
|
.context
|
||||||
|
.report_lint(&POSSIBLY_MISSING_ATTRIBUTE, attribute)
|
||||||
|
{
|
||||||
|
let mut diag = builder.into_diagnostic(format_args!(
|
||||||
|
"Submodule `{attr_name}` may not be available as an attribute \
|
||||||
|
on module `{module_name}`"
|
||||||
|
));
|
||||||
|
diag.help(format_args!(
|
||||||
|
"Consider explicitly importing `{maybe_submodule_name}`"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return fallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let Some(builder) = self.context.report_lint(&UNRESOLVED_ATTRIBUTE, attribute)
|
let Some(builder) = self.context.report_lint(&UNRESOLVED_ATTRIBUTE, attribute)
|
||||||
else {
|
else {
|
||||||
return fallback();
|
return fallback();
|
||||||
|
|
@ -9098,30 +9124,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let diagnostic = match value_type {
|
let diagnostic = match value_type {
|
||||||
Type::ModuleLiteral(module) => {
|
Type::ModuleLiteral(module) => builder.into_diagnostic(format_args!(
|
||||||
let module = module.module(db);
|
"Module `{module_name}` has no member `{attr_name}`",
|
||||||
let module_name = module.name(db);
|
module_name = module.module(db).name(db),
|
||||||
if module.kind(db).is_package()
|
)),
|
||||||
&& let Some(relative_submodule) = ModuleName::new(attr_name)
|
|
||||||
{
|
|
||||||
let mut maybe_submodule_name = module_name.clone();
|
|
||||||
maybe_submodule_name.extend(&relative_submodule);
|
|
||||||
if resolve_module(db, &maybe_submodule_name).is_some() {
|
|
||||||
let mut diag = builder.into_diagnostic(format_args!(
|
|
||||||
"Submodule `{attr_name}` may not be available as an attribute \
|
|
||||||
on module `{module_name}`"
|
|
||||||
));
|
|
||||||
diag.help(format_args!(
|
|
||||||
"Consider explicitly importing `{maybe_submodule_name}`"
|
|
||||||
));
|
|
||||||
return fallback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.into_diagnostic(format_args!(
|
|
||||||
"Module `{module_name}` has no member `{attr_name}`",
|
|
||||||
))
|
|
||||||
}
|
|
||||||
Type::ClassLiteral(class) => builder.into_diagnostic(format_args!(
|
Type::ClassLiteral(class) => builder.into_diagnostic(format_args!(
|
||||||
"Class `{}` has no attribute `{attr_name}`",
|
"Class `{}` has no attribute `{attr_name}`",
|
||||||
class.name(db),
|
class.name(db),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue