Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions Engine/Commands/InvokeScriptAnalyzerCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public class InvokeScriptAnalyzerCommand : PSCmdlet, IOutputWriter
private const string ParameterSet_Path_IncludeSuppressed = nameof(Path) + "_" + nameof(IncludeSuppressed);
private const string ParameterSet_ScriptDefinition_SuppressedOnly = nameof(ScriptDefinition) + "_" + nameof(SuppressedOnly);
private const string ParameterSet_ScriptDefinition_IncludeSuppressed = nameof(ScriptDefinition) + "_" + nameof(IncludeSuppressed);
private const string ParameterSet_ScriptBlock_SuppressedOnly = nameof(ScriptBlock) + "_" + nameof(SuppressedOnly);
private const string ParameterSet_ScriptBlock_IncludeSuppressed = nameof(ScriptBlock) + "_" + nameof(IncludeSuppressed);

#region Private variables
List<string> processedPaths;
Expand Down Expand Up @@ -65,15 +67,13 @@ public string Path
/// <summary>
/// ScriptDefinition: a script definition in the form of a string to run rules on.
/// </summary>
[Parameter(Position = 0,
[Parameter(
ParameterSetName = ParameterSet_ScriptDefinition_IncludeSuppressed,
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true)]
[Parameter(Position = 0,
[Parameter(
ParameterSetName = ParameterSet_ScriptDefinition_SuppressedOnly,
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true)]
[ValidateNotNull]
public string ScriptDefinition
Expand All @@ -83,6 +83,31 @@ public string ScriptDefinition
}
private string scriptDefinition;

/// <summary>
/// ScriptBlock: a script block to run rules on.
/// </summary>
[Parameter(Position = 0,
ParameterSetName = ParameterSet_ScriptBlock_IncludeSuppressed,
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true)]
[Parameter(Position = 0,
ParameterSetName = ParameterSet_ScriptBlock_SuppressedOnly,
Mandatory = true,
ValueFromPipeline = true,
ValueFromPipelineByPropertyName = true)]
[ValidateNotNull]
public ScriptBlock ScriptBlock
{
get { return scriptBlock; }
set
{
scriptBlock = value;
scriptDefinition = value?.ToString();
}
}
private ScriptBlock scriptBlock;

/// <summary>
/// CustomRulePath: The path to the file containing custom rules to run.
/// </summary>
Expand Down Expand Up @@ -179,13 +204,15 @@ public SwitchParameter Recurse
/// </summary>
[Parameter(ParameterSetName = ParameterSet_Path_SuppressedOnly)]
[Parameter(ParameterSetName = ParameterSet_ScriptDefinition_SuppressedOnly)]
[Parameter(ParameterSetName = ParameterSet_ScriptBlock_SuppressedOnly)]
public SwitchParameter SuppressedOnly { get; set; }

/// <summary>
/// Include suppressed diagnostics in the output.
/// </summary>
[Parameter(ParameterSetName = ParameterSet_Path_IncludeSuppressed, Mandatory = true)]
[Parameter(ParameterSetName = ParameterSet_ScriptDefinition_IncludeSuppressed, Mandatory = true)]
[Parameter(ParameterSetName = ParameterSet_ScriptBlock_IncludeSuppressed, Mandatory = true)]
public SwitchParameter IncludeSuppressed { get; set; }

/// <summary>
Expand Down
26 changes: 24 additions & 2 deletions Tests/Engine/InvokeScriptAnalyzer.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Describe "Test available parameters" {
}
}

Context "Path parameter" {
Context "ScriptDefinition parameter" {
It "has a ScriptDefinition parameter" {
$params.ContainsKey("ScriptDefinition") | Should -BeTrue
}
Expand All @@ -37,6 +37,16 @@ Describe "Test available parameters" {
}
}

Context "ScriptBlock parameter" {
It "has a ScriptBlock parameter" {
$params.ContainsKey("ScriptBlock") | Should -BeTrue
}

It "accepts ScriptBlock" {
$params["ScriptBlock"].ParameterType.FullName | Should -Be "System.Management.Automation.ScriptBlock"
}
}

Context "CustomRulePath parameters" {
It "has a CustomRulePath parameter" {
$params.ContainsKey("CustomRulePath") | Should -BeTrue
Expand Down Expand Up @@ -85,10 +95,12 @@ Describe "Test available parameters" {
}
}

It "Has 4 parameter sets" {
It "Has 6 parameter sets" {
$parameterSets = @(
'Path_IncludeSuppressed'
'Path_SuppressedOnly'
'ScriptBlock_IncludeSuppressed'
'ScriptBlock_SuppressedOnly'
'ScriptDefinition_IncludeSuppressed'
'ScriptDefinition_SuppressedOnly'
)
Expand All @@ -108,6 +120,16 @@ Describe "Test ScriptDefinition" {
}
}

Describe "Test ScriptBlock" {
Context "When given a script block" {
It "Runs rules on script with 1 warning" {
# this is a script with 1 error (var declared but not used)
$violations = Invoke-ScriptAnalyzer {$var = 1}
$violations.Count | Should -Be 1
}
}
}

Describe "Test Path" {
Context "When given a single file" {
It "Has the same effect as without Path parameter" {
Expand Down
9 changes: 9 additions & 0 deletions Tests/Engine/LibraryUsage.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ Describe 'Library Usage' -Skip:$IsCoreCLR {
[parameter(Mandatory = $true, ParameterSetName="ScriptDefinition_IncludeSuppressed")]
[string] $ScriptDefinition,

[parameter(Mandatory = $true, ParameterSetName="ScriptBlock_SuppressedOnly")]
[parameter(Mandatory = $true, ParameterSetName="ScriptBlock_IncludeSuppressed")]
[scriptblock] $ScriptBlock,

[Parameter(Mandatory = $false)]
[Alias("CustomizedRulePath")]
[string[]] $CustomRulePath = $null,
Expand All @@ -43,10 +47,12 @@ Describe 'Library Usage' -Skip:$IsCoreCLR {

[Parameter(Mandatory = $false, ParameterSetName = "Path_SuppressedOnly")]
[Parameter(Mandatory = $false, ParameterSetName = "ScriptDefinition_SuppressedOnly")]
[Parameter(Mandatory = $false, ParameterSetName = "ScriptBlock_SuppressedOnly")]
[switch] $SuppressedOnly,

[Parameter(Mandatory, ParameterSetName = "Path_IncludeSuppressed")]
[Parameter(Mandatory, ParameterSetName = "ScriptDefinition_IncludeSuppressed")]
[Parameter(Mandatory, ParameterSetName = "ScriptBlock_IncludeSuppressed")]
[switch] $IncludeSuppressed,

[Parameter(Mandatory = $false)]
Expand Down Expand Up @@ -97,6 +103,9 @@ Describe 'Library Usage' -Skip:$IsCoreCLR {
}
else
{
if ($null -ne $ScriptBlock) {
$ScriptDefinition = $ScriptBlock.ToString()
}
$results = $scriptAnalyzer.AnalyzeScriptDefinition($ScriptDefinition, [ref] $null, [ref] $null)
}

Expand Down
5 changes: 3 additions & 2 deletions Tests/Engine/ModuleHelp.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,9 @@ Describe 'Cmdlet parameter help' {

$parameterHelpPipelineInput = if ($parameterHelp.pipelineInput -eq 'True (ByPropertyName, ByValue)') {
$true
}
else {
} elseif ($parameterHelp.pipelineInput -eq 'True (ByPropertyName)') {
$true
} else {
[System.Boolean]::Parse($parameterHelp.pipelineInput)
}

Expand Down
115 changes: 93 additions & 22 deletions docs/Cmdlets/Invoke-ScriptAnalyzer.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,25 @@ Invoke-ScriptAnalyzer [-ScriptDefinition] <string> [-CustomRulePath <string[]>]
[<CommonParameters>]
```

### ScriptBlock_IncludeSuppressed

```
Invoke-ScriptAnalyzer [-ScriptBlock] <ScriptBlock> -IncludeSuppressed [-CustomRulePath <string[]>]
[-RecurseCustomRulePath] [-IncludeDefaultRules] [-ExcludeRule <string[]>]
[-IncludeRule <string[]>] [-Severity <string[]>] [-Recurse] [-EnableExit] [-Settings <Object>]
[-SaveDscDependency] [-ReportSummary] [-WhatIf] [-Confirm] [<CommonParameters>]
```

### ScriptBlock_SuppressedOnly

```
Invoke-ScriptAnalyzer [-ScriptBlock] <ScriptBlock> [-CustomRulePath <string[]>]
[-RecurseCustomRulePath] [-IncludeDefaultRules] [-ExcludeRule <string[]>]
[-IncludeRule <string[]>] [-Severity <string[]>] [-Recurse] [-SuppressedOnly] [-EnableExit]
[-Settings <Object>] [-SaveDscDependency] [-ReportSummary] [-WhatIf] [-Confirm]
[<CommonParameters>]
```

## DESCRIPTION

`Invoke-ScriptAnalyzer` evaluates scripts or module files (`.ps1`, `.psm1`, and `.psd1` files) based
Expand Down Expand Up @@ -156,9 +175,9 @@ Invoke-ScriptAnalyzer -Path .\Get-Widgets.ps1
```

```Output
RuleName Severity FileName Line Message
-------- -------- -------- ---- -------
PSProvideCommentHelp Information ManageProf 14 The cmdlet 'Get-Widget' does not have a help comment.
RuleName Severity ScriptName Line Message
-------- -------- -------- ---- -------
PSProvideCommentHelp Information ManageProf 14 The cmdlet 'Get-Widget' does not have a help comment.
iles.psm1
```

Expand All @@ -167,11 +186,11 @@ Invoke-ScriptAnalyzer -Path .\Get-Widgets.ps1 -SuppressedOnly
```

```Output
Rule Name Severity File Name Line Justification
--------- -------- --------- ---- -------------
PSAvoidUsingCmdletAliases Warning ManageProf 21 Resolution in progress.
Rule Name Severity ScriptName Line Justification
--------- -------- --------- ---- -------------
PSAvoidUsingCmdletAliases Warning ManageProf 21 Resolution in progress.
iles.psm1
PSUseSingularNouns Warning ManageProf 14
PSUseSingularNouns Warning ManageProf 14
iles.psm1
```

Expand Down Expand Up @@ -208,20 +227,51 @@ Invoke-ScriptAnalyzer -ScriptDefinition "function Get-Widgets {Write-Host 'Hello
```

```Output
RuleName Severity FileName Line Message
-------- -------- -------- ---- -------
PSAvoidUsingWriteHost Warning 1 Script
because
there i
suppres
Write-O
PSUseSingularNouns Warning 1 The cmd
noun sh
RuleName Severity ScriptName Line Message
-------- -------- -------- ---- -------
PSAvoidUsingWriteHost Warning 1 Script
because
there i
suppres
Write-O
PSUseSingularNouns Warning 1 The cmd
noun sh
```

When you use the **ScriptDefinition** parameter, the **FileName** property of the
**DiagnosticRecord** object is `$null`.

### EXAMPLE 10 - Analyze a script block

This example uses the **ScriptBlock** parameter to analyze a function at the command line. The
function is defined within a script block.

```powershell
Invoke-ScriptAnalyzer -ScriptBlock {function Get-Widgets {Write-Host 'Hello'}}
```

```Output

RuleName Severity ScriptName Line Message
-------- -------- ---------- ---- -------
PSUseSingularNouns Warning 1 The cmdlet 'Get-Widgets' uses a plural
noun. A singular noun should be used
instead.
PSAvoidUsingWriteHost Warning 1 Script definition uses Write-Host.
Avoid using Write-Host because it might
not work in all hosts, does not work
when there is no host, and (prior to PS
5.0) cannot be suppressed, captured, or
redirected. Instead, use Write-Output,
Write-Verbose, or Write-Information.



```

When you use the **ScriptBlock** parameter, the **ScriptName** property of the
**DiagnosticRecord** object is `$null`.

## PARAMETERS

### -CustomRulePath
Expand Down Expand Up @@ -362,7 +412,7 @@ Include suppressed diagnostics in output.

```yaml
Type: SwitchParameter
Parameter Sets: Path_IncludeSuppressed, ScriptDefinition_IncludeSuppressed
Parameter Sets: Path_IncludeSuppressed, ScriptBlock_IncludeSuppressed, ScriptDefinition_IncludeSuppressed
Aliases:

Required: True
Expand Down Expand Up @@ -472,6 +522,23 @@ Accept pipeline input: False
Accept wildcard characters: False
```

### -ScriptBlock

Runs the analysis on commands, functions, or expressions on a scriptblock. You can use this feature to
analyze statements, expressions, and functions, independent of their script context.

```yaml
Type: ScriptBlock
Parameter Sets: ScriptBlock_IncludeSuppressed, ScriptBlock_SuppressedOnly
Aliases:

Required: True
Position: 0
Default value: None
Accept pipeline input: True (ByPropertyName, ByValue)
Accept wildcard characters: False
```

### -ScriptDefinition

Runs the analysis on commands, functions, or expressions in a string. You can use this feature to
Expand All @@ -483,9 +550,9 @@ Parameter Sets: ScriptDefinition_IncludeSuppressed, ScriptDefinition_SuppressedO
Aliases:

Required: True
Position: 0
Position: Named
Default value: None
Accept pipeline input: True (ByPropertyName, ByValue)
Accept pipeline input: True (ByPropertyName)
Accept wildcard characters: False
```

Expand Down Expand Up @@ -569,7 +636,7 @@ To suppress a rule, use the **SuppressMessageAttribute**. For help, see the exam

```yaml
Type: SwitchParameter
Parameter Sets: Path_SuppressedOnly, ScriptDefinition_SuppressedOnly
Parameter Sets: Path_SuppressedOnly, ScriptBlock_SuppressedOnly, ScriptDefinition_SuppressedOnly
Aliases:

Required: False
Expand Down Expand Up @@ -620,9 +687,13 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable

## INPUTS

### None
### String

You can pipe a string representing a script path to this cmdlet. The string is bound to the `-Path` parameter by value.

### ScriptBlock

You cannot pipe input to this cmdlet.
You can pipe a script block to this cmdlet. The script block is bound to the `-ScriptBlock` parameter by value.

## OUTPUTS

Expand Down