Skip to content

Commit 8e3a2c3

Browse files
authored
ide: support find references for join using clause (#816)
1 parent 734f69f commit 8e3a2c3

File tree

1 file changed

+31
-10
lines changed

1 file changed

+31
-10
lines changed

β€Žcrates/squawk_ide/src/find_references.rsβ€Ž

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::binder::{self, Binder};
22
use crate::offsets::token_from_offset;
33
use crate::resolve;
44
use rowan::{TextRange, TextSize};
5+
use smallvec::{SmallVec, smallvec};
56
use squawk_syntax::{
67
SyntaxNodePtr,
78
ast::{self, AstNode},
@@ -10,7 +11,7 @@ use squawk_syntax::{
1011

1112
pub fn find_references(file: &ast::SourceFile, offset: TextSize) -> Vec<TextRange> {
1213
let binder = binder::bind(file);
13-
let Some(target) = find_target(file, offset, &binder) else {
14+
let Some(targets) = find_targets(file, offset, &binder) else {
1415
return vec![];
1516
};
1617

@@ -21,14 +22,14 @@ pub fn find_references(file: &ast::SourceFile, offset: TextSize) -> Vec<TextRang
2122
match node {
2223
ast::NameRef(name_ref) => {
2324
if let Some(found_refs) = resolve::resolve_name_ref(&binder, &name_ref)
24-
&& found_refs.contains(&target)
25+
&& found_refs.iter().any(|ptr| targets.contains(ptr))
2526
{
2627
refs.push(name_ref.syntax().text_range());
2728
}
2829
},
2930
ast::Name(name) => {
3031
let found = SyntaxNodePtr::new(name.syntax());
31-
if found == target {
32+
if targets.contains(&found) {
3233
refs.push(name.syntax().text_range());
3334
}
3435
},
@@ -41,20 +42,20 @@ pub fn find_references(file: &ast::SourceFile, offset: TextSize) -> Vec<TextRang
4142
refs
4243
}
4344

44-
fn find_target(file: &ast::SourceFile, offset: TextSize, binder: &Binder) -> Option<SyntaxNodePtr> {
45+
fn find_targets(
46+
file: &ast::SourceFile,
47+
offset: TextSize,
48+
binder: &Binder,
49+
) -> Option<SmallVec<[SyntaxNodePtr; 1]>> {
4550
let token = token_from_offset(file, offset)?;
4651
let parent = token.parent()?;
4752

4853
if let Some(name) = ast::Name::cast(parent.clone()) {
49-
return Some(SyntaxNodePtr::new(name.syntax()));
54+
return Some(smallvec![SyntaxNodePtr::new(name.syntax())]);
5055
}
5156

5257
if let Some(name_ref) = ast::NameRef::cast(parent.clone()) {
53-
// TODO: I think we want to return a list of targets so we can support cases like:
54-
// select * from t join u using (id);
55-
// ^ find refs
56-
return resolve::resolve_name_ref(binder, &name_ref)
57-
.and_then(|ptrs| ptrs.into_iter().next());
58+
return resolve::resolve_name_ref(binder, &name_ref);
5859
}
5960

6061
None
@@ -143,6 +144,26 @@ table users;
143144
");
144145
}
145146

147+
#[test]
148+
fn join_using_column() {
149+
assert_snapshot!(find_refs("
150+
create table t(id int);
151+
create table u(id int);
152+
select * from t join u using (id$0);
153+
"), @r"
154+
β•­β–Έ
155+
2 β”‚ create table t(id int);
156+
β”‚ ── 1. reference
157+
3 β”‚ create table u(id int);
158+
β”‚ ── 2. reference
159+
4 β”‚ select * from t join u using (id);
160+
β”‚ ┬┬
161+
β”‚ β”‚β”‚
162+
β”‚ β”‚0. query
163+
β•°β•΄ 3. reference
164+
");
165+
}
166+
146167
#[test]
147168
fn find_from_definition() {
148169
assert_snapshot!(find_refs("

0 commit comments

Comments
Β (0)