Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lsp/inlay hints on pipe #3290

Draft
wants to merge 30 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8f65822
impl inlayHints prototype
ascandone Jun 18, 2024
01cc4f7
impl inlay hints
ascandone Jun 18, 2024
40e3fda
turned inlay hint option on
ascandone Jun 18, 2024
cb25197
avoid showing inlay hints when pipe do not span many lines
ascandone Jun 18, 2024
4d73744
improved inlay hints navigation
ascandone Jun 18, 2024
4657386
iterating nested pipe exprs
ascandone Jun 18, 2024
e790852
completed expr navigation
ascandone Jun 18, 2024
c4c5891
removed todo comment
ascandone Jun 18, 2024
6e882de
renamed functions
ascandone Jun 18, 2024
f60065d
follow clippy suggestions
ascandone Jun 18, 2024
18e7cf3
edit test name
ascandone Jun 20, 2024
5f9e87c
avoid printing inlay hints of simple lits
ascandone Jun 21, 2024
c6fd138
using visitor pattern
ascandone Jun 21, 2024
f43199a
moved modules around
ascandone Jun 21, 2024
33a2d65
moved submodule in separate file
ascandone Jun 21, 2024
a9d916f
implemented config functionality
ascandone Jun 25, 2024
dfdbc0f
minor cleanups
ascandone Jun 25, 2024
388d92d
avoid sending unhandled requests
ascandone Jul 4, 2024
5bb1aa6
changed camel case to snake case
ascandone Jul 20, 2024
102782c
fix rebase
ascandone Jul 30, 2024
18c99af
refactored modules
ascandone Jul 30, 2024
24384da
fix clippy issue
ascandone Jul 30, 2024
fe1c2a3
fixed rebase
ascandone Sep 8, 2024
0b09d80
moved function to TypedExpr methods
ascandone Sep 8, 2024
cc0409b
using serde to parse config
ascandone Sep 8, 2024
9fa355b
cleaner config parsing
ascandone Sep 8, 2024
307060c
testing inlay hints snapshot with default config
ascandone Sep 8, 2024
08cb07b
fixes after rebase
ascandone Sep 8, 2024
0cbefd3
fix clippy issues
ascandone Sep 8, 2024
2966da4
fixes after rebase
ascandone Sep 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
avoid printing inlay hints of simple lits
  • Loading branch information
ascandone committed Sep 20, 2024
commit 5f9e87cc17d09b0d4f5c0128ea3e947f90d8b285
171 changes: 126 additions & 45 deletions compiler-core/src/language_server/inlay_hints.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{
ast::{
Definition, SrcSpan, Statement, TypedDefinition, TypedExpr, TypedModule, TypedStatement,
Definition, SrcSpan, Statement, TypedAssignment, TypedDefinition, TypedExpr, TypedModule,
TypedStatement,
},
line_numbers::LineNumbers,
type_::pretty::Printer,
Expand All @@ -26,6 +27,16 @@ impl<'a> Buf<'a> {
}
}

fn is_simple_lit(expr: &TypedExpr) -> bool {
matches!(
expr,
TypedExpr::Int { .. }
| TypedExpr::Float { .. }
| TypedExpr::String { .. }
| TypedExpr::BitArray { .. }
)
}

impl<'a> Buf<'a> {
pub fn push_inlay_hints_definition(&mut self, typed_def: TypedDefinition) {
if let Definition::Function(f) = typed_def {
Expand All @@ -43,6 +54,56 @@ impl<'a> Buf<'a> {
}
}

fn push_inlay_hints_pipeline(
&mut self,
assignments: Vec<TypedAssignment>,
finally: &TypedExpr,
) {
fn get_this_line(this: &Buf<'_>, span: &SrcSpan) -> u32 {
this.line_numbers.line_and_column_number(span.end).line
}

let mut prev_hint: Option<(u32, Option<InlayHint>)> = None;
for assign in assignments {
let this_line = get_this_line(self, &assign.location);

if let Some((prev_line, prev_hint)) = prev_hint {
if prev_line != this_line {
if let Some(prev_hint) = prev_hint {
self.hints.push(prev_hint);
}
}
};

let this_hint = InlayHint {
label: Printer::new().pretty_print(assign.type_().as_ref(), 0),
offset: assign.location.end,
};
prev_hint = Some((
this_line,
if is_simple_lit(&assign.value) {
None
} else {
Some(this_hint)
},
));
self.push_inlay_hints_expr(*assign.value);
}

if let Some((prev_line, prev_hint)) = prev_hint {
let this_line = get_this_line(self, &finally.location());
if this_line != prev_line {
if let Some(prev_hint) = prev_hint {
self.hints.push(prev_hint);
}
self.hints.push(InlayHint {
label: Printer::new().pretty_print(finally.type_().as_ref(), 0),
offset: finally.location().end,
});
}
}
}

fn push_inlay_hints_expr(&mut self, typed_st: TypedExpr) {
match typed_st {
TypedExpr::Int { .. }
Expand All @@ -59,42 +120,7 @@ impl<'a> Buf<'a> {
assignments,
finally,
} => {
fn get_this_line(this: &Buf<'_>, span: &SrcSpan) -> u32 {
this.line_numbers.line_and_column_number(span.end).line
}

let mut prev_hint = None;

for assign in assignments {
let str_type = Printer::new().pretty_print(assign.type_().as_ref(), 0);

let this_line = get_this_line(self, &assign.location);

if let Some((prev_line, prev_hint)) = prev_hint {
if prev_line != this_line {
self.hints.push(prev_hint);
}
};

let this_hint = InlayHint {
label: str_type,
offset: assign.location.end,
};
prev_hint = Some((this_line, this_hint));
self.push_inlay_hints_expr(*assign.value);
}

let (prev_line, prev_hint) = prev_hint.expect("Expected a non-empty arr");
let this_line = get_this_line(self, &finally.location());
if this_line != prev_line {
let str_type_finally = Printer::new().pretty_print(finally.type_().as_ref(), 0);
self.hints.push(prev_hint);
self.hints.push(InlayHint {
label: str_type_finally,
offset: finally.location().end,
})
}

self.push_inlay_hints_pipeline(assignments, &finally);
self.push_inlay_hints_expr(*finally);
}

Expand Down Expand Up @@ -211,9 +237,58 @@ mod tests {
assert_inlay_hints(src, vec![]);
}

#[test]
fn no_hints_when_value_is_literal() {
let src = r#"
pub fn ret_str(f1) {
"abc"
|> f1()
}

pub fn ret_int(f2) {
42
|> f2()
}

pub fn ret_float(f3) {
42.2
|> f3()
}

pub fn ret_bit_array(f4) {
<<1, 2>>
|> f4()
}
"#;

assert_inlay_hints(
src,
vec![
InlayHint {
label: "a".to_string(),
offset: index_of_end(src, "|> f1()"),
},
InlayHint {
label: "a".to_string(),
offset: index_of_end(src, "|> f2()"),
},
InlayHint {
label: "a".to_string(),
offset: index_of_end(src, "|> f3()"),
},
InlayHint {
label: "a".to_string(),
offset: index_of_end(src, "|> f4()"),
},
],
);
}

#[test]
fn show_many_hints() {
let src = r#"
const int_val = 0

fn identity(x) {
x
}
Expand All @@ -223,7 +298,7 @@ mod tests {
}

pub fn example_pipe() {
0
int_val
|> ret_str()
|> identity()
}
Expand All @@ -234,7 +309,7 @@ mod tests {
vec![
InlayHint {
label: "Int".to_string(),
offset: index_of_end(src, "0"),
offset: index_of_end(src, " int_val"),
},
InlayHint {
label: "String".to_string(),
Expand All @@ -251,14 +326,16 @@ mod tests {
#[test]
fn hints_nested_in_case_block() {
let src = r#"
const int_val = 0

fn identity(x) {
x
}

fn main(a) {
case a {
_ -> {
0
int_val
|> identity()
}
}
Expand All @@ -270,7 +347,7 @@ mod tests {
vec![
InlayHint {
label: "Int".to_string(),
offset: index_of_end(src, "0"),
offset: index_of_end(src, " int_val"),
},
InlayHint {
label: "Int".to_string(),
Expand All @@ -283,13 +360,15 @@ mod tests {
#[test]
fn hints_nested_for_apply_fn_let() {
let src = r#"
const int_val = 0

fn identity(x) {
x
}

fn main() {
let f = identity(fn() {
0
int_val
|> identity()
})
}
Expand All @@ -300,7 +379,7 @@ mod tests {
vec![
InlayHint {
label: "Int".to_string(),
offset: index_of_end(src, "0"),
offset: index_of_end(src, " int_val"),
},
InlayHint {
label: "Int".to_string(),
Expand All @@ -313,13 +392,15 @@ mod tests {
#[test]
fn hints_in_use() {
let src = r#"
const int_val = 0

fn identity(x) {
x
}

fn main(f) {
use a <- f()
0
int_val
|> identity()
}
"#;
Expand All @@ -329,7 +410,7 @@ mod tests {
vec![
InlayHint {
label: "Int".to_string(),
offset: index_of_end(src, "0"),
offset: index_of_end(src, " int_val"),
},
InlayHint {
label: "Int".to_string(),
Expand Down
7 changes: 4 additions & 3 deletions compiler-core/src/language_server/tests/inlay_hints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,20 @@ use lsp_types::{
#[test]
fn render_inlay_hints() {
ascandone marked this conversation as resolved.
Show resolved Hide resolved
let code = "
fn get_int() { 42 }
fn to_str(x) { \"abc\" }

fn main() {
42
get_int()
|> to_str()
}
";

expect_hints(
code,
vec![
default_hint(Position::new(4, 6), "Int"),
default_hint(Position::new(5, 15), "String"),
default_hint(Position::new(5, 13), "Int"),
default_hint(Position::new(6, 15), "String"),
],
);
}
Expand Down