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

RenameProvider for variable/function renaming #2152

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

Conversation

Razmo99
Copy link

@Razmo99 Razmo99 commented Mar 25, 2024

PR Summary

This is a sister pull request to pr #4950 and issue Smart Variable Rename. It implements the server side component to allow refactoring of Powershell functions and variables.

It does this by implementing two new handlers RenameSymbolHandler and PrepareRenameSymbolHandler which is just plumbing to receive the incoming requests from the client. PrepareRenameSymbolHandler is used to determine if the rename is possible and RenameSymbolHandler is what actually returns the edits to the client.

All the action to decide what is renamed is done within two classes IterativeFunctionRename and IterativeVariableRename to boil it down the Abstract Syntax Tree(AST) of the script file is analyzed, then the symbol at the target line and column is retrieved. It then loops through the AST following rules to determine scope and what to rename. This is then passed back to the client to action.

Below are the current features

  • Rename Variables
  • Rename Functions
  • Is Scope Aware
  • Supports renaming splats
  • Supports renaming function parameters
  • If a function parameter is renamed it will add an alias

Below are the current limitations

  • Only refactors within the open file
  • Restricted to not work if dot sourcing is detected

Tests to cover as many scenarios as I could think of and to ensure the features described above function have been written

PR Context

This pull request should be helpful as its implementing a feature that I think has been desired for some time among Powershell developers. It should improve coding efficiency and allow code to be refactored with ease.

@JustinGrote
Copy link
Collaborator

We will also need to make sure we account for the scoping issues as mentioned by Rob that are very difficult to handle, even if it means we warn about this as best effort, or straight up refuse to do it.
PowerShell/vscode-powershell#261 (comment)

@Razmo99
Copy link
Author

Razmo99 commented Jun 5, 2024

I made some test cases for renaming from within a for / each loop and limiting the rename to the scope if the var is defined within the creation of the statement. My only concern is a case like below.

If you run the code powershell treats the $i = 10 as the highest scope assignment which is then redefined in the loop but kept in function scope for when its printed. As it stands if you renamed $i = 10 it would rename the loop using the same variable. however if you renamed from within the loop it would not touch the $i=10

$a = 1..5
$b = 6..10
function test {
    process {
        $i = 10
        
        for ($Renamed = 0; $Renamed -lt $b.Count; $Renamed++) {
            $null = $Renamed
        }
        
        for ($i = 0; $i -lt $a.Count; $i++) {
            write-output $i
        }
        
        write-output "I will be 5 : $i not 10"
    }
}
test

foreach ($number in $x) {
testing_files $number

function testing_files {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Rename on function applies to the keyword. I like this behavior if it isn't immediately intuitive, should we do the same for like foreach as well for the inner var?

Copy link
Author

Choose a reason for hiding this comment

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

I like this behavior aswell, its a happy byproduct of how the FunctionDefinitionAST works, I don't think it would be too hard to get it working for for / foreach statments. In the screenshot below you can see that the VariableExpressionAst is nicely nested just need some logic to target it when the parent is selected.

image

Razmo99 added 19 commits June 6, 2024 12:17
… scriptAST correctly otherwise it just picks up the $a = 1..5
…mer, proper error return's now when renaming commandAST thats not defined in the script file
…d if it exists before the functions definition
…r is target is within a parameter block within a function to solve
…scope and a helper method IsVariableExpressionAssignedInTargetScope
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.

None yet

2 participants