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

Add cousin search to goto and hover #1670

Merged
merged 2 commits into from
Oct 12, 2023
Merged

Add cousin search to goto and hover #1670

merged 2 commits into from
Oct 12, 2023

Conversation

jneem
Copy link
Member

@jneem jneem commented Oct 9, 2023

When encountering trees of merges and annotations in the AST, we've been doing some analysis to include "cousins" into the local scope when generating completions. This PR extends this analysis to hover and goto definition/references. For example, hovering over the first foo in the following example now correctly brings up the doc metadata.

{
   inner = { foo = 1 }
} | { inner = { foo | doc "hello" } }

@github-actions github-actions bot temporarily deployed to pull request October 9, 2023 18:25 Inactive
lsp/nls/src/analysis.rs Show resolved Hide resolved
/// If this definition came from a record field, this is the containing
/// record. Note that having a parent record is mutually exclusive with
/// having a non-empty path, because non-empty paths only come from let
/// pattern bindings.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would that make sense to encode this invariant as a type, instead of a comment (a simple enum with maybe some helper functions)?

// We're traversing up the tree starting at the parent, so this is the
// path to the parent (not the original def).
if let Some(parent_path) = ancestors.path() {
let uncles = self.resolve_term_path(&ancestor, parent_path.iter().copied());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the uncles are the other leaf of the merge expression enclosing the current term? I think those method could benefit from being described at a high level in the documentation (even more if they're public API, despite "public API" being a bit less meaningful for NLS)

Comment on lines +135 to +137
// TODO: This usage map is based only on static scoping, and not on our "extended"
// scopes that we build up dynamically based on merges. Improving this probably
// requires building the extended scopes at static analysis time.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What exactly do you mean by that? We don't have dynamic scoping in Nickel, so you can't use a field that isn't part of the record, even if it will be brought by merging later. Or are you talking about context completion, e.g. in the case {foo | String} & { [.] } you would like to provide completion for foo?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For context completion this already works, but one example that doesn't currently work is a "goto references" request for the first foo in

{ foo = 1 } & { bar = foo }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nickel> { foo = 1 } & { bar = foo }
error: unbound identifier `foo`
  ┌─ <repl-input-0>:1:23
  │
1 │ { foo = 1 } & { bar = foo }
  │                       ^^^ this identifier is unbound

Nickel doesn't have dynamic scoping, so this is invalid. Or did you mean {foo = 1} & {bar = foo, foo}, which would be the "valid" version? But then, I think it's ok to go to definition to the foo in the RHS. That's what you would do for a function (say (fun foo => foo) 1, you wouldn't go to 1, I mean you could but it's not really expected from the LSP).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, that's what I get for trying to minimize an example without actually checking it 😅. But yes, currently we go to only the definition on the RHS whereas I'd like to go to both definitions (GotoDefinition can have multiple responses). Also, when asking for References on the LHS foo, I'd like to respond with the RHS foo.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I didn't even know goto definition could show multiple locations (and haven't noticed on Nickel). Now it makes sense, thanks!

@github-actions github-actions bot temporarily deployed to pull request October 12, 2023 18:51 Inactive
@jneem jneem added this pull request to the merge queue Oct 12, 2023
Merged via the queue into master with commit 97e18af Oct 12, 2023
5 checks passed
@jneem jneem deleted the hover-improvements branch October 12, 2023 21:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants