mirror of https://github.com/astral-sh/ruff
[ty] Fix find references for type defined in stub (#21732)
This commit is contained in:
parent
b4f618e180
commit
3738ab1c46
|
|
@ -1656,4 +1656,70 @@ func<CURSOR>_alias()
|
||||||
|
|
|
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn stub_target() {
|
||||||
|
let test = CursorTest::builder()
|
||||||
|
.source(
|
||||||
|
"path.pyi",
|
||||||
|
r#"
|
||||||
|
class Path:
|
||||||
|
def __init__(self, path: str): ...
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"path.py",
|
||||||
|
r#"
|
||||||
|
class Path:
|
||||||
|
def __init__(self, path: str):
|
||||||
|
self.path = path
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.source(
|
||||||
|
"importer.py",
|
||||||
|
r#"
|
||||||
|
from path import Path<CURSOR>
|
||||||
|
|
||||||
|
a: Path = Path("test")
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert_snapshot!(test.references(), @r###"
|
||||||
|
info[references]: Reference 1
|
||||||
|
--> path.pyi:2:7
|
||||||
|
|
|
||||||
|
2 | class Path:
|
||||||
|
| ^^^^
|
||||||
|
3 | def __init__(self, path: str): ...
|
||||||
|
|
|
||||||
|
|
||||||
|
info[references]: Reference 2
|
||||||
|
--> importer.py:2:18
|
||||||
|
|
|
||||||
|
2 | from path import Path
|
||||||
|
| ^^^^
|
||||||
|
3 |
|
||||||
|
4 | a: Path = Path("test")
|
||||||
|
|
|
||||||
|
|
||||||
|
info[references]: Reference 3
|
||||||
|
--> importer.py:4:4
|
||||||
|
|
|
||||||
|
2 | from path import Path
|
||||||
|
3 |
|
||||||
|
4 | a: Path = Path("test")
|
||||||
|
| ^^^^
|
||||||
|
|
|
||||||
|
|
||||||
|
info[references]: Reference 4
|
||||||
|
--> importer.py:4:11
|
||||||
|
|
|
||||||
|
2 | from path import Path
|
||||||
|
3 |
|
||||||
|
4 | a: Path = Path("test")
|
||||||
|
| ^^^^
|
||||||
|
|
|
||||||
|
"###);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
use crate::find_node::CoveringNode;
|
use crate::find_node::CoveringNode;
|
||||||
use crate::goto::GotoTarget;
|
use crate::goto::GotoTarget;
|
||||||
use crate::{Db, NavigationTarget, ReferenceKind, ReferenceTarget};
|
use crate::{Db, NavigationTargets, ReferenceKind, ReferenceTarget};
|
||||||
use ruff_db::files::File;
|
use ruff_db::files::File;
|
||||||
use ruff_python_ast::{
|
use ruff_python_ast::{
|
||||||
self as ast, AnyNodeRef,
|
self as ast, AnyNodeRef,
|
||||||
|
|
@ -49,10 +49,9 @@ pub(crate) fn references(
|
||||||
|
|
||||||
// When finding references, do not resolve any local aliases.
|
// When finding references, do not resolve any local aliases.
|
||||||
let model = SemanticModel::new(db, file);
|
let model = SemanticModel::new(db, file);
|
||||||
let target_definitions_nav = goto_target
|
let target_definitions = goto_target
|
||||||
.get_definition_targets(&model, ImportAliasResolution::PreserveAliases)?
|
.get_definition_targets(&model, ImportAliasResolution::PreserveAliases)?
|
||||||
.definition_targets(db)?;
|
.declaration_targets(db)?;
|
||||||
let target_definitions: Vec<NavigationTarget> = target_definitions_nav.into_iter().collect();
|
|
||||||
|
|
||||||
// Extract the target text from the goto target for fast comparison
|
// Extract the target text from the goto target for fast comparison
|
||||||
let target_text = goto_target.to_string()?;
|
let target_text = goto_target.to_string()?;
|
||||||
|
|
@ -115,7 +114,7 @@ pub(crate) fn references(
|
||||||
fn references_for_file(
|
fn references_for_file(
|
||||||
db: &dyn Db,
|
db: &dyn Db,
|
||||||
file: File,
|
file: File,
|
||||||
target_definitions: &[NavigationTarget],
|
target_definitions: &NavigationTargets,
|
||||||
target_text: &str,
|
target_text: &str,
|
||||||
mode: ReferencesMode,
|
mode: ReferencesMode,
|
||||||
references: &mut Vec<ReferenceTarget>,
|
references: &mut Vec<ReferenceTarget>,
|
||||||
|
|
@ -159,7 +158,7 @@ fn is_symbol_externally_visible(goto_target: &GotoTarget<'_>) -> bool {
|
||||||
struct LocalReferencesFinder<'a> {
|
struct LocalReferencesFinder<'a> {
|
||||||
model: &'a SemanticModel<'a>,
|
model: &'a SemanticModel<'a>,
|
||||||
tokens: &'a Tokens,
|
tokens: &'a Tokens,
|
||||||
target_definitions: &'a [NavigationTarget],
|
target_definitions: &'a NavigationTargets,
|
||||||
references: &'a mut Vec<ReferenceTarget>,
|
references: &'a mut Vec<ReferenceTarget>,
|
||||||
mode: ReferencesMode,
|
mode: ReferencesMode,
|
||||||
target_text: &'a str,
|
target_text: &'a str,
|
||||||
|
|
@ -318,12 +317,10 @@ impl LocalReferencesFinder<'_> {
|
||||||
GotoTarget::from_covering_node(self.model, covering_node, offset, self.tokens)
|
GotoTarget::from_covering_node(self.model, covering_node, offset, self.tokens)
|
||||||
{
|
{
|
||||||
// Get the definitions for this goto target
|
// Get the definitions for this goto target
|
||||||
if let Some(current_definitions_nav) = goto_target
|
if let Some(current_definitions) = goto_target
|
||||||
.get_definition_targets(self.model, ImportAliasResolution::PreserveAliases)
|
.get_definition_targets(self.model, ImportAliasResolution::PreserveAliases)
|
||||||
.and_then(|definitions| definitions.declaration_targets(self.model.db()))
|
.and_then(|definitions| definitions.declaration_targets(self.model.db()))
|
||||||
{
|
{
|
||||||
let current_definitions: Vec<NavigationTarget> =
|
|
||||||
current_definitions_nav.into_iter().collect();
|
|
||||||
// Check if any of the current definitions match our target definitions
|
// Check if any of the current definitions match our target definitions
|
||||||
if self.navigation_targets_match(¤t_definitions) {
|
if self.navigation_targets_match(¤t_definitions) {
|
||||||
// Determine if this is a read or write reference
|
// Determine if this is a read or write reference
|
||||||
|
|
@ -337,7 +334,7 @@ impl LocalReferencesFinder<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if `Vec<NavigationTarget>` match our target definitions
|
/// Check if `Vec<NavigationTarget>` match our target definitions
|
||||||
fn navigation_targets_match(&self, current_targets: &[NavigationTarget]) -> bool {
|
fn navigation_targets_match(&self, current_targets: &NavigationTargets) -> bool {
|
||||||
// Since we're comparing the same symbol, all definitions should be equivalent
|
// Since we're comparing the same symbol, all definitions should be equivalent
|
||||||
// We only need to check against the first target definition
|
// We only need to check against the first target definition
|
||||||
if let Some(first_target) = self.target_definitions.iter().next() {
|
if let Some(first_target) = self.target_definitions.iter().next() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue