Skip to content

Suppress external AST based rules #588

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 6 commits into from
Aug 2, 2016
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
38 changes: 34 additions & 4 deletions Engine/ScriptAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1455,6 +1455,28 @@ private Tuple<List<SuppressedRecord>, List<DiagnosticRecord>> SuppressRule(
return records;
}

/// <summary>
/// Wrapper around SuppressRule method.
///
/// This enables suppressing external rules (written in PowerShell).
/// Since there can be an inconsistency between the rule name in
/// diagnostic record and the actual rule (function) name, we use
/// the diagnostic record rule name for suppression
/// </summary>
/// <param name="ruleSuppressions"></param>
/// <param name="ruleDiagnosticRecord"></param>
/// <returns>Returns a tuple of suppressed and diagnostic records</returns>
private Tuple<List<SuppressedRecord>, List<DiagnosticRecord>> SuppressRule(
Dictionary<string, List<RuleSuppression>> ruleSuppressions,
DiagnosticRecord ruleDiagnosticRecord
)
{
return SuppressRule(
ruleDiagnosticRecord.RuleName,
ruleSuppressions,
new List<DiagnosticRecord> { ruleDiagnosticRecord });
}

/// <summary>
/// Analyzes the syntax tree of a script file that has already been parsed.
/// </summary>
Expand Down Expand Up @@ -1752,13 +1774,21 @@ public IEnumerable<DiagnosticRecord> AnalyzeSyntaxTree(
}
}

foreach (var record in this.GetExternalRecord(scriptAst, scriptTokens, exRules.ToArray(), fileName))
foreach (var ruleRecord in this.GetExternalRecord(scriptAst, scriptTokens, exRules.ToArray(), fileName))
{
diagnostics.Add(record);
var records = SuppressRule(ruleSuppressions, ruleRecord);
foreach (var record in records.Item2)
{
diagnostics.Add(record);
}
foreach (var suppressedRec in records.Item1)
{
suppressed.Add(suppressedRec);
}
}
}

#endregion
#endregion

// Need to reverse the concurrentbag to ensure that results are sorted in the increasing order of line numbers
IEnumerable<DiagnosticRecord> diagnosticsList = diagnostics.Reverse();
Expand Down
30 changes: 23 additions & 7 deletions Tests/Engine/RuleSuppression.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,29 @@ function SuppressPwdParam()

if (!$testingLibraryUsage)
{
Context "Bad Rule Suppression" {
It "Throws a non-terminating error" {
Invoke-ScriptAnalyzer -ScriptDefinition $ruleSuppressionBad -IncludeRule "PSAvoidUsingUserNameAndPassWordParams" -ErrorVariable errorRecord -ErrorAction SilentlyContinue
$errorRecord.Count | Should Be 1
$errorRecord.FullyQualifiedErrorId | Should match "suppression message attribute error"
}
}
Context "Bad Rule Suppression" {
It "Throws a non-terminating error" {
Invoke-ScriptAnalyzer -ScriptDefinition $ruleSuppressionBad -IncludeRule "PSAvoidUsingUserNameAndPassWordParams" -ErrorVariable errorRecord -ErrorAction SilentlyContinue
$errorRecord.Count | Should Be 1
$errorRecord.FullyQualifiedErrorId | Should match "suppression message attribute error"
}
}

Context "External Rule Suppression" {
$externalRuleSuppression = @'
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('CommunityAnalyzerRules\Measure-WriteHost','')]
param() # without the param block, powershell parser throws up!
Write-Host "write-host"
'@
It "Suppresses violation of an external ast rule" {
Invoke-ScriptAnalyzer `
-ScriptDefinition $externalRuleSuppression `
-CustomRulePath (Join-Path $directory "CommunityAnalyzerRules") `
-OutVariable ruleViolations `
-SuppressedOnly
$ruleViolations.Count | Should Be 1
}
}
}
}

Expand Down
8 changes: 6 additions & 2 deletions build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,12 @@ if ($BuildDocs)
New-ExternalHelp -Path $markdownDocsPath -OutputPath $outputDocsPath -Force -Verbose:$verbosity
}


$moduleRootPath = Join-Path (Split-Path $profile) 'Modules'
# Appveyor errors out due to $profile being null. Hence...
$moduleRootPath = "$HOME/Documents/WindowsPowerShell/Modules"
if ($profile -ne $null)
{
$moduleRootPath = Join-Path (Split-Path $profile) 'Modules'
}
$modulePSSAPath = Join-Path $moduleRootPath 'PSScriptAnalyzer'
if ($Install)
{
Expand Down