-
Notifications
You must be signed in to change notification settings - Fork 132
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 Rename Symbol Capability #915
Conversation
Thanks for looking into this! And great that you are opening a draft PR, makes it easier to help you. I do believe we have all the building blocks available to implement this feature – also note that a lot of the required functionality is available through https://github.com/bash-lsp/bash-language-server/blob/main/server/src/util/declarations.ts (which is what is used by the analyzer to get declarations). Declarations contain both environment variables, variables and functions.
I suggest descoping that for the first version (unless this is easy to implement). |
Thanks for the quick response! I'm still getting familiar with the code base so thanks for the tip on using the functionality in I'll take your advice and descope my ideas about special variables for now since I'm not sure how complex it is to implement. |
Hi @skovhus, it took a bit of exploration and experimentation, but I think I'm more or less done with renaming not defined and scoped variables and functions, and I think renaming global variables and functions isn't too far off. Before I continue though, I'd like to get your feedback on what I've done and the approach I took so I know I'm going in the right direction. Cases covered
Though I think function nesting, subshells, and such are rarely needed or used, I opted to support them so that in those cases where a user does use them, they won't get too janky of an experience. Limitations
Approach takenThe initial approach I took is as follows:
I quickly learned that though this approach worked well enough for renaming not defined variables, it broke down when dealing with things like local declarations and scopes. So, I ended up slowly adding methods to
I added methods instead of changing what's already there since I didn't want to interfere with the current functionality and diagnostics provided by the language server and risk breaking the current experience for users. However, I do think what I added could be incorporated later on by other handlers. For example, I think That said, I do think I'm adding quite a bit of code, and I do realize that the onus of reviewing all of this would fall onto you. So, I wanted to know if you're alright with how I'm going about things and with all of the cases I'm trying to cover. Do you think I did too much? Should I tone down what I'm trying to support? Did I miss something and maybe I'm just reimplementing things that are already available in the code base? How could I make this easier for you to review later on? |
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.
Amazing work here. 👏 👏 👏 I quickly looked over the code and came with some suggestions. But I'm really happy about the level of communication you do here and the videos.
I would love if you invested in writing some high level unit tests covering all the cases we handle and do not handle.
/** | ||
* A more scope-aware version of findOccurrences. | ||
*/ | ||
public findOccurrencesWithin({ |
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 didn't look to carefully here, but it might be we can reuse some functionality from utils/declarations
.
server/src/analyser.ts
Outdated
parent = this.findParentScopeNode(uri, parent.startPosition, parent.endPosition) | ||
} | ||
|
||
// TODO: Handle global definitions |
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 you mean declarations across files? getGlobalDeclarations
should help with this.
Thanks for the review, I appreciate it. I'll update the implementation based on your suggestions. Don't worry about the tests, I've kept track of the cases covered and not and plan to write them in test form when the implementation is a bit more locked in. I've been adding and removing methods here and there during my exploration and didn't want to add and remove tests at the same time. Since you seem to be alright with the general direction I'm going, I'll just ping you again when I'm done with the implementation + tests. Hopefully it won't take me so long this time 😅 Thanks again! |
It seems like this is pretty close! 👏 |
Hi! Yeah, it's pretty close now. Taking me a while since I've only been able to chip at it little by little and I had to think through a bit on how workspace-wide renames should work, but the implementation's pretty much done. I just have to fix the failing tests due to snapshots not expecting I'll probably make an updated write-up of the cases covered, limitations, and approach taken when I'm done as some things have changed since the last one I commented. Heads up though, I tried to use as much of what's already in the code base, but I wasn't able to use what's in |
No worries. |
Handle multiple variable assignments and declarations per declaration command when searching inside functions
Handle multiple variable assignments and declarations per declaration command when searching globally
Handle multiple variable assignments and declarations in one declaration command
0de7536
to
a96d50c
Compare
Hi @skovhus, I'm finally done. There are a lot of lines added, but most of those are from tests and snapshots. I'm not sure if it's overkill, but I wanted to document as much behavior as I reasonably could while taking into account some edge cases, and that's what I ended up with. Now, onto the updates. I'll be skipping visuals this time since I think the tests and example cases in Cases covered
Limitations
You can find tests that expound and give more examples of these in the "Edge or not covered cases" under the "onRenameRequest" describe block and some parts of the "onPrepareRename" describe block. Honestly though, there are probably more limitations that I'm just not aware of since there are so many cases that can be created with Bash. Approach takenThere are some changes from the original, but the overall steps are the same.
Thank you so much for your patience on this. Feel free to tell me if there's anything else I need to do or if I missed anything and I'll try to address it as soon as I can. |
i did a rough test, work fine, thanks. |
Hi @Shane-XB-Qian, thanks for testing it on your setup. Glad it works well. Unfortunately, yes, that case is an expected case since |
Sorry for the late review. Amazing work here @mcecode – let me know if you have other ideas for improving the LSP. I would love some help maintaining this project... |
Hi, I'd like to give implementing #161 a try, though it might take some time since I'm new to language servers and renaming in Bash doesn't seem to be as straightforward as in other languages. I have
onPrepareRename
working already, so hopefullyonRenameRequest
won't be too difficult to implement.For global defined variables, I'm planning to base the rename on the
includeAllWorkspaceSymbols
config. If it's set tofalse
, then the symbol would only be renamed within files linked by sourcing. If it's set totrue
, then the symbol would be renamed throughout the whole workspace.For variables that are not defined, renaming would only happen within the file. I'm thinking this could be useful for renaming environment variables like if someone wants to change
$HOME
to$PWD
for some reason.For special variables, I'm thinking$1
to$9
could be renamed since it's common to assign these to variables with more descriptive names. It could be useful, for example, if someone created a quick script or function and now want to clean it up, they could just rename$1
to$myVar
and assignmyVar="$1"
at the top of the script or function. I don't think other special variables like$@
or$#
should be renamed since they already have meaning in and of themselves.Feedback on the approach I'm thinking of taking and the work I've done so far would be much appreciated :)
Todos:
onPrepareRename
onRenameRequest
for undeclared symbolsonRenameRequest
for scoped symbolsonRenameRequest
for global symbolsonPrepareRename
handleronRenameRequest
handlerREADME.md
)