Skip to content

Commit e2a2ee7

Browse files
feat: hover on types (#557)
1 parent 8d8076c commit e2a2ee7

File tree

22 files changed

+535
-75
lines changed

22 files changed

+535
-75
lines changed

crates/pgt_completions/src/relevance/filtering.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ impl CompletionFilter<'_> {
163163
// only autocomplete left side of binary expression
164164
WrappingClause::Where => {
165165
ctx.before_cursor_matches_kind(&["keyword_and", "keyword_where"])
166-
|| (ctx.before_cursor_matches_kind(&["."])
166+
|| (ctx.before_cursor_matches_kind(&["field_qualifier"])
167167
&& ctx.matches_ancestor_history(&["field"]))
168168
}
169169

crates/pgt_hover/src/hoverables/column.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
11
use std::fmt::Write;
22

3-
use pgt_schema_cache::Column;
3+
use pgt_schema_cache::{Column, SchemaCache};
44
use pgt_treesitter::TreesitterContext;
55

66
use crate::{contextual_priority::ContextualPriority, to_markdown::ToHoverMarkdown};
77

88
impl ToHoverMarkdown for pgt_schema_cache::Column {
9-
fn hover_headline<W: Write>(&self, writer: &mut W) -> Result<(), std::fmt::Error> {
9+
fn hover_headline<W: Write>(
10+
&self,
11+
writer: &mut W,
12+
_schema_cache: &SchemaCache,
13+
) -> Result<(), std::fmt::Error> {
1014
write!(
1115
writer,
1216
"`{}.{}.{}`",
1317
self.schema_name, self.table_name, self.name
1418
)
1519
}
1620

17-
fn hover_body<W: Write>(&self, writer: &mut W) -> Result<bool, std::fmt::Error> {
21+
fn hover_body<W: Write>(
22+
&self,
23+
writer: &mut W,
24+
_schema_cache: &SchemaCache,
25+
) -> Result<bool, std::fmt::Error> {
1826
if let Some(comment) = &self.comment {
1927
write!(writer, "Comment: '{}'", comment)?;
2028
writeln!(writer)?;
@@ -46,7 +54,11 @@ impl ToHoverMarkdown for pgt_schema_cache::Column {
4654
Ok(true)
4755
}
4856

49-
fn hover_footer<W: Write>(&self, writer: &mut W) -> Result<bool, std::fmt::Error> {
57+
fn hover_footer<W: Write>(
58+
&self,
59+
writer: &mut W,
60+
_schema_cache: &SchemaCache,
61+
) -> Result<bool, std::fmt::Error> {
5062
if let Some(default) = &self.default_expr {
5163
writeln!(writer)?;
5264
write!(writer, "Default: {}", default)?;

crates/pgt_hover/src/hoverables/function.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::fmt::Write;
22

3-
use pgt_schema_cache::Function;
3+
use pgt_schema_cache::{Function, SchemaCache};
44
use pgt_treesitter::TreesitterContext;
55

66
use crate::{contextual_priority::ContextualPriority, to_markdown::ToHoverMarkdown};
@@ -10,7 +10,11 @@ impl ToHoverMarkdown for Function {
1010
"sql"
1111
}
1212

13-
fn hover_headline<W: Write>(&self, writer: &mut W) -> Result<(), std::fmt::Error> {
13+
fn hover_headline<W: Write>(
14+
&self,
15+
writer: &mut W,
16+
_schema_cache: &SchemaCache,
17+
) -> Result<(), std::fmt::Error> {
1418
write!(writer, "`{}.{}", self.schema, self.name)?;
1519

1620
if let Some(args) = &self.argument_types {
@@ -28,7 +32,11 @@ impl ToHoverMarkdown for Function {
2832
Ok(())
2933
}
3034

31-
fn hover_body<W: Write>(&self, writer: &mut W) -> Result<bool, std::fmt::Error> {
35+
fn hover_body<W: Write>(
36+
&self,
37+
writer: &mut W,
38+
_schema_cache: &SchemaCache,
39+
) -> Result<bool, std::fmt::Error> {
3240
let kind_text = match self.kind {
3341
pgt_schema_cache::ProcKind::Function => "Function",
3442
pgt_schema_cache::ProcKind::Procedure => "Procedure",
@@ -55,7 +63,11 @@ impl ToHoverMarkdown for Function {
5563
Ok(true)
5664
}
5765

58-
fn hover_footer<W: Write>(&self, writer: &mut W) -> Result<bool, std::fmt::Error> {
66+
fn hover_footer<W: Write>(
67+
&self,
68+
writer: &mut W,
69+
_schema_cache: &SchemaCache,
70+
) -> Result<bool, std::fmt::Error> {
5971
if let Some(def) = self.definition.as_ref() {
6072
/*
6173
* We don't want to show 250 lines of functions to the user.

crates/pgt_hover/src/hoverables/mod.rs

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
use pgt_schema_cache::SchemaCache;
2+
13
use crate::{contextual_priority::ContextualPriority, to_markdown::ToHoverMarkdown};
24

35
mod column;
46
mod function;
7+
mod postgres_type;
58
mod role;
69
mod schema;
710
mod table;
@@ -16,6 +19,7 @@ pub enum Hoverable<'a> {
1619
Function(&'a pgt_schema_cache::Function),
1720
Role(&'a pgt_schema_cache::Role),
1821
Schema(&'a pgt_schema_cache::Schema),
22+
PostgresType(&'a pgt_schema_cache::PostgresType),
1923
}
2024

2125
impl<'a> From<&'a pgt_schema_cache::Schema> for Hoverable<'a> {
@@ -48,6 +52,12 @@ impl<'a> From<&'a pgt_schema_cache::Role> for Hoverable<'a> {
4852
}
4953
}
5054

55+
impl<'a> From<&'a pgt_schema_cache::PostgresType> for Hoverable<'a> {
56+
fn from(value: &'a pgt_schema_cache::PostgresType) -> Self {
57+
Hoverable::PostgresType(value)
58+
}
59+
}
60+
5161
impl ContextualPriority for Hoverable<'_> {
5262
fn relevance_score(&self, ctx: &pgt_treesitter::TreesitterContext) -> f32 {
5363
match self {
@@ -56,38 +66,76 @@ impl ContextualPriority for Hoverable<'_> {
5666
Hoverable::Function(function) => function.relevance_score(ctx),
5767
Hoverable::Role(role) => role.relevance_score(ctx),
5868
Hoverable::Schema(schema) => schema.relevance_score(ctx),
69+
Hoverable::PostgresType(type_) => type_.relevance_score(ctx),
5970
}
6071
}
6172
}
6273

6374
impl ToHoverMarkdown for Hoverable<'_> {
64-
fn hover_headline<W: std::fmt::Write>(&self, writer: &mut W) -> Result<(), std::fmt::Error> {
75+
fn hover_headline<W: std::fmt::Write>(
76+
&self,
77+
writer: &mut W,
78+
schema_cache: &SchemaCache,
79+
) -> Result<(), std::fmt::Error> {
6580
match self {
66-
Hoverable::Table(table) => ToHoverMarkdown::hover_headline(*table, writer),
67-
Hoverable::Column(column) => ToHoverMarkdown::hover_headline(*column, writer),
68-
Hoverable::Function(function) => ToHoverMarkdown::hover_headline(*function, writer),
69-
Hoverable::Role(role) => ToHoverMarkdown::hover_headline(*role, writer),
70-
Hoverable::Schema(schema) => ToHoverMarkdown::hover_headline(*schema, writer),
81+
Hoverable::Table(table) => {
82+
ToHoverMarkdown::hover_headline(*table, writer, schema_cache)
83+
}
84+
Hoverable::Column(column) => {
85+
ToHoverMarkdown::hover_headline(*column, writer, schema_cache)
86+
}
87+
Hoverable::Function(function) => {
88+
ToHoverMarkdown::hover_headline(*function, writer, schema_cache)
89+
}
90+
Hoverable::Role(role) => ToHoverMarkdown::hover_headline(*role, writer, schema_cache),
91+
Hoverable::Schema(schema) => {
92+
ToHoverMarkdown::hover_headline(*schema, writer, schema_cache)
93+
}
94+
Hoverable::PostgresType(type_) => {
95+
ToHoverMarkdown::hover_headline(*type_, writer, schema_cache)
96+
}
7197
}
7298
}
7399

74-
fn hover_body<W: std::fmt::Write>(&self, writer: &mut W) -> Result<bool, std::fmt::Error> {
100+
fn hover_body<W: std::fmt::Write>(
101+
&self,
102+
writer: &mut W,
103+
schema_cache: &SchemaCache,
104+
) -> Result<bool, std::fmt::Error> {
75105
match self {
76-
Hoverable::Table(table) => ToHoverMarkdown::hover_body(*table, writer),
77-
Hoverable::Column(column) => ToHoverMarkdown::hover_body(*column, writer),
78-
Hoverable::Function(function) => ToHoverMarkdown::hover_body(*function, writer),
79-
Hoverable::Role(role) => ToHoverMarkdown::hover_body(*role, writer),
80-
Hoverable::Schema(schema) => ToHoverMarkdown::hover_body(*schema, writer),
106+
Hoverable::Table(table) => ToHoverMarkdown::hover_body(*table, writer, schema_cache),
107+
Hoverable::Column(column) => ToHoverMarkdown::hover_body(*column, writer, schema_cache),
108+
Hoverable::Function(function) => {
109+
ToHoverMarkdown::hover_body(*function, writer, schema_cache)
110+
}
111+
Hoverable::Role(role) => ToHoverMarkdown::hover_body(*role, writer, schema_cache),
112+
Hoverable::Schema(schema) => ToHoverMarkdown::hover_body(*schema, writer, schema_cache),
113+
Hoverable::PostgresType(type_) => {
114+
ToHoverMarkdown::hover_body(*type_, writer, schema_cache)
115+
}
81116
}
82117
}
83118

84-
fn hover_footer<W: std::fmt::Write>(&self, writer: &mut W) -> Result<bool, std::fmt::Error> {
119+
fn hover_footer<W: std::fmt::Write>(
120+
&self,
121+
writer: &mut W,
122+
schema_cache: &SchemaCache,
123+
) -> Result<bool, std::fmt::Error> {
85124
match self {
86-
Hoverable::Table(table) => ToHoverMarkdown::hover_footer(*table, writer),
87-
Hoverable::Column(column) => ToHoverMarkdown::hover_footer(*column, writer),
88-
Hoverable::Function(function) => ToHoverMarkdown::hover_footer(*function, writer),
89-
Hoverable::Role(role) => ToHoverMarkdown::hover_footer(*role, writer),
90-
Hoverable::Schema(schema) => ToHoverMarkdown::hover_footer(*schema, writer),
125+
Hoverable::Table(table) => ToHoverMarkdown::hover_footer(*table, writer, schema_cache),
126+
Hoverable::Column(column) => {
127+
ToHoverMarkdown::hover_footer(*column, writer, schema_cache)
128+
}
129+
Hoverable::Function(function) => {
130+
ToHoverMarkdown::hover_footer(*function, writer, schema_cache)
131+
}
132+
Hoverable::Role(role) => ToHoverMarkdown::hover_footer(*role, writer, schema_cache),
133+
Hoverable::Schema(schema) => {
134+
ToHoverMarkdown::hover_footer(*schema, writer, schema_cache)
135+
}
136+
Hoverable::PostgresType(type_) => {
137+
ToHoverMarkdown::hover_footer(*type_, writer, schema_cache)
138+
}
91139
}
92140
}
93141

@@ -98,6 +146,7 @@ impl ToHoverMarkdown for Hoverable<'_> {
98146
Hoverable::Function(function) => function.body_markdown_type(),
99147
Hoverable::Role(role) => role.body_markdown_type(),
100148
Hoverable::Schema(schema) => schema.body_markdown_type(),
149+
Hoverable::PostgresType(type_) => type_.body_markdown_type(),
101150
}
102151
}
103152

@@ -108,6 +157,7 @@ impl ToHoverMarkdown for Hoverable<'_> {
108157
Hoverable::Function(function) => function.footer_markdown_type(),
109158
Hoverable::Role(role) => role.footer_markdown_type(),
110159
Hoverable::Schema(schema) => schema.footer_markdown_type(),
160+
Hoverable::PostgresType(type_) => type_.footer_markdown_type(),
111161
}
112162
}
113163
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
use std::fmt::Write;
2+
3+
use pgt_schema_cache::{PostgresType, SchemaCache};
4+
use pgt_treesitter::TreesitterContext;
5+
6+
use crate::{contextual_priority::ContextualPriority, to_markdown::ToHoverMarkdown};
7+
8+
impl ToHoverMarkdown for PostgresType {
9+
fn hover_headline<W: Write>(
10+
&self,
11+
writer: &mut W,
12+
_schema_cache: &SchemaCache,
13+
) -> Result<(), std::fmt::Error> {
14+
write!(writer, "`{}.{}` (Custom Type)", self.schema, self.name)?;
15+
Ok(())
16+
}
17+
18+
fn hover_body<W: Write>(
19+
&self,
20+
writer: &mut W,
21+
schema_cache: &SchemaCache,
22+
) -> Result<bool, std::fmt::Error> {
23+
if let Some(comment) = &self.comment {
24+
write!(writer, "Comment: '{}'", comment)?;
25+
writeln!(writer)?;
26+
writeln!(writer)?;
27+
}
28+
29+
if !self.attributes.attrs.is_empty() {
30+
write!(writer, "Attributes:")?;
31+
writeln!(writer)?;
32+
33+
for attribute in &self.attributes.attrs {
34+
write!(writer, "- {}", attribute.name)?;
35+
36+
if let Some(type_info) = schema_cache.find_type_by_id(attribute.type_id) {
37+
write!(writer, ": ")?;
38+
39+
if type_info.schema != "pg_catalog" {
40+
write!(writer, "{}.", type_info.schema)?;
41+
}
42+
43+
write!(writer, "{}", type_info.name)?;
44+
} else {
45+
write!(writer, " (type_id: {})", attribute.type_id)?;
46+
}
47+
48+
writeln!(writer)?;
49+
}
50+
51+
writeln!(writer)?;
52+
}
53+
54+
if !self.enums.values.is_empty() {
55+
write!(writer, "Enum Permutations:")?;
56+
writeln!(writer)?;
57+
58+
for kind in &self.enums.values {
59+
write!(writer, "- {}", kind)?;
60+
writeln!(writer)?;
61+
}
62+
63+
writeln!(writer)?;
64+
}
65+
66+
Ok(true)
67+
}
68+
69+
fn hover_footer<W: Write>(
70+
&self,
71+
writer: &mut W,
72+
_schema_cache: &SchemaCache,
73+
) -> Result<bool, std::fmt::Error> {
74+
writeln!(writer)?;
75+
Ok(true)
76+
}
77+
}
78+
79+
impl ContextualPriority for PostgresType {
80+
// there are no schemas with duplicate names.
81+
fn relevance_score(&self, ctx: &TreesitterContext) -> f32 {
82+
let mut score = 0.0;
83+
84+
if ctx
85+
.get_mentioned_relations(&Some(self.schema.clone()))
86+
.is_some()
87+
{
88+
score += 100.0;
89+
}
90+
91+
if ctx.get_mentioned_relations(&None).is_some() && self.schema == "public" {
92+
score += 100.0;
93+
}
94+
95+
if self.schema == "public" && score == 0.0 {
96+
score += 10.0;
97+
}
98+
99+
score
100+
}
101+
}

crates/pgt_hover/src/hoverables/role.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
use std::fmt::Write;
22

3-
use pgt_schema_cache::Role;
3+
use pgt_schema_cache::{Role, SchemaCache};
44
use pgt_treesitter::TreesitterContext;
55

66
use crate::{contextual_priority::ContextualPriority, to_markdown::ToHoverMarkdown};
77

88
impl ToHoverMarkdown for pgt_schema_cache::Role {
9-
fn hover_headline<W: Write>(&self, writer: &mut W) -> Result<(), std::fmt::Error> {
9+
fn hover_headline<W: Write>(
10+
&self,
11+
writer: &mut W,
12+
_schema_cache: &SchemaCache,
13+
) -> Result<(), std::fmt::Error> {
1014
write!(writer, "`{}`", self.name)?;
1115

1216
Ok(())
1317
}
1418

15-
fn hover_body<W: Write>(&self, writer: &mut W) -> Result<bool, std::fmt::Error> {
19+
fn hover_body<W: Write>(
20+
&self,
21+
writer: &mut W,
22+
_schema_cache: &SchemaCache,
23+
) -> Result<bool, std::fmt::Error> {
1624
if let Some(comm) = self.comment.as_ref() {
1725
write!(writer, "Comment: '{}'", comm)?;
1826
writeln!(writer)?;
@@ -81,7 +89,11 @@ impl ToHoverMarkdown for pgt_schema_cache::Role {
8189
Ok(true)
8290
}
8391

84-
fn hover_footer<W: Write>(&self, _writer: &mut W) -> Result<bool, std::fmt::Error> {
92+
fn hover_footer<W: Write>(
93+
&self,
94+
_writer: &mut W,
95+
_schema_cache: &SchemaCache,
96+
) -> Result<bool, std::fmt::Error> {
8597
Ok(false)
8698
}
8799
}

0 commit comments

Comments
 (0)