Skip to content

Commit

Permalink
feat: Add hover docs for builtin types: (#42)
Browse files Browse the repository at this point in the history
Adds hover docs to builtin types such as `int`, `string` etc in message
fields and methods.
  • Loading branch information
coder3101 authored Dec 26, 2024
1 parent 7df5ad0 commit bb41aab
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ impl LanguageServer for ProtoLanguageServer {
};

let content = self.state.get_content(&uri);
let identifier = tree.get_actionable_node_text_at_position(&pos, content.as_bytes());
let identifier = tree.get_hoverable_node_text_at_position(&pos, content.as_bytes());
let current_package_name = tree.get_package_name(content.as_bytes());

let Some(identifier) = identifier else {
Expand Down
10 changes: 10 additions & 0 deletions src/parser/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ impl ParsedTree {
.map(|n| n.utf8_text(content.as_ref()).expect("utf-8 parse error"))
}

pub fn get_hoverable_node_text_at_position<'a>(
&'a self,
pos: &Position,
content: &'a [u8],
) -> Option<&'a str> {
let n = self.get_node_at_position(pos)?;
self.get_actionable_node_text_at_position(pos, content)
.or(Some(n.kind()))
}

pub fn get_ancestor_nodes_at_position<'a>(&'a self, pos: &Position) -> Vec<Node<'a>> {
let Some(mut n) = self.get_actionable_node_at_position(pos) else {
return vec![];
Expand Down
108 changes: 108 additions & 0 deletions src/workspace/hover.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,118 @@
use std::{collections::HashMap, sync::LazyLock};

use async_lsp::lsp_types::MarkedString;

use crate::{
formatter::ProtoFormatter, state::ProtoLanguageState, utils::split_identifier_package,
};


static BUITIN_DOCS: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
HashMap::from([
(
"int32",
r#"A 32-bit integer (varint encoding)
Values of this type range between `-2147483648` and `2147483647`.
Beware that negative values are encoded as five bytes on the wire!"#,
),
(
"int64",
r#"A 64-bit integer (varint encoding)
Values of this type range between `-9223372036854775808` and `9223372036854775807`.
Beware that negative values are encoded as ten bytes on the wire!"#,
),
(
"uint32",
r#"A 32-bit unsigned integer (varint encoding)
Values of this type range between `0` and `4294967295`."#,
),
(
"uint64",
r#"A 64-bit unsigned integer (varint encoding)
Values of this type range between `0` and `18446744073709551615`."#,
),
(
"sint32",
r#"A 32-bit integer (ZigZag encoding)
Values of this type range between `-2147483648` and `2147483647`."#,
),
(
"sint64",
r#"A 64-bit integer (ZigZag encoding)
Values of this type range between `-9223372036854775808` and `9223372036854775807`."#,
),
(
"fixed32",
r#"A 32-bit unsigned integer (4-byte encoding)
Values of this type range between `0` and `4294967295`."#,
),
(
"fixed64",
r#"A 64-bit unsigned integer (8-byte encoding)
Values of this type range between `0` and `18446744073709551615`."#,
),
(
"sfixed32",
r#"A 32-bit integer (4-byte encoding)
Values of this type range between `-2147483648` and `2147483647`."#,
),
(
"sfixed64",
r#"A 64-bit integer (8-byte encoding)
Values of this type range between `-9223372036854775808` and `9223372036854775807`."#,
),
(
"float",
"A single-precision floating point number (IEEE-745.2008 binary32).",
),
(
"double",
"A double-precision floating point number (IEEE-745.2008 binary64).",
),
(
"string",
r#"A string of text.
Stores at most 4GB of text. Intended to be UTF-8 encoded Unicode; use `bytes` if you need other encodings."#,
),
(
"bytes",
r#"A blob of arbitrary bytes.
Stores at most 4GB of binary data. Encoded as base64 in JSON."#,
),
(
"bool",
r#"A Boolean value: `true` or `false`.
Encoded as a single byte: `0x00` or `0xff` (all non-zero bytes decode to `true`)."#,
),
(
"default",
r#"A magic option that specifies the field's default value.
Unlike every other option on a field, this does not have a corresponding field in
`google.protobuf.FieldOptions`; it is implemented by compiler magic."#,
),
])
});

impl<F: ProtoFormatter> ProtoLanguageState<F> {
pub fn hover(&self, curr_package: &str, identifier: &str) -> Vec<MarkedString> {
if let Some(docs) = BUITIN_DOCS.get(identifier) {
return vec![MarkedString::String(docs.to_string())];
}

let (mut package, identifier) = split_identifier_package(identifier);
if package.is_empty() {
package = curr_package;
Expand Down Expand Up @@ -42,6 +149,7 @@ mod test {
state.upsert_file(&c_uri, c.to_owned());

assert_yaml_snapshot!(state.hover("com.workspace", "Author"));
assert_yaml_snapshot!(state.hover("com.workspace", "int64"));
assert_yaml_snapshot!(state.hover("com.workspace", "Author.Address"));
assert_yaml_snapshot!(state.hover("com.workspace", "com.utility.Foobar.Baz"));
assert_yaml_snapshot!(state.hover("com.utility", "Baz"));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
source: src/workspace/hover.rs
expression: "state.hover(\"com.library\", \"Author.Address\")"
expression: "state.hover(\"com.workspace\", \"int64\")"
snapshot_kind: text
---
- Address is a Address
- "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!"
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
source: src/workspace/hover.rs
expression: "state.hover(\"com.library\", \"com.utility.Foobar.Baz\")"
expression: "state.hover(\"com.workspace\", \"Author.Address\")"
snapshot_kind: text
---
- What is baz?
- Address is a Address
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
source: src/workspace/hover.rs
expression: "state.hover(\"com.utility\", \"Baz\")"
snapshot_kind: text
---
- What is baz?

0 comments on commit bb41aab

Please sign in to comment.