Skip to content

Finalise new -ReportSummary switch #895

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

Merged
merged 14 commits into from
Mar 2, 2018
Merged
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
52 changes: 52 additions & 0 deletions Engine/Commands/InvokeScriptAnalyzerCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,19 @@ public SwitchParameter AttachAndDebug
set { attachAndDebug = value; }
}
private bool attachAndDebug = false;

#endif
/// <summary>
/// Write a summary of rule violations to the host, which might be undesirable in some cases, therefore this switch is optional.
/// </summary>
[Parameter(Mandatory = false)]
public SwitchParameter ReportSummary
{
get { return reportSummary; }
set { reportSummary = value; }
}
private SwitchParameter reportSummary;

#endregion Parameters

#region Overrides
Expand Down Expand Up @@ -424,9 +436,49 @@ private void WriteToOutput(IEnumerable<DiagnosticRecord> diagnosticRecords)
{
foreach (ILogger logger in ScriptAnalyzer.Instance.Loggers)
{
var errorCount = 0;
var warningCount = 0;
var infoCount = 0;

foreach (DiagnosticRecord diagnostic in diagnosticRecords)
{
logger.LogObject(diagnostic, this);
switch (diagnostic.Severity)
{
case DiagnosticSeverity.Information:
infoCount++;
break;
case DiagnosticSeverity.Warning:
warningCount++;
break;
case DiagnosticSeverity.Error:
errorCount++;
break;
default:
throw new ArgumentOutOfRangeException(nameof(diagnostic.Severity), $"Severity '{diagnostic.Severity}' is unknown");
}
}

if (ReportSummary.IsPresent)
{
var numberOfRuleViolations = infoCount + warningCount + errorCount;
if (numberOfRuleViolations == 0)
{
Host.UI.WriteLine("0 rule violations found.");
}
else
{
var pluralS = numberOfRuleViolations > 1 ? "s" : string.Empty;
var message = $"{numberOfRuleViolations} rule violation{pluralS} found. Severity distribution: {DiagnosticSeverity.Error} = {errorCount}, {DiagnosticSeverity.Warning} = {warningCount}, {DiagnosticSeverity.Information} = {infoCount}";
if (warningCount + errorCount == 0)
{
ConsoleHostHelper.DisplayMessageUsingSystemProperties(Host, "WarningForegroundColor", "WarningBackgroundColor", message);
}
else
{
ConsoleHostHelper.DisplayMessageUsingSystemProperties(Host, "ErrorForegroundColor", "ErrorBackgroundColor", message);
}
}
}
}

Expand Down
46 changes: 46 additions & 0 deletions Engine/Generic/ConsoleHostHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Management.Automation.Host;

namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic
{
internal static class ConsoleHostHelper
{
internal static void DisplayMessageUsingSystemProperties(PSHost psHost, string foregroundColorPropertyName, string backgroundPropertyName, string message)
{
var gotForegroundColor = TryGetPrivateDataConsoleColor(psHost, foregroundColorPropertyName, out ConsoleColor foregroundColor);
var gotBackgroundColor = TryGetPrivateDataConsoleColor(psHost, backgroundPropertyName, out ConsoleColor backgroundColor);
if (gotForegroundColor && gotBackgroundColor)
{
psHost.UI.WriteLine(foregroundColor: foregroundColor, backgroundColor: backgroundColor, value: message);
}
else
{
psHost.UI.WriteLine(message);
}
}

private static bool TryGetPrivateDataConsoleColor(PSHost psHost, string propertyName, out ConsoleColor consoleColor)
{
consoleColor = default(ConsoleColor);
var property = psHost.PrivateData.Properties[propertyName];
if (property == null)
{
return false;
}

try
{
consoleColor = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), property.Value.ToString(), true);
}
catch (InvalidCastException)
{
return false;
}

return true;
}
}
}
12 changes: 12 additions & 0 deletions Tests/Engine/InvokeScriptAnalyzer.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -504,4 +504,16 @@ Describe "Test -EnableExit Switch" {
powershell -Command 'Import-Module PSScriptAnalyzer; Invoke-ScriptAnalyzer -ScriptDefinition gci -EnableExit'
$LASTEXITCODE | Should -Be 1
}

Describe "-ReportSummary switch" {
$reportSummaryFor1Warning = '*1 rule violation found. Severity distribution: Error = 0, Warning = 1, Information = 0*'
It "prints the correct report summary using the -NoReportSummary switch" {
$result = powershell -command 'Invoke-Scriptanalyzer -ScriptDefinition gci -ReportSummary'
"$result" | Should -BeLike $reportSummaryFor1Warning
}
It "does not print the report summary when not using -NoReportSummary switch" {
$result = powershell -command 'Invoke-Scriptanalyzer -ScriptDefinition gci'
"$result" | Should -Not -BeLike $reportSummaryFor1Warning
}
}
}
20 changes: 18 additions & 2 deletions Tests/Engine/LibraryUsage.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,13 @@ function Invoke-ScriptAnalyzer {

[Parameter(Mandatory = $false)]
[switch] $Fix,

[Parameter(Mandatory = $false)]
[switch] $EnableExit,

[Parameter(Mandatory = $false)]
[switch] $EnableExit
)
[switch] $ReportSummary
)

if ($null -eq $CustomRulePath)
{
Expand Down Expand Up @@ -98,6 +101,19 @@ function Invoke-ScriptAnalyzer {
}

$results

if ($ReportSummary.IsPresent)
{
if ($null -ne $results)
{
# This is not the exact message that it would print but close enough
Write-Host "$($results.Count) rule violations found. Severity distribution: Error = 1, Warning = 3, Information = 5" -ForegroundColor Red
}
else
{
Write-Host '0 rule violations found.' -ForegroundColor Green
}
}

if ($EnableExit.IsPresent -and $null -ne $results)
{
Expand Down
19 changes: 17 additions & 2 deletions docs/markdown/Invoke-ScriptAnalyzer.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ Evaluates a script or module based on selected best practice rules
### UNNAMED_PARAMETER_SET_1
```
Invoke-ScriptAnalyzer [-Path] <String> [-CustomRulePath <String>] [-RecurseCustomRulePath]
[-ExcludeRule <String[]>] [-IncludeRule <String[]>] [-Severity <String[]>] [-Recurse] [-SuppressedOnly] [-Fix] [-EnableExit]
[-ExcludeRule <String[]>] [-IncludeRule <String[]>] [-Severity <String[]>] [-Recurse] [-SuppressedOnly] [-Fix] [-EnableExit] [-ReportSummary]
[-Settings <String>]
```

### UNNAMED_PARAMETER_SET_2
```
Invoke-ScriptAnalyzer [-ScriptDefinition] <String> [-CustomRulePath <String>] [-RecurseCustomRulePath]
[-ExcludeRule <String[]>] [-IncludeRule <String[]>] [-Severity <String[]>] [-Recurse] [-SuppressedOnly] [-EnableExit]
[-ExcludeRule <String[]>] [-IncludeRule <String[]>] [-Severity <String[]>] [-Recurse] [-SuppressedOnly] [-EnableExit] [-ReportSummary]
[-Settings <String>]
```

Expand Down Expand Up @@ -432,6 +432,21 @@ Accept pipeline input: False
Accept wildcard characters: False
```

### -ReportSummary
Writes a report summary of the found warnings to the host.

```yaml
Type: SwitchParameter
Parameter Sets: (All)
Aliases:

Required: False
Position: Named
Default value: False
Accept pipeline input: False
Accept wildcard characters: False
```

### -Settings
File path that contains user profile or hash table for ScriptAnalyzer

Expand Down