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

Implement renaming for Functions, Constants and Type Variants #4282

Open
wants to merge 25 commits into
base: main
Choose a base branch
from

Conversation

GearsDatapacks
Copy link
Member

This PR closes #3259
This is pretty much ready, except for two things:

  • It's missing tests
  • There's an annoying bug to do with module shadowing which I still have to figure out how to resolve

@GearsDatapacks GearsDatapacks force-pushed the cross-module-value-renaming branch 2 times, most recently from 8e78f2c to d4c87d0 Compare February 27, 2025 11:08
@GearsDatapacks GearsDatapacks force-pushed the cross-module-value-renaming branch from d4c87d0 to 1f931b9 Compare February 27, 2025 17:16
@GearsDatapacks
Copy link
Member Author

GearsDatapacks commented Feb 28, 2025

Ok, this is ready for review now. I'm not super happy with the way I fixed the module access shadowing bug, but I couldn't think of another way to do it. Let me know if you have any thoughts.

@GearsDatapacks GearsDatapacks marked this pull request as ready for review February 28, 2025 20:30
Copy link
Member

@lpil lpil left a comment

Choose a reason for hiding this comment

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

Super nice!! I'm really excited about this one.

I've not finished reviewing totally but I've gotta go so I wanted to drop my thoughts so far. See inline notes.

import mod.{Constructor}

pub fn main() {
#(Constructor(75), mod.Constructor(57))
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if when renaming a constructor that has been imported in an unqualified fashion it should alias the import rather than rename it globally.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I wasn't sure about this. Maybe we can ask in Discord and hear other people's opinions on it.

@@ -1064,6 +1073,8 @@ impl<A, B, C, E> Definition<A, B, C, E> {
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct UnqualifiedImport {
pub location: SrcSpan,
/// The location excluding the potential `as ...` clause, or the `type` keyword
pub imported_name_location: SrcSpan,
Copy link
Member

Choose a reason for hiding this comment

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

I think the start here is redundant as it's the same as location, it could be a single position int instead.

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually in the following case: import some_module.{type SomeType as SomeAlias}, the full location contains type SomeType as SomeAlias, whereas the imported_name_location only contains SomeType. Therefore, it is completely separate information to the full location.

change_annotations: None,
};

for module in modules.values() {
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps we should have an import graph so we can get these modules directly rather than traversing everything? Probably doesn't matter. Something for later perhaps.

That aside, this is a hashmap of modules that have been compiled, it does not include any that were loaded from the cache. This means there will be no renaming in any module that have not been recompiled in that editor session!

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah that makes sense. I guess that means we need to store reference information in the module interface and cache it then.
As for an import graph, I'm happy to use one if you want; not exactly sure what that data structure would look like, or how we would build it and where it would be stored.

#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct References {
pub imported_modules: HashSet<EcoString>,
pub value_references: HashMap<(EcoString, EcoString), Vec<SrcSpan>>,
Copy link
Member

Choose a reason for hiding this comment

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

It seems like it may be challenging to identify unused code with this data structure, and replacing the current broken usage tracking system is one of the main goals of the call graph work. Did you have thoughts on how that'd be done?

Copy link
Member Author

Choose a reason for hiding this comment

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

That's true, I wasn't thinking too much about the current usage tracking. We already generate an in-module call-graph for dependency ordering, so would it be possible to use just that for usage tracking? We can't use that for renaming because it doesn't track cross-module usage.

@GearsDatapacks GearsDatapacks marked this pull request as draft March 1, 2025 21:53
@GearsDatapacks
Copy link
Member Author

Ok, I have now added the reference information to the cache so we can rename values in cached modules.
It feels a bit wasteful, it's quite a lot of information which is only needed for the LSP, but I don't think there's any other way around it.
I have responded to a couple of your comments, let me know your thoughts.

@GearsDatapacks GearsDatapacks marked this pull request as ready for review March 2, 2025 12:52
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.

LSP: rename custom type variant
2 participants