Skip to content

Renames CustomizedRulePath parameter and modifies its behavior. #365

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
Nov 23, 2015
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
25 changes: 20 additions & 5 deletions Engine/Commands/GetScriptAnalyzerRuleCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,25 @@ public class GetScriptAnalyzerRuleCommand : PSCmdlet, IOutputWriter
[Parameter(Mandatory = false)]
[ValidateNotNullOrEmpty]
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public string[] CustomizedRulePath
[Alias("CustomizedRulePath")]
public string CustomRulePath
{
get { return customizedRulePath; }
set { customizedRulePath = value; }
get { return customRulePath; }
set { customRulePath = value; }
}
private string[] customizedRulePath;
private string customRulePath;

/// <summary>
/// RecurseCustomRulePath: Find rules within subfolders under the path
/// </summary>
[Parameter(Mandatory = false)]
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public SwitchParameter RecurseCustomRulePath
{
get { return recurseCustomRulePath; }
set { recurseCustomRulePath = value; }
}
private bool recurseCustomRulePath;

/// <summary>
/// Name: The name of a specific rule to list.
Expand Down Expand Up @@ -76,7 +89,9 @@ public string[] Severity
/// </summary>
protected override void BeginProcessing()
{
ScriptAnalyzer.Instance.Initialize(this, customizedRulePath);
string[] rulePaths = Helper.ProcessCustomRulePaths(customRulePath,
this.SessionState, recurseCustomRulePath);
ScriptAnalyzer.Instance.Initialize(this, rulePaths);
}

/// <summary>
Expand Down
26 changes: 21 additions & 5 deletions Engine/Commands/InvokeScriptAnalyzerCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,25 @@ public string ScriptDefinition
[Parameter(Mandatory = false)]
[ValidateNotNull]
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public string[] CustomizedRulePath
[Alias("CustomizedRulePath")]
public string CustomRulePath
{
get { return customizedRulePath; }
set { customizedRulePath = value; }
get { return customRulePath; }
set { customRulePath = value; }
}
private string[] customizedRulePath;
private string customRulePath;

/// <summary>
/// RecurseCustomRulePath: Find rules within subfolders under the path
/// </summary>
[Parameter(Mandatory = false)]
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public SwitchParameter RecurseCustomRulePath
{
get { return recurseCustomRulePath; }
set { recurseCustomRulePath = value; }
}
private bool recurseCustomRulePath;

/// <summary>
/// ExcludeRule: Array of names of rules to be disabled.
Expand Down Expand Up @@ -164,9 +177,12 @@ public string Profile
/// </summary>
protected override void BeginProcessing()
{
string[] rulePaths = Helper.ProcessCustomRulePaths(customRulePath,
this.SessionState, recurseCustomRulePath);

ScriptAnalyzer.Instance.Initialize(
this,
customizedRulePath,
rulePaths,
this.includeRule,
this.excludeRule,
this.severity,
Expand Down
37 changes: 37 additions & 0 deletions Engine/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Management.Automation;
Expand Down Expand Up @@ -983,9 +984,45 @@ public Tuple<List<SuppressedRecord>, List<DiagnosticRecord>> SuppressRule(string
return result;
}

public static string[] ProcessCustomRulePaths(string rulePath, SessionState sessionState, bool recurse = false)
{
//if directory is given, list all the psd1 files
List<string> outPaths = new List<string>();
if (rulePath == null)
{
return null;
}
try
{
Collection<PathInfo> pathInfo = sessionState.Path.GetResolvedPSPathFromPSPath(rulePath);
foreach (PathInfo pinfo in pathInfo)
{
string path = pinfo.Path;
if (Directory.Exists(path))
{
path = path.TrimEnd('\\');
if (recurse)
{
outPaths.AddRange(Directory.GetDirectories(pinfo.Path, "*", SearchOption.AllDirectories));
}
}
outPaths.Add(path);
}
return outPaths.ToArray();
}
catch (Exception ex)
{
// need to do this as the path validation takes place later in the hierarchy.
outPaths.Add(rulePath);
return outPaths.ToArray();
}
}


#endregion
}


internal class TupleComparer : IComparer<Tuple<int, int>>
{
public int Compare(Tuple<int, int> t1, Tuple<int, int> t2)
Expand Down
10 changes: 5 additions & 5 deletions Engine/ScriptAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ internal void Initialize<TCmdlet>(
{
throw new ArgumentNullException("cmdlet");
}

this.Initialize(
cmdlet,
cmdlet.SessionState.Path,
Expand Down Expand Up @@ -188,7 +188,7 @@ private void Initialize(
if (!String.IsNullOrWhiteSpace(profile))
{
try
{
{
profile = path.GetResolvedPSPathFromPSPath(profile).First().Path;
}
catch
Expand Down Expand Up @@ -784,7 +784,7 @@ public Dictionary<string, List<string>> CheckRuleExtension(string[] path, PathIn
// We have to identify the childPath is really a directory or just a module name.
// You can also consider following two commands.
// Get-ScriptAnalyzerRule -RuleExtension "ContosoAnalyzerRules"
// Get-ScriptAnalyzerRule -RuleExtension "%USERPROFILE%\WindowsPowerShell\Modules\ContosoAnalyzerRules"
// Get-ScriptAnalyzerRule -RuleExtension "%USERPROFILE%\WindowsPowerShell\Modules\ContosoAnalyzerRules"
if (Path.GetDirectoryName(childPath) == string.Empty)
{
resolvedPath = childPath;
Expand All @@ -797,14 +797,14 @@ public Dictionary<string, List<string>> CheckRuleExtension(string[] path, PathIn

using (System.Management.Automation.PowerShell posh =
System.Management.Automation.PowerShell.Create())
{
{
posh.AddCommand("Get-Module").AddParameter("Name", resolvedPath).AddParameter("ListAvailable");
PSModuleInfo moduleInfo = posh.Invoke<PSModuleInfo>().First();

// Adds original path, otherwise path.Except<string>(validModPaths) will fail.
// It's possible that user can provide something like this:
// "..\..\..\ScriptAnalyzer.UnitTest\modules\CommunityAnalyzerRules\CommunityAnalyzerRules.psd1"
if (moduleInfo.ExportedFunctions.Count > 0) validModPaths.Add(childPath);
if (moduleInfo.ExportedFunctions.Count > 0) validModPaths.Add(resolvedPath);
}
}
catch
Expand Down
73 changes: 69 additions & 4 deletions Tests/Engine/CustomizedRule.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,83 @@ Describe "Test importing correct customized rules" {
}

Context "Test Get-ScriptAnalyzer with customized rules" {
It "will show the customized rule" {
It "will show the custom rule" {
$customizedRulePath = Get-ScriptAnalyzerRule -CustomizedRulePath $directory\samplerule\samplerule.psm1 | Where-Object {$_.RuleName -eq $measure}
$customizedRulePath.Count | Should Be 1
}


It "will show the custom rule when given a rule folder path" {
$customizedRulePath = Get-ScriptAnalyzerRule -CustomizedRulePath $directory\samplerule | Where-Object {$_.RuleName -eq $measure}
$customizedRulePath.Count | Should Be 1
}

if (!$testingLibraryUsage)
{
It "will show the custom rule when given a rule folder path with trailing backslash" {
$customizedRulePath = Get-ScriptAnalyzerRule -CustomizedRulePath $directory\samplerule\ | Where-Object {$_.RuleName -eq $measure}
$customizedRulePath.Count | Should Be 1
}

It "will show the custom rules when given a glob" {
$customizedRulePath = Get-ScriptAnalyzerRule -CustomizedRulePath $directory\samplerule\samplerule* | Where-Object {$_.RuleName -match $measure}
$customizedRulePath.Count | Should be 4
}

It "will show the custom rules when given recurse switch" {
$customizedRulePath = Get-ScriptAnalyzerRule -RecurseCustomRulePath -CustomizedRulePath $directory\samplerule | Where-Object {$_.RuleName -eq $measure}
$customizedRulePath.Count | Should be 3
}

it "will show the custom rules when given glob with recurse switch" {
$customizedRulePath = Get-ScriptAnalyzerRule -RecurseCustomRulePath -CustomizedRulePath $directory\samplerule\samplerule* | Where-Object {$_.RuleName -eq $measure}
$customizedRulePath.Count | Should be 5
}

it "will show the custom rules when given glob with recurse switch" {
$customizedRulePath = Get-ScriptAnalyzerRule -RecurseCustomRulePath -CustomizedRulePath $directory\samplerule* | Where-Object {$_.RuleName -eq $measure}
$customizedRulePath.Count | Should be 3
}
}
}

Context "Test Invoke-ScriptAnalyzer with customized rules" {
It "will show the customized rule in the results" {
It "will show the custom rule in the results" {
$customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -CustomizedRulePath $directory\samplerule\samplerule.psm1 | Where-Object {$_.Message -eq $message}
$customizedRulePath.Count | Should Be 1
}

It "will show the custom rule in the results when given a rule folder path" {
$customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -CustomizedRulePath $directory\samplerule | Where-Object {$_.Message -eq $message}
$customizedRulePath.Count | Should Be 1
}

if (!$testingLibraryUsage)
{
It "will show the custom rule in the results when given a rule folder path with trailing backslash" {
$customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -CustomizedRulePath $directory\samplerule\ | Where-Object {$_.Message -eq $message}
$customizedRulePath.Count | Should Be 1
}

It "will show the custom rules when given a glob" {
$customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -CustomizedRulePath $directory\samplerule\samplerule* | Where-Object {$_.Message -eq $message}
$customizedRulePath.Count | Should be 3
}

It "will show the custom rules when given recurse switch" {
$customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -RecurseCustomRulePath -CustomizedRulePath $directory\samplerule | Where-Object {$_.Message -eq $message}
$customizedRulePath.Count | Should be 3
}

it "will show the custom rules when given glob with recurse switch" {
$customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -RecurseCustomRulePath -CustomizedRulePath $directory\samplerule\samplerule* | Where-Object {$_.Message -eq $message}
$customizedRulePath.Count | Should be 4
}

it "will show the custom rules when given glob with recurse switch" {
$customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -RecurseCustomRulePath -CustomizedRulePath $directory\samplerule* | Where-Object {$_.Message -eq $message}
$customizedRulePath.Count | Should be 3
}
}
}
}

}
8 changes: 6 additions & 2 deletions Tests/Engine/GetScriptAnalyzerRule.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ Describe "Test available parameters" {

Context "RuleExtension parameters" {
It "has a RuleExtension parameter" {
$params.ContainsKey("CustomizedRulePath") | Should Be $true
$params.ContainsKey("CustomRulePath") | Should Be $true
}

It "accepts string array" {
$params["CustomizedRulePath"].ParameterType.FullName | Should Be "System.String[]"
$params["CustomRulePath"].ParameterType.FullName | Should Be "System.String"
}

It "takes CustomizedRulePath parameter as an alias of CustomRulePath paramter" {
$params.CustomRulePath.Aliases.Contains("CustomizedRulePath") | Should be $true
}
}

}
Expand Down
23 changes: 17 additions & 6 deletions Tests/Engine/InvokeScriptAnalyzer.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,30 @@ Describe "Test available parameters" {
$params.ContainsKey("ScriptDefinition") | Should Be $true
}

It "accepts string" {
It "accepts string" {
$params["ScriptDefinition"].ParameterType.FullName | Should Be "System.String"
}
}

Context "CustomizedRulePath parameters" {
It "has a CustomizedRulePath parameter" {
$params.ContainsKey("CustomizedRulePath") | Should Be $true
Context "CustomRulePath parameters" {
It "has a CustomRulePath parameter" {
$params.ContainsKey("CustomRulePath") | Should Be $true
}

It "accepts string array" {
$params["CustomizedRulePath"].ParameterType.FullName | Should Be "System.String[]"
It "accepts a string" {
if ($testingLibraryUsage)
{
$params["CustomRulePath"].ParameterType.FullName | Should Be "System.String[]"
}
else
{
$params["CustomRulePath"].ParameterType.FullName | Should Be "System.String"
}
}

It "has a CustomizedRulePath alias"{
$params.CustomRulePath.Aliases.Contains("CustomizedRulePath") | Should be $true
}
}

Context "IncludeRule parameters" {
Expand Down
26 changes: 20 additions & 6 deletions Tests/Engine/LibraryUsage.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ function Invoke-ScriptAnalyzer {
[string] $ScriptDefinition,

[Parameter(Mandatory = $false)]
[string[]] $CustomizedRulePath = $null,
[Alias("CustomizedRulePath")]
[string[]] $CustomRulePath = $null,

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

[Parameter(Mandatory=$false)]
[string[]] $ExcludeRule = $null,
Expand All @@ -32,18 +36,28 @@ function Invoke-ScriptAnalyzer {
[switch] $Recurse,

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

$scriptAnalyzer = New-Object "Microsoft.Windows.PowerShell.ScriptAnalyzer.ScriptAnalyzer"
[Parameter(Mandatory = $false)]
[string] $Profile = $null
)
# There is an inconsistency between this implementation and c# implementation of the cmdlet.
# The CustomRulePath parameter here is of "string[]" type whereas in the c# implementation it is of "string" type.
# If we set the CustomRulePath parameter here to "string[]", then the library usage test fails when run as an administrator.
# We want to note that the library usage test doesn't fail when run as a non-admin user.
# The following is the error statement when the test runs as an administrator.
# Assert failed on "Initialize" with "7" argument(s): "Test failed due to terminating error: The module was expected to contain an assembly manifest. (Exception from HRESULT: 0x80131018)"

$scriptAnalyzer = New-Object "Microsoft.Windows.PowerShell.ScriptAnalyzer.ScriptAnalyzer";
$scriptAnalyzer.Initialize(
$runspace,
$testOutputWriter,
$CustomizedRulePath,
$CustomRulePath,
$IncludeRule,
$ExcludeRule,
$Severity,
$SuppressedOnly.IsPresent
$SuppressedOnly.IsPresent,
$Profile
);

if ($PSCmdlet.ParameterSetName -eq "File") {
Expand Down
Loading