Go To Definition/Find All References with Set-Variable
Please fill in these details so that we can help you!
System Details
- Operating system name and version:
- VS Code version: 1.8.0
- PowerShell extension version: 0.7.2
- Output from
$PSVersionTable: PSVersion 5.0.10240.17146 WSManStackVersion 3.0 SerializationVersion 1.1.0.1 CLRVersion 4.0.30319.42000 BuildVersion 10.0.10011.16384 PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...} PSRemotingProtocolVersion 2.3
Issue Description
Not sure how feasible this is with your plugin, but if a variable is defined using the Set-Variable cmdlet (such as how you define constants) if is not possible to use Find All References or Go To Definition command on them because they are not defined using the $ notation.
We'll look into it!
This is tricky because Set-Variable creates variables at runtime so there is no AST representation of the variable at edit time. You could special case this and find instances New-Variable and Set-Variable that use a string literal for the variable name. But if the cmdlet uses an expression e.g. Set-Variable -name (Get-VariableNameFunction) -value 42, not so easy without partially executing script.
Plus there are other ways for variable creation e.g.: New-Item variable: -Name foo -Value 'var var binks' and Copy-Item variable:\foo variable:\baz.
Yep, Keith's right, it's difficult to make this work 100% (or even 50% for that matter). I think the expectation should be that "obvious cases" like Set-Variable with the variable name plainly visible will be located. We shouldn't need to partially execute any code to get language features to work.
Don’t forget New-Variable. Pretty much the same.
As a workaround for the case of constants, I'm defining normal variables at first and use Set-Variable -Option ReadOnly afterwards. Contrary to -Option Constant the -Option ReadOnly can be used on already defined variables.
$CONST_FOO = 42; Set-Variable CONST_FOO -Option ReadOnly
$CONST_FOO = 0
# -> WriteError: Cannot overwrite variable CONST_FOO because it is read-only or constant.
Often one defines a bunch of constants in a separate module. Using a common prefix, you only need a single Set-Variable call, avoiding the need to repeat the variable names.
$CONST_FOO = 42
$CONST_BAR = 23
Set-Variable CONST_* -Option ReadOnly
Export-ModuleMember -Variable CONST_*
Within a module, the Set-Variable call only affects variables in module scope, so you can't accidentally make variables outside of the module scope read-only.
A caveat is that a variable with -Option ReadOnly can still be deleted using Remove-Variable VarName -Force. For me this isn't an issue, because I only want to protect against accidentally changing the values of constants. Remove-Variable is rarely used and I can't see how someone would accidentally use it.
Edit:
Actually, you can make an undeletable constant out of an existing variable, by using New-Variable -Force:
$CONST_FOO = 42
$CONST_BAR = 23
Get-Variable CONST_* | ForEach-Object { New-Variable -Name $_.Name -Value $_.Value -Option Constant -Force }
I don't see any downside of this pattern (yet).