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
Display signature when hovering over function definitions or module constants #2302
Display signature when hovering over function definitions or module constants #2302
Conversation
Now hovering over the function body is ignored, and hovering over an argument will display just the type of that argument. Hovering anywhere else in the function head will display the signature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fab! Thank you. I've left a note inline, and we'll need tests for the new functionality.
range: Some(src_span_to_lsp_range(arg.location, &line_numbers)), | ||
}); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This finding logic should live with the other finding logic in node_at_position
. This function is only about showing the information rather than hunting through the AST.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that would involve extending the Located
enum, right? I can have a go at that in the next few days (and also try to write some tests 🤞)
Now the hover_for_... functions don't do a bunch of unpacking of the AST nodes anymore, but it's still happening in the `hover` function. To move the functionality into `node_at_position`, I think we'd have to change the `Located` enum.
} else { | ||
Some(hover_for_function_head(fun, lines)) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This finding logic should go in the node_at_position
functions with the other finding logic that deals with byte indexes and AST. This function here doesn't perform any finding logic, it just maps from a found node to a hover response function.
Sorry, I was unclear previously!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds like the best way to do this, but I wanted to check if my understanding/approach sounds reasonable before I try to do stuff (also this is my first open-source contribution of non-trivial size, so this is a bit scary).
Does this sound right:
node_at_position
should be capable of finding the function head and each function arg. The main type node_at_position
returns is Located
, and I don't think there's a way to represent a function argument in a Located
. So I think I'd add an entry to Located
called Arg(&'a TypedArg)
. Then in TypedDefinition::find_node
, I'd try to return a Located::Arg
if possible, and a Located::ModuleStatement
if not?
(And also I'll look at how to write tests for the new behavior.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup! That's perfect
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is there still some location logic in this function? What is the case in which it is needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The remaining logic is to prevent the function signature coming up when you hover leading/trailing whitespace or comments in the function body. It's essentially undoing the .full_location()
logic in ast.rs
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lpil I added another commit removing all the finding logic from the hover
function by adding a separate FunctionBody
entry to Located
. So now looking at a function head will return Located::ModuleStatement(Definition::Function(fun))
, and looking at the function body will return Located::FunctionBody(fun)
.
I wonder if maybe there should be separate AST nodes for function body and function head.
I think this might be ready for another look. I've tidied things up a bit and added some tests. The main issues now are:
Located::ModuleStatement(Definition::Function(fun)) => {
if fun.location.contains(byte_index) {
Some(hover_for_function_head(fun, lines))
} else {
// Don't show hover info for function body
None
}
} Which could be fixed, but I'm not sure if that would break any assumptions we're making about
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking really nice! I've left a couple tiny questions inline.
Would you mind also updating the CHANGELOG file? Thank you
let empty_smolstr = SmolStr::from(""); | ||
let documentation = fun.documentation.as_ref().unwrap_or(&empty_smolstr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does .unwrap_or_default()
not work here? Or .unwrap_or("".into())
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.unwrap_or_default()
was the first thing I'd tried since you were using it for all the results of .get_documentation()
. That didn't work because .documentation
itself is a SmolStr
, and &SmolStr
doesn't have Default
implemented.
Trying some more stuff, the only other way I can see is
let documentation = fun
.documentation
.as_ref()
.map(|s| s.as_str())
.unwrap_or_default();
which feels "cleaner" in some way, but also less readable?
…-over-function-definition
…-over-function-definition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fantastic!! Thank you so much
Rebase failed
Would you like to rebase the branch to remove the merge commits and conflicts, or should I squash merge? |
Probably easiest if you just squash merge? But I can also do a rebase if that's the preferred workflow |
Works for me! Thanks |
Hi!
I had a go at #2241.
Hovering over constants now displays their type:
And hovering over function definitions displays their signature:
Happy to make any changes you need to this PR :)
Thanks!