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

Improve the "goto definition" feature of the LSP by making it work across multiple files #1029

Merged
merged 7 commits into from
Jan 12, 2023

Conversation

ebresafegaga
Copy link
Contributor

@ebresafegaga ebresafegaga commented Jan 3, 2023

Closes #932

This change adds support for cross file navigation using the "goto reference" feature of the LSP.

@ebresafegaga ebresafegaga self-assigned this Jan 3, 2023
@github-actions github-actions bot temporarily deployed to pull request January 3, 2023 15:24 Inactive
@ebresafegaga ebresafegaga changed the title Improve "goto reference" and "find references" by making them work across multiple files Improve "goto definition" and "find references" by making them work across multiple files Jan 4, 2023
@github-actions github-actions bot temporarily deployed to pull request January 4, 2023 12:41 Inactive
@github-actions github-actions bot temporarily deployed to pull request January 9, 2023 14:26 Inactive
@ebresafegaga ebresafegaga changed the title Improve "goto definition" and "find references" by making them work across multiple files Improve the "goto definition" feature of the LSP by making it work across multiple files Jan 10, 2023
@ebresafegaga ebresafegaga marked this pull request as ready for review January 10, 2023 14:50
Comment on lines 35 to 54
fn get_item_kind_with_id(&self, file: FileId, id: ItemId) -> Option<(&ItemId, &TermKind)> {
if file == id.file_id {
// This usage references an item in the file we're currently linearizing
let item = self.linearization.get(id.index)?;
Some((&item.id, &item.kind))
} else {
// This usage references an item in another file (that has already been linearized)
let item = self
.lin_cache
.get(&id.file_id)?
.get_item(id, self.lin_cache)?;
Some((&item.id, &item.kind))
}
}

fn get_item_kind(&self, file: FileId, id: ItemId) -> Option<&TermKind> {
let (_, kind) = self.get_item_kind_with_id(file, id)?;
Some(kind)
}

Copy link
Member

@yannham yannham Jan 11, 2023

Choose a reason for hiding this comment

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

Would it make sense to have a get_item and get_item_mut functions, as in Completed, rather than those specialized versions? Then the caller could just get the item and decide what to do with it. Here it feels a bit like we are just instantiating a get_item function with some arbitrary post-processing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would it make sense to rather have a get_item and get_item_mut functions, as in Completed, rather than those specialized versions?

That would have been better, but the problem with it is that, with Building, we're not yet done linearizing the current file, so the linearization items in Building have the type LinearizationItem<UnifType>, while the linearization items in the other files would have the type LinearizationItem<Types>, so that will lead to a return type mismatch from the function. I noticed that we only need the TermKind (and in some cases, the ItemId), so this was a nice way to avoid using the whole struct regardless of the generic parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Then the caller could just get the item and decide what to do with it. Here it feels a bit like we are just instantiating a get_item function with some arbitrary post-processing.

Right. It's just a convenience, because we know the caller does just one thing it. But we can change it to avoid the "post-processing"

lsp/nls/src/linearization/building.rs Outdated Show resolved Hide resolved
let (_, kind) = self.get_item_kind_with_id(file, id)?;
Some(kind)
}

fn get_item_kind_mut(&mut self, file: FileId, id: ItemId) -> Option<&mut TermKind> {
Copy link
Member

Choose a reason for hiding this comment

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

Could get rid of this function as well, probably, if having a get_item_mut.

Comment on lines 171 to +172
mut defers: Vec<(ItemId, ItemId, Ident)>,
) {
) -> Vec<(ItemId, ItemId, Ident)> {
Copy link
Member

Choose a reason for hiding this comment

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

What is this new return value doing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It returns a list of items that could not be resolved.

Copy link
Member

Choose a reason for hiding this comment

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

I see. Then it might be valuable to document this function, and in particular what the return value is.

lsp/nls/src/requests/goto.rs Outdated Show resolved Hide resolved
Copy link
Member

@yannham yannham left a comment

Choose a reason for hiding this comment

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

Fair enough for get_item_kind_XXX, if it's used a lot. Do as you see fit, but here is a suggestion though: split the part that fetches the items in separate functions get_item and get_item_mut, and use them from within get_item_kind_xxx. Doing so, we've not added much code (juste moved some parts in dedicated functions), function definitions are smaller, and if we need to get an item for another reason, the methods to do so are already in place.

Comment on lines 171 to +172
mut defers: Vec<(ItemId, ItemId, Ident)>,
) {
) -> Vec<(ItemId, ItemId, Ident)> {
Copy link
Member

Choose a reason for hiding this comment

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

I see. Then it might be valuable to document this function, and in particular what the return value is.

@github-actions github-actions bot temporarily deployed to pull request January 11, 2023 14:44 Inactive
@github-actions github-actions bot temporarily deployed to pull request January 12, 2023 09:45 Inactive
@ebresafegaga ebresafegaga merged commit 8e07351 into master Jan 12, 2023
@ebresafegaga ebresafegaga deleted the lsp/goto branch January 12, 2023 10:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make goto reference work across files
2 participants