-
-
Notifications
You must be signed in to change notification settings - Fork 868
Allow renaming module from ModuleSelect
#4750
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
base: main
Are you sure you want to change the base?
Conversation
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.
Brilliant, thank you. This will be really nice.
I've left some notes inline, thank you
Hello! Just figuring out what is going to go into what release. Are you still working on this? :) |
Yes I am! As for a progress update, most tests are written but still need to write some for guard clause and record access with same name as module. From what I can tell and have tested, all references to the module (alias) can be found and are appropriately renamed but it can't yet be renamed from every reference. |
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.
Thank you! This is looking fab!
I've not finished reviewing this yet, the snapshots are quite a bit more verbose than we usually go for, so it is taking me longer than usual and I've run out of time, but my comments so far should be useful if not complete.
It would be fab if the tests could be slimmed down to make them more focused- I've left some comments inline on that theme.
I think there's some repetition with the test also, with multiple tests testing the use of the AST visitor reaching everywhere.
I've not yet found any test for nested modules, if there are none we want those too.
Thanks again! Looking really nice, it'll be very nice to have this functionality in the language server.
.iter() | ||
.zip(elements_type.iter()) | ||
.for_each(|(e, type_)| self.visit_type_ast(e, type_)); | ||
} |
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.
If the tuple AST must always have a tuple type then panic in the case that it does not instead of silently skipping over the malformed code. We want to know when there is a bug.
Could it be linked here? Do the links need to be collapsed?
self.visit_type_ast(return_, ret_type); | ||
} | ||
} | ||
_ => {} |
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.
Same as above- no catch alls, panic for impossible invariants, and what about links?
|
||
-- app.gleam | ||
import mod | ||
fn func() { let _: fn(mod.GenericType(mod.Type)) -> mod.GenericType(mod.Type) = fn(arg: mod.GenericType(mod.Type)) -> mod.GenericType(mod.Type) { arg } } |
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.
These snapshots with really long unformatted lines are hard to read and it's not immediately clear what bit is being focused. Please use more normal formatting.
const c10 = alias.const3 <> alias.const3 | ||
type Type1 { Var(alias.Type) } | ||
type Type2 = alias.GenericType(alias.Type) | ||
type Record { Record (bool: Bool) } |
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 can't tell what this test is testing, it's very large!
pub const const2 = <<0:8>> | ||
pub const const3 = "Hello" | ||
pub type Type { Variant1 Variant2(Int) } | ||
pub type GenericType(inner) { Node(inner, GenericType(inner)) Leaf } |
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.
It would be nicer if this repeated code wasn't so large, each test uses very little of it. Ideally tests don't include things that they don't use, to make it clearer what they test and the snapshots easier to read. Currently it's quite slow to review these snapshots as it takes a moment for each one to spot the actual test code in the snapshot.
That said, a lot of code has been written using this boilerplate now, so would be annoying to change that.
Tests have been slimmed down quite extensively, if you want any specific or more tests let me know |
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.
Hello! This is looking fab! I've left a few small notes inline, and I think we may be missing tests to cover these situations:
- Namespaced modules (e.g.
one/two
) - Imports with spaces (e.g.
import one / two . { three , four } as five
- Uses of modules with spaces (e.g.
let x = thingy . Thingy
) - Triggering rename of an aliased module from uses of it
- Triggering rename of a namespaced module from uses of it
compiler-core/src/ast.rs
Outdated
} | ||
} | ||
|
||
pub(crate) fn name_location(&self) -> SrcSpan { |
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 isn't the location of the module name, that would always be the value of the module_location
field. Perhaps "used_name_location"? Please document what this function does also
) { | ||
if *module_name == self.module_name { | ||
self.references.push(ModuleNameReference { | ||
location: SrcSpan::new(location.start, field_start - 1), |
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.
Comments start with a capital letter 🙏
|
||
for (arg, type_) in arguments.iter().zip(args_type) { | ||
self.visit_type_ast(arg, type_); | ||
} |
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.
Can't we call the original method to do the iteration?
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 reason I was not using the original method was because I was using the full namespaced module name, and the TypeAstConstructor
's module
field contains the alias instead of the full name (as do other AST nodes). The type_
field however does contain the full name which is why I decided to use this custom method.
I have now been trying to use the alias instead of the full module name which has cleaned this Visit
Impl quite a lot but causes the hover action to fail since they both use Located::ModuleName
and the alias is not used as the key inside the ProjectCompiler
's importable_modules
hashmap.
So from what I can tell, either the AST nodes need to contain the full module name instead of/as well as the alias (see TypedExpr::ModuleSelect
) or Located::ModuleName
needs to contain both.
Which would you rather want or do you know of an alternative solution?
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.
Sounds good to me.
} | ||
// If new name is same as original, remove the alias | ||
ModuleNameReferenceKind::AliasedImport if params.new_name == original => { | ||
// subtract 1 from start to delete leading space added above |
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.
Capital letter please.
What leading space added above? What happens if there's multiple spaces?
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.
there are two scenarios imports can fall into:
1: Import does not contain unqualified member import -> delete all of (module_location.end+1, import.location.end), this will delete all spaces between module and alias as well as the alias itself but not remove any spacing after alias
2: Import does contain unqualified member import -> import AST node does not explicitly contain end location for unqualified imports so the only safe space to remove is the one required to separate tokens
By only deleting the required space, even if there are multiple, I tried to introduce consistency and allow the user to keep multiple import aliases aligned when using the LSP to rename.
Is that okay with you?
|
||
for (arg, type_) in arguments.iter().zip(args_type) { | ||
self.visit_type_ast(arg, type_); | ||
} |
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.
Sounds good to me.
match node { | ||
TypeAst::Constructor(TypeAstConstructor { module, arguments, .. }) => { | ||
let _ = type_.named_type_information().inspect(|(module_name, _, args_type)| { | ||
if let Some((_, location)) = module { |
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.
Do the module check first as it's cheaper than the call to named_type_information
.
Write these clauses using pattern matching instead of the inspect
please, as it's a bit cryptic and the end result isn't used, making inspect
not the right combinator for this action also.
This PR addresses #4716