Psscriptanalyzer: Warning about unused variable in VSCode

Created on 27 Oct 2017  路  10Comments  路  Source: PowerShell/PSScriptAnalyzer

A wrong warning about unused variable, but that variable used later in code:

default

Area - PSUseDeclaredVarsMoreThanAssignments Area - Rules

Most helpful comment

There are various issues with false positives of this rule that would probably need to be re-written from the ground up using a different technique to overcome its limitations. I plan to collate all those issues in a meta-issue at some point.

All 10 comments

+1
I've seen this as well with Insiders build + latest everything. But it's not consistent and sometimes I just have to restart the powershell session

I tried running Script Analyzer on its own against the original repro and I'm seeing the warning. Here's the repro:

In the file repro.ps1:

$a = 0
$b = @(1, 2)
$b | ForEach-Object {
    $a += 1
}
Write-Host $a

in a terminal:

Install-Module -Name PSScriptAnalyzer

Invoke-ScriptAnalyzer -Path path/to/repro.ps1 -Settings PSGallery -Recurse

The output:

RuleName                            Severity     ScriptName Line  Message
--------                            --------     ---------- ----  -------
PSUseDeclaredVarsMoreThanAssignment Warning      repro2.ps1 4     The variable 'a' is assigned but never used.

I think this warning is appropriate. In your example, $a in the original assignment and the $a inside the foreach block are in two different scopes. Try this:

$a = 1

& {
    $a = 2
}

$a

image

I don't believe there is an accurate way for PSScriptAnalyzer to guess that your intention is to use the $a variable in the parent scope, and it has to assume that you have assigned an unused variable.

There are various issues with false positives of this rule that would probably need to be re-written from the ground up using a different technique to overcome its limitations. I plan to collate all those issues in a meta-issue at some point.

Here is my example. $RemoveCount is reported as unused. $RemoveError is not

main loopk in code. Calls functions Remove-member() and Write-Log()

$BaseDir = "C:\Temp\attest"
get-childitem $BaseDir*_AttestListing.csv | foreach {
$CSVfile=$_

write-log "Processing data file: $($CSVfile.name)" -verbose
$RemoveCount = 0
$RemoveError = $false
import-csv $CSVfile |foreach{
    $line = $_
    if ($line."Remove Member?" -match "[yYxX]") {
        echo "Removing $($line."Member Name") from $($line."Group Name")"
        #write-log "Removing $("$_.Member Name") from $("$_.Group Name")" -verbose
        If (Remove-Member($line)) {
            $RemoveCount = $RemoveCount + 1
        } else {
            $RemoveError = $true
        }

    }
}
if ($RemoveError -eq $true){
    Write-log "Error processing changes for: $($CSVFile.fullname)" -verbose
    # If error removing, file is not renamed and must be processed manually
 } else {

    if ($RemoveCount -eq 0) {
        Write-log "No changes processed for $($CSVFile.fullname)" -verbose
    }Else { 
        Write-log "$RemoveCount members removed from $($CSVFile.fullname)" -verbose
    }

    Try {
        Rename-item $CSVfile.fullname "$($CSVFile.basename)_processed.csv"
    }
    Catch {}
}

}

+1

The directive to suppress messages also does not work:

[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments","")]

$smtpserver_a = "smtp.example.com"
$smtpserver_b = "smtp.example.com"  < error
$smtpserver_c = "smtp.example.com"  < error
$smtpserver_d = "smtp.example.com"  < error

Anyone know how to suppress this in the visual code settings?

@guyWicks Your example case already got fixed in PR #836 and will be in the upcoming release of 1.17 that is hopefully going to be released in the next days.
The Suppressionattribute needs to be on a function or Param() block in order to work.
VsVode has a setting to define a relative path to a PSSA settings file where you can define and customize the rules to be used inside VSCode. I would not recommend turning off this rule though because it is still useful despite some false positives. Most warnings produced by different code analysis tools needs human judgement, please keep that in mind. It is always a trade off between being able to determine 100% that something is wrong and warning on the possibility that something could be wrong.

Thanks for this.

For future reference, this now works as I expected:

[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments","")]
param()

$smtpserver_a = "smtp.example.com"  # no error
$smtpserver_b = "smtp.example.com"  # no error
$smtpserver_c = "smtp.example.com"  # no error
$smtpserver_d = "smtp.example.com"  #no error

Agree with your recommendation to use this suppression with caution - in my particular use-case I have a common file that stores global configuration variables so these are not used in this file, but in other files. You may legitimately criticise this design model :)

If the warning appears in variables you're referencing inside a Foreach-Object, or other construct, then specifying a scope on the variable seems to appease the warning.

To borrow/modify @mattmcnabb's example:

$a = 1

& {
    $script:a = 2
}

$a

I don't believe there is an accurate way for PSScriptAnalyzer to guess that your intention is to use the $a variable in the parent scope, and it has to assume that you have assigned an unused variable.

I think that method _is_ $script: (or global, or local): https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes?view=powershell-6

This is definitely still an issue in the latest VSCode v1.51.1

image

Was this page helpful?
0 / 5 - 0 ratings