#PSScriptAnalyzer and "Unused Variables"

67 messages · Page 1 of 1 (latest)

eager marsh
#

The Notorious PSScriptAnalyzer

So I'm trying to tweak the notoriously dysfunctional/irritating PSSCriptAnalyzer in VSCode. All I want to do is suppress warnings for the whole "Hey you didn't use this declared variable :)" rule (which is actually called PSUseDeclaredVarsMoreThanAssignments). However, I only want the warnings to be suppressed for specific variables, and I'm so close to getting it to work, but I'm missing something.

My favorite part about this nonsense is that I'm getting warnings for a built-in preference variable, $ErrorView, even though the rest of the preference variables are fine.

The code so far...

I've managed to disable the rule completely by putting the following into Microsoft.PowerShell_profile.ps1:

[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments')]
    param($ErrorView)    

Anything I put in the param() block made no difference, as long as it was there (empty or not), the whole rule was turned off.

Then I got even closer

But still not quite there.

While I was actually typing this post, I realized part of the problem was that it needs to be a function, then I can specify which variables I want the rule to ignore. And it almost worked. I know, obvious in hindsight, but it's been a long day. 🙃

What I have now:

# Microsoft.PowerShell_profile.ps1
function SuppressUnused() {
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments')]
        param($ErrorView)
}

Anyway, I thought I had finally gotten it to work when I got the desired result in my profile (in the attached picture), but when I tested it in a random .ps1 file, the $ErrorView variable was still being flagged as unused.

eager marsh
# eager marsh __**The Notorious `PSScriptAnalyzer`**__ So I'm trying to tweak the notoriously...

I can put a bandaid on it though, when it comes to other files, by calling the function (example below), but I'd prefer not to have to do that in the actual script files, especially if I want to distribute them in any way.

And that's all, folks

I've been going through the documentation for PSScriptAnalyzer and I can't quite figure out the syntax, let alone what I'm missing. I also tried toying with the PSScriptAnalyzerSettings.psd1 but I'm even more lost there. I'm sure it's something simple, but I'm just not seeing it.

Any input would be greatly appreciated, thanks in advance!

rough crystal
#

this: ```ps
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments')]

#

disables the rule completely

#

it never disables it just for one variable

#

the rule evalutes every ScriptBlockAst, so the body of every script, function, etc

#

it uses an internal lookup table to determine what's baked in or not

eager marsh
# rough crystal it never disables it just for one variable

...I realized part of the problem was that it needs to be a function, then I can specify which variables I want the rule to ignore.

# Microsoft.PowerShell_profile.ps1
function SuppressUnused() {

[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments')]
        param($ErrorView)
}

This does allow me to specify variables (results in the attached screenshot above), I just can't get it to apply automatically outside my profile.

I hoped the solution would be in the Analyzer's config, PSScriptAnalyzerSettings.psd1, but as I said before, I'm completely lost in how to setup that one. lol

rough crystal
#

...I realized part of the problem was that it needs to be a function, then I can specify which variables I want the rule to ignore.
Honestly I don't know what you mean by this

#

this defines a new function with a new child scope and a new parameter named after a built in variable

#
function SuppressUnused() {

[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments')]
        param($ErrorView)
}
#

this does not suppress the rule for a single variable. At the very best it's a pretty unpleasant hack

#

the variables it ignores are constant values in the module, then it's dynamic evaluation of your script block

#

the variables are constants because retrieving the built-in list is only possible via an internal method of PS itself so it can't just hook a "what's built in".

#

then the rule itself is not a configurable rule so you cannot add your own exceptions

#

at the end of the day, if what you've done works for you and you're happy then go for it. However, it not a supportable way of avoiding the rule.

#

if you're vaguely curious, this is how you get the list of built-in variables from PS:

[PowerShell].Assembly.GetType('System.Management.Automation.SpecialVariables').GetFields('Static,NonPublic') |
    Where-Object FieldType -eq ([string]) |
    ForEach-Object GetValue($null)
```. Not a public API though so could break at any point. I use the output of this in an AvoidOutOfScopeVariables rule I have
eager marsh
# rough crystal > ...I realized part of the problem was that it needs to be a function, then I c...

Sorry I didn't really elaborate on that much.

When I originally used:

[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments')]

it disabled the rule completely, like you said. However, when I created the function, I was able to disable the warning for just $ErrorView, and the test variable I created still threw a warning (which was the goal).

Here, these two "before and after" images show what I'm talking about.

(also I haven't had a chance to read everything else you said, I was busy getting the screenshots lol)

rough crystal
#

I was able to disable the warning for just $ErrorView, and the test variable I created still threw a warning (which was the goal).
Yes, because you defined a parameter called ErrorView

#

so see "pretty dirty hack"

#

ErrorView should be added to the list of constants in PSScriptAnalyzer

eager marsh
eager marsh
rough crystal
#

essentially ErrorView needs adding to the end of this list of constants:
https://github.com/PowerShell/PSScriptAnalyzer/blob/da2c9180029806648a40994978fe205307d0f281/Engine/SpecialVars.cs#L32
And then into this array:
https://github.com/PowerShell/PSScriptAnalyzer/blob/da2c9180029806648a40994978fe205307d0f281/Engine/SpecialVars.cs#L67
Then it'll be properly ignored.

Arguably it might be nice to have that rule changed into a configurable rule. But it's an extremely complicated rule to toy with changing beyond the constants.

eager marsh
#

Yeah C# barely qualifies as "a work in progress" when it comes to what I've learned so far, so I tend to avoid playing with files like this lol

rough crystal
#

this is fair 😄

#

you don't have to though

eager marsh
#

but since you've given me a pretty solid lead, would you be able to point me in the general direction of that file for me to modify/break it? lmao

rough crystal
#

it's the file linked above, but you'd have to download the source, make the change, then recompile PSScriptAnalyzer

#

it's not plain text so you can't just edit the file and dust off your hands I'm afraid

eager marsh
#

I had a feeling you were going to say that lol

rough crystal
#

looks like that PR is stalled which is a real shame

eager marsh
#

It's honestly hilarious (in a sad way) that it's not on the list AND hasn't been fixed yet. lmao

#

I tried looking into this problem months ago, except I quickly gave up when all found were posts of people who just flat-out gave up on PSScriptAnalyzer as a whole lol

rough crystal
#

pretty sure I have that rule disabled everywhere too

#

it's just one of those that's pretty much impossible to make accurate

eager marsh
#

I'll do that if I have to in the end, but I tend to get forgetful of the silly things when I've hyperfixated on a project for 6+ hours straight. So it would be nice if I didn't HAVE to throw it out completely lol

rough crystal
#

yeah I know what you mean

eager marsh
#

Well, I'm gonna fork it and try to recompile it like you said. If by some miracle I succeed I'll make it public and post back for anyone who wants it lol

#

Thanks a ton for the help and info

rough crystal
#

no....

#

don't make it public

#

you need to be very mindful of it's copyright notices before you go and do that

eager marsh
#

It's under the MIT license, it doesn't look like there should be any issues- especially if I don't claim it to be my own lol

rough crystal
#

aye, well as long as you've read and are happy with the licence terms 😄

eager marsh
#

Yeah I have no intention of trying to screw Microsoft out of any pennies. They have scary lawyers and I am quite broke. lmao

rough crystal
#

haha 😄

eager marsh
#

besides, this all hinges on me actually being able to make it work. which is hilariously unlikely, at best 😂

rough crystal
#

yeah, I can't comment on that part. I spent 10 minutes one time trying to make it build on my computer and haven't looked at it since

eager marsh
#

I still have to try to compile a beta release of winget because mine is just hopelessly broken

rough crystal
#

heh I'm staying well clear of that one too 😄

eager marsh
#

yeah I'm not even bothering to ask around for that one because I know it's just gonna wind up being "Reinstall windows" or "build the beta release"

#

I'd rather jury-rig a VM for whatever I need than do either tbh lmao

#

Anyway, thanks again for the help!

rough crystal
#

any time 🙂

rocky ferry
#

For what it's worth, you can do this, at the top of any file (script or module, makes no difference):

[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'ErrorView')]
param()

rocky ferry
#

(my tiny, insignificant weight)

fast geyser
#

covered above, the only way I could break mine was not using it or not declariing

function Test { param( $x ) } 
function Test { param() $x }
eager marsh
fast geyser
#

in my head, I heard the name sigh as -- was it a couch? in the highhiker's guide