Skip to content

Commit bb41aab

Browse files
authored
feat: Add hover docs for builtin types: (#42)
Adds hover docs to builtin types such as `int`, `string` etc in message fields and methods.
1 parent 7df5ad0 commit bb41aab

6 files changed

+131
-5
lines changed

src/lsp.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ impl LanguageServer for ProtoLanguageServer {
163163
};
164164

165165
let content = self.state.get_content(&uri);
166-
let identifier = tree.get_actionable_node_text_at_position(&pos, content.as_bytes());
166+
let identifier = tree.get_hoverable_node_text_at_position(&pos, content.as_bytes());
167167
let current_package_name = tree.get_package_name(content.as_bytes());
168168

169169
let Some(identifier) = identifier else {

src/parser/tree.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ impl ParsedTree {
6363
.map(|n| n.utf8_text(content.as_ref()).expect("utf-8 parse error"))
6464
}
6565

66+
pub fn get_hoverable_node_text_at_position<'a>(
67+
&'a self,
68+
pos: &Position,
69+
content: &'a [u8],
70+
) -> Option<&'a str> {
71+
let n = self.get_node_at_position(pos)?;
72+
self.get_actionable_node_text_at_position(pos, content)
73+
.or(Some(n.kind()))
74+
}
75+
6676
pub fn get_ancestor_nodes_at_position<'a>(&'a self, pos: &Position) -> Vec<Node<'a>> {
6777
let Some(mut n) = self.get_actionable_node_at_position(pos) else {
6878
return vec![];

src/workspace/hover.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,118 @@
1+
use std::{collections::HashMap, sync::LazyLock};
2+
13
use async_lsp::lsp_types::MarkedString;
24

35
use crate::{
46
formatter::ProtoFormatter, state::ProtoLanguageState, utils::split_identifier_package,
57
};
68

9+
10+
static BUITIN_DOCS: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
11+
HashMap::from([
12+
(
13+
"int32",
14+
r#"A 32-bit integer (varint encoding)
15+
16+
Values of this type range between `-2147483648` and `2147483647`.
17+
Beware that negative values are encoded as five bytes on the wire!"#,
18+
),
19+
(
20+
"int64",
21+
r#"A 64-bit integer (varint encoding)
22+
23+
Values of this type range between `-9223372036854775808` and `9223372036854775807`.
24+
Beware that negative values are encoded as ten bytes on the wire!"#,
25+
),
26+
(
27+
"uint32",
28+
r#"A 32-bit unsigned integer (varint encoding)
29+
30+
Values of this type range between `0` and `4294967295`."#,
31+
),
32+
(
33+
"uint64",
34+
r#"A 64-bit unsigned integer (varint encoding)
35+
36+
Values of this type range between `0` and `18446744073709551615`."#,
37+
),
38+
(
39+
"sint32",
40+
r#"A 32-bit integer (ZigZag encoding)
41+
42+
Values of this type range between `-2147483648` and `2147483647`."#,
43+
),
44+
(
45+
"sint64",
46+
r#"A 64-bit integer (ZigZag encoding)
47+
48+
Values of this type range between `-9223372036854775808` and `9223372036854775807`."#,
49+
),
50+
(
51+
"fixed32",
52+
r#"A 32-bit unsigned integer (4-byte encoding)
53+
54+
Values of this type range between `0` and `4294967295`."#,
55+
),
56+
(
57+
"fixed64",
58+
r#"A 64-bit unsigned integer (8-byte encoding)
59+
60+
Values of this type range between `0` and `18446744073709551615`."#,
61+
),
62+
(
63+
"sfixed32",
64+
r#"A 32-bit integer (4-byte encoding)
65+
66+
Values of this type range between `-2147483648` and `2147483647`."#,
67+
),
68+
(
69+
"sfixed64",
70+
r#"A 64-bit integer (8-byte encoding)
71+
72+
Values of this type range between `-9223372036854775808` and `9223372036854775807`."#,
73+
),
74+
(
75+
"float",
76+
"A single-precision floating point number (IEEE-745.2008 binary32).",
77+
),
78+
(
79+
"double",
80+
"A double-precision floating point number (IEEE-745.2008 binary64).",
81+
),
82+
(
83+
"string",
84+
r#"A string of text.
85+
86+
Stores at most 4GB of text. Intended to be UTF-8 encoded Unicode; use `bytes` if you need other encodings."#,
87+
),
88+
(
89+
"bytes",
90+
r#"A blob of arbitrary bytes.
91+
92+
Stores at most 4GB of binary data. Encoded as base64 in JSON."#,
93+
),
94+
(
95+
"bool",
96+
r#"A Boolean value: `true` or `false`.
97+
98+
Encoded as a single byte: `0x00` or `0xff` (all non-zero bytes decode to `true`)."#,
99+
),
100+
(
101+
"default",
102+
r#"A magic option that specifies the field's default value.
103+
104+
Unlike every other option on a field, this does not have a corresponding field in
105+
`google.protobuf.FieldOptions`; it is implemented by compiler magic."#,
106+
),
107+
])
108+
});
109+
7110
impl<F: ProtoFormatter> ProtoLanguageState<F> {
8111
pub fn hover(&self, curr_package: &str, identifier: &str) -> Vec<MarkedString> {
112+
if let Some(docs) = BUITIN_DOCS.get(identifier) {
113+
return vec![MarkedString::String(docs.to_string())];
114+
}
115+
9116
let (mut package, identifier) = split_identifier_package(identifier);
10117
if package.is_empty() {
11118
package = curr_package;
@@ -42,6 +149,7 @@ mod test {
42149
state.upsert_file(&c_uri, c.to_owned());
43150

44151
assert_yaml_snapshot!(state.hover("com.workspace", "Author"));
152+
assert_yaml_snapshot!(state.hover("com.workspace", "int64"));
45153
assert_yaml_snapshot!(state.hover("com.workspace", "Author.Address"));
46154
assert_yaml_snapshot!(state.hover("com.workspace", "com.utility.Foobar.Baz"));
47155
assert_yaml_snapshot!(state.hover("com.utility", "Baz"));
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
source: src/workspace/hover.rs
3-
expression: "state.hover(\"com.library\", \"Author.Address\")"
3+
expression: "state.hover(\"com.workspace\", \"int64\")"
4+
snapshot_kind: text
45
---
5-
- Address is a Address
6+
- "A 64-bit integer (varint encoding)\n\nValues of this type range between `-9223372036854775808` and `9223372036854775807`.\nBeware that negative values are encoded as ten bytes on the wire!"
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
source: src/workspace/hover.rs
3-
expression: "state.hover(\"com.library\", \"com.utility.Foobar.Baz\")"
3+
expression: "state.hover(\"com.workspace\", \"Author.Address\")"
4+
snapshot_kind: text
45
---
5-
- What is baz?
6+
- Address is a Address
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
source: src/workspace/hover.rs
3+
expression: "state.hover(\"com.utility\", \"Baz\")"
4+
snapshot_kind: text
5+
---
6+
- What is baz?

0 commit comments

Comments
 (0)