Skip to content

Commit 4ead1d5

Browse files
authored
ide: semantic syntax highlight name refs (#1059)
1 parent 8d72121 commit 4ead1d5

7 files changed

Lines changed: 494 additions & 110 deletions

File tree

crates/squawk_ide/src/find_references.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use crate::binder::Binder;
22
use crate::builtins::{builtins_binder, parse_builtins};
3+
use crate::classify::classify_def_node;
34
use crate::db::{File, bind, parse};
4-
use crate::goto_definition::{FileId, Location};
5+
use crate::goto_definition::{FileId, Location, LocationKind};
56
use crate::offsets::token_from_offset;
67
use crate::resolve;
78
use rowan::TextSize;
@@ -23,7 +24,7 @@ pub fn find_references(db: &dyn Db, file: File, offset: TextSize) -> Vec<Locatio
2324
let builtins_tree = parse_builtins(db).tree();
2425
let builtins_binder = builtins_binder(db);
2526

26-
let Some((target_file, target_defs)) = find_target_defs(
27+
let Some((target_file, target_defs, target_kind)) = find_target_defs(
2728
&source_file,
2829
offset,
2930
&current_binder,
@@ -45,6 +46,7 @@ pub fn find_references(db: &dyn Db, file: File, offset: TextSize) -> Vec<Locatio
4546
refs.push(Location {
4647
file: FileId::Builtins,
4748
range: ptr.to_node(builtins_tree.syntax()).text_range(),
49+
kind: target_kind,
4850
});
4951
}
5052
}
@@ -60,6 +62,7 @@ pub fn find_references(db: &dyn Db, file: File, offset: TextSize) -> Vec<Locatio
6062
refs.push(Location {
6163
file: FileId::Current,
6264
range: name_ref.syntax().text_range(),
65+
kind: target_kind,
6366
});
6467
}
6568
},
@@ -70,6 +73,7 @@ pub fn find_references(db: &dyn Db, file: File, offset: TextSize) -> Vec<Locatio
7073
refs.push(Location {
7174
file: FileId::Current,
7275
range: name.syntax().text_range(),
76+
kind: target_kind,
7377
});
7478
}
7579
},
@@ -88,14 +92,17 @@ fn find_target_defs(
8892
current_binder: &Binder,
8993
builtins_tree: &ast::SourceFile,
9094
builtins_binder: &Binder,
91-
) -> Option<(FileId, SmallVec<[SyntaxNodePtr; 1]>)> {
95+
) -> Option<(FileId, SmallVec<[SyntaxNodePtr; 1]>, LocationKind)> {
9296
let token = token_from_offset(file, offset)?;
9397
let parent = token.parent()?;
9498

95-
if let Some(name) = ast::Name::cast(parent.clone()) {
99+
if let Some(name) = ast::Name::cast(parent.clone())
100+
&& let Some(kind) = classify_def_node(name.syntax()).map(LocationKind::from)
101+
{
96102
return Some((
97103
FileId::Current,
98104
smallvec![SyntaxNodePtr::new(name.syntax())],
105+
kind,
99106
));
100107
}
101108

@@ -105,8 +112,8 @@ fn find_target_defs(
105112
FileId::Current => (current_binder, file.syntax()),
106113
FileId::Builtins => (builtins_binder, builtins_tree.syntax()),
107114
};
108-
if let Some(ptrs) = resolve::resolve_name_ref_ptrs(binder, root, &name_ref) {
109-
return Some((file_id, ptrs));
115+
if let Some((ptrs, kind)) = resolve::resolve_name_ref(binder, root, &name_ref) {
116+
return Some((file_id, ptrs, kind));
110117
}
111118
}
112119
}

crates/squawk_ide/src/goto_definition.rs

Lines changed: 110 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::binder;
22
use crate::builtins::parse_builtins;
3+
use crate::classify::{NameRefClass, classify_def_node};
34
use crate::db::{File, parse};
45
use crate::offsets::token_from_offset;
56
use crate::resolve;
@@ -31,7 +32,10 @@ pub fn goto_definition(db: &dyn Db, file: File, offset: TextSize) -> SmallVec<[L
3132
if let Some(case_expr) = ast::CaseExpr::cast(parent)
3233
&& let Some(case_token) = case_expr.case_token()
3334
{
34-
return smallvec![Location::range(case_token.text_range())];
35+
return smallvec![Location::current(
36+
case_token.text_range(),
37+
LocationKind::CaseExpr
38+
)];
3539
}
3640
}
3741
}
@@ -40,26 +44,28 @@ pub fn goto_definition(db: &dyn Db, file: File, offset: TextSize) -> SmallVec<[L
4044
if ast::Commit::can_cast(parent.kind())
4145
&& let Some(begin_range) = find_preceding_begin(source_file, token.text_range().start())
4246
{
43-
return smallvec![Location::range(begin_range)];
47+
return smallvec![Location::current(begin_range, LocationKind::CommitBegin)];
4448
}
4549

4650
// goto def on ROLLBACK -> BEGIN/START TRANSACTION
4751
if ast::Rollback::can_cast(parent.kind())
4852
&& let Some(begin_range) = find_preceding_begin(source_file, token.text_range().start())
4953
{
50-
return smallvec![Location::range(begin_range)];
54+
return smallvec![Location::current(begin_range, LocationKind::CommitBegin)];
5155
}
5256

5357
// goto def on BEGIN/START TRANSACTION -> COMMIT or ROLLBACK
5458
if ast::Begin::can_cast(parent.kind())
5559
&& let Some(end_range) =
5660
find_following_commit_or_rollback(source_file, token.text_range().end())
5761
{
58-
return smallvec![Location::range(end_range)];
62+
return smallvec![Location::current(end_range, LocationKind::CommitEnd)];
5963
}
6064

61-
if let Some(name) = ast::Name::cast(parent.clone()) {
62-
return smallvec![Location::range(name.syntax().text_range())];
65+
if let Some(name) = ast::Name::cast(parent.clone())
66+
&& let Some(kind) = classify_def_node(name.syntax()).map(LocationKind::from)
67+
{
68+
return smallvec![Location::current(name.syntax().text_range(), kind)];
6369
}
6470

6571
if let Some(name_ref) = ast::NameRef::cast(parent.clone()) {
@@ -71,13 +77,14 @@ pub fn goto_definition(db: &dyn Db, file: File, offset: TextSize) -> SmallVec<[L
7177
// TODO: we should salsa this
7278
let binder_output = binder::bind(file);
7379
let root = file.syntax();
74-
if let Some(ptrs) = resolve::resolve_name_ref_ptrs(&binder_output, root, &name_ref) {
80+
if let Some((ptrs, kind)) = resolve::resolve_name_ref(&binder_output, root, &name_ref) {
7581
let ranges = ptrs
7682
.iter()
7783
.map(|ptr| ptr.to_node(file.syntax()).text_range())
7884
.map(|range| Location {
7985
file: file_id,
8086
range,
87+
kind,
8188
})
8289
.collect();
8390
return ranges;
@@ -106,6 +113,7 @@ pub fn goto_definition(db: &dyn Db, file: File, offset: TextSize) -> SmallVec<[L
106113
return smallvec![Location {
107114
file: file_id,
108115
range: ptr.to_node(file.syntax()).text_range(),
116+
kind: LocationKind::Type,
109117
}];
110118
}
111119
}
@@ -120,17 +128,111 @@ pub enum FileId {
120128
Builtins,
121129
}
122130

131+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
132+
pub enum LocationKind {
133+
Aggregate,
134+
CaseExpr,
135+
Channel,
136+
Column,
137+
CommitBegin,
138+
CommitEnd,
139+
Cursor,
140+
Database,
141+
EventTrigger,
142+
Extension,
143+
Function,
144+
Index,
145+
NamedArgParameter,
146+
Policy,
147+
PreparedStatement,
148+
Procedure,
149+
Role,
150+
Schema,
151+
Sequence,
152+
Server,
153+
Table,
154+
Tablespace,
155+
Trigger,
156+
Type,
157+
View,
158+
Window,
159+
}
160+
123161
#[derive(Debug, Clone, PartialEq, Eq)]
124162
pub struct Location {
125163
pub file: FileId,
126164
pub range: TextRange,
165+
pub kind: LocationKind,
127166
}
128167

129168
impl Location {
130-
fn range(range: TextRange) -> Location {
169+
fn current(range: TextRange, kind: LocationKind) -> Location {
131170
Location {
132171
file: FileId::Current,
133172
range,
173+
kind,
174+
}
175+
}
176+
}
177+
178+
impl From<NameRefClass> for LocationKind {
179+
fn from(class: NameRefClass) -> Self {
180+
match class {
181+
NameRefClass::Aggregate => LocationKind::Aggregate,
182+
NameRefClass::Channel => LocationKind::Channel,
183+
NameRefClass::Cursor => LocationKind::Cursor,
184+
NameRefClass::Database => LocationKind::Database,
185+
NameRefClass::EventTrigger => LocationKind::EventTrigger,
186+
NameRefClass::Extension => LocationKind::Extension,
187+
NameRefClass::Index => LocationKind::Index,
188+
NameRefClass::NamedArgParameter => LocationKind::NamedArgParameter,
189+
NameRefClass::Policy => LocationKind::Policy,
190+
NameRefClass::PreparedStatement => LocationKind::PreparedStatement,
191+
NameRefClass::Role => LocationKind::Role,
192+
NameRefClass::Schema => LocationKind::Schema,
193+
NameRefClass::Sequence => LocationKind::Sequence,
194+
NameRefClass::Server => LocationKind::Server,
195+
NameRefClass::Tablespace => LocationKind::Tablespace,
196+
NameRefClass::Trigger => LocationKind::Trigger,
197+
NameRefClass::Type => LocationKind::Type,
198+
NameRefClass::View => LocationKind::View,
199+
NameRefClass::Window => LocationKind::Window,
200+
201+
NameRefClass::CallProcedure | NameRefClass::Procedure | NameRefClass::ProcedureCall => {
202+
LocationKind::Procedure
203+
}
204+
205+
NameRefClass::Function
206+
| NameRefClass::FunctionCall
207+
| NameRefClass::FunctionName
208+
| NameRefClass::Routine
209+
| NameRefClass::SelectFunctionCall => LocationKind::Function,
210+
211+
NameRefClass::AlterColumn
212+
| NameRefClass::CompositeTypeField
213+
| NameRefClass::ConstraintColumn
214+
| NameRefClass::CreateIndexColumn
215+
| NameRefClass::DeleteColumn
216+
| NameRefClass::ForeignKeyColumn
217+
| NameRefClass::InsertColumn
218+
| NameRefClass::JoinUsingColumn
219+
| NameRefClass::MergeColumn
220+
| NameRefClass::PolicyColumn
221+
| NameRefClass::QualifiedColumn
222+
| NameRefClass::SelectColumn
223+
| NameRefClass::SelectQualifiedColumn
224+
| NameRefClass::UpdateColumn => LocationKind::Column,
225+
226+
NameRefClass::DeleteQualifiedColumnTable
227+
| NameRefClass::ForeignKeyTable
228+
| NameRefClass::FromTable
229+
| NameRefClass::InsertQualifiedColumnTable
230+
| NameRefClass::LikeTable
231+
| NameRefClass::MergeQualifiedColumnTable
232+
| NameRefClass::PolicyQualifiedColumnTable
233+
| NameRefClass::SelectQualifiedColumnTable
234+
| NameRefClass::Table
235+
| NameRefClass::UpdateQualifiedColumnTable => LocationKind::Table,
134236
}
135237
}
136238
}

0 commit comments

Comments
 (0)