Skip to content

Add CustomRulePath property to settings file #803

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 15 commits into from
Jul 31, 2017
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
7 changes: 6 additions & 1 deletion .build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,12 @@ function Get-ResourceTaskParam($project) {
@{
Inputs = "$project/Strings.resx"
Outputs = "$project/Strings.cs"
Jobs = {& "$resourceScript $project"}
Data = $project
Jobs = {
Push-Location $BuildRoot
& $resourceScript $Task.Data
Pop-Location
}
Before = "$project/build"
}
}
Expand Down
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Place your settings in this file to overwrite default and user settings.
{
"editor.tabSize": 4,
"powershell.codeFormatting.preset": "Allman"
}
37 changes: 35 additions & 2 deletions Engine/Commands/InvokeScriptAnalyzerCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,9 @@ protected override void BeginProcessing()
ProcessPath();
}

string[] combRulePaths = null;
var combRecurseCustomRulePath = RecurseCustomRulePath.IsPresent;
var combIncludeDefaultRules = IncludeDefaultRules.IsPresent;
try
{
var settingsObj = PSSASettings.Create(
Expand All @@ -274,7 +277,30 @@ protected override void BeginProcessing()
if (settingsObj != null)
{
ScriptAnalyzer.Instance.UpdateSettings(settingsObj);

// For includeDefaultRules and RecurseCustomRulePath we override the value in the settings file by
// command line argument.
combRecurseCustomRulePath = OverrideSwitchParam(
settingsObj.RecurseCustomRulePath,
"RecurseCustomRulePath");
combIncludeDefaultRules = OverrideSwitchParam(
settingsObj.IncludeDefaultRules,
"IncludeDefaultRules");
}

// Ideally we should not allow the parameter to be set from settings and command line
// simultaneously. But since, this was done before with IncludeRules, ExcludeRules and Severity,
// we use the same strategy for CustomRulePath. So, we take the union of CustomRulePath provided in
// the settings file and if provided on command line.
var settingsCustomRulePath = Helper.ProcessCustomRulePaths(
settingsObj?.CustomRulePath?.ToArray(),
this.SessionState,
combRecurseCustomRulePath);
combRulePaths = rulePaths == null
? settingsCustomRulePath
: settingsCustomRulePath == null
? rulePaths
: rulePaths.Concat(settingsCustomRulePath).ToArray();
}
catch
{
Expand All @@ -285,11 +311,11 @@ protected override void BeginProcessing()

ScriptAnalyzer.Instance.Initialize(
this,
rulePaths,
combRulePaths,
this.includeRule,
this.excludeRule,
this.severity,
null == rulePaths ? true : this.includeDefaultRules,
combRulePaths == null || combIncludeDefaultRules,
this.suppressedOnly);
}

Expand Down Expand Up @@ -388,6 +414,13 @@ private bool IsFileParameterSet()
return String.Equals(this.ParameterSetName, "File", StringComparison.OrdinalIgnoreCase);
}

private bool OverrideSwitchParam(bool paramValue, string paramName)
{
return MyInvocation.BoundParameters.ContainsKey(paramName)
? ((SwitchParameter)MyInvocation.BoundParameters[paramName]).ToBool()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if this is false..do you want to use the original value

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is that if the user doesn't specify a switch, then use the value from the settings file. But if the user specifies the switch on the command line then use the command line argument.

For example, if IncludeDefaultRules is set to $true in the settings file and if the user specifies -IncludeDefaultRules:$false on the command line, then the final value for IncludeDefaultRules will be set to $false

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok

: paramValue;
}

#endregion // Private Methods
}
}
37 changes: 32 additions & 5 deletions Engine/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,23 @@ internal enum SettingsMode { None = 0, Auto, File, Hashtable, Preset };
/// </summary>
public class Settings
{
private bool recurseCustomRulePath = false;
private bool includeDefaultRules = false;
private string filePath;
private List<string> includeRules;
private List<string> excludeRules;
private List<string> severities;
private List<string> customRulePath;
private Dictionary<string, Dictionary<string, object>> ruleArguments;

public string FilePath { get { return filePath; } }
public IEnumerable<string> IncludeRules { get { return includeRules; } }
public IEnumerable<string> ExcludeRules { get { return excludeRules; } }
public IEnumerable<string> Severities { get { return severities; } }
public Dictionary<string, Dictionary<string, object>> RuleArguments { get { return ruleArguments; } }
public bool RecurseCustomRulePath => recurseCustomRulePath;
public bool IncludeDefaultRules => includeDefaultRules;
public string FilePath => filePath;
public IEnumerable<string> IncludeRules => includeRules;
public IEnumerable<string> ExcludeRules => excludeRules;
public IEnumerable<string> Severities => severities;
public IEnumerable<string> CustomRulePath => customRulePath;
public Dictionary<string, Dictionary<string, object>> RuleArguments => ruleArguments;

/// <summary>
/// Create a settings object from the input object.
Expand Down Expand Up @@ -400,6 +406,27 @@ private void parseSettingsHashtable(Hashtable settingsHashtable)
excludeRules = GetData(val, key);
break;

case "customrulepath":
customRulePath = GetData(val, key);
break;

case "includedefaultrules":
case "recursecustomrulepath":
if (!(val is bool))
{
throw new InvalidDataException(string.Format(
CultureInfo.CurrentCulture,
Strings.SettingsValueTypeMustBeBool,
settingKey));
}

var booleanVal = (bool)val;
var field = this.GetType().GetField(
key,
BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.NonPublic);
field.SetValue(this, booleanVal);
break;

case "rules":
try
{
Expand Down
3 changes: 3 additions & 0 deletions Engine/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,9 @@
<data name="SettingsNotParsable" xml:space="preserve">
<value>Cannot parse settings. Will abort the invocation.</value>
</data>
<data name="SettingsValueTypeMustBeBool" xml:space="preserve">
<value>{0} property must be of type bool.</value>
</data>
<data name="ModuleDepHandlerTempLocation" xml:space="preserve">
<value>Temporary module location: {0}.</value>
</data>
Expand Down
8 changes: 4 additions & 4 deletions New-StronglyTypedCsFileForResx.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ internal class {0} {{
$entry -f $name,$val
}
} | Out-String

$bodyCode = $body -f $shortClassName,$ModuleName,$entries,$ClassName

if ($NamespaceName)
Expand All @@ -126,10 +126,10 @@ internal class {0} {{
return $resultCode -replace "`r`n?|`n","`r`n"
}

$projectRoot = Split-Path $MyInvocation.InvocationName
$projectRoot = $PWD
if (-not (Test-Path "$projectRoot/global.json"))
{
throw "Not in solution root"
throw "Not in solution root: $projectRoot"
}
$inputFilePath = Join-Path $projectRoot "$project/Strings.resx"
$outputFilePath = Join-Path $projectRoot "$project/Strings.cs"
Expand All @@ -141,4 +141,4 @@ if ($project -eq "Rules")
$className += ".Strings"
$xml = [xml](Get-Content -raw $inputFilePath)
$genSource = Get-StronglyTypeCsFileForResx -xml $xml -ModuleName Foo -ClassName $className
Set-Content -Encoding Ascii -Path $outputFilePath -Value $genSource
Set-Content -Encoding Ascii -Path $outputFilePath -Value $genSource
67 changes: 66 additions & 1 deletion Tests/Engine/InvokeScriptAnalyzer.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,74 @@ Describe "Test CustomizedRulePath" {
$customizedRulePath = Invoke-ScriptAnalyzer $directory\TestScript.ps1 -CustomRulePath ("$directory\CommunityAnalyzerRules", "$directory\samplerule", "$directory\samplerule\samplerule2")
$customizedRulePath.Count | Should Be 3
}

}

if (!$testingLibraryUsage)
{
Context "When used from settings file" {
It "Should use the CustomRulePath parameter" {
$settings = @{
CustomRulePath = "$directory\CommunityAnalyzerRules"
IncludeDefaultRules = $false
RecurseCustomRulePath = $false
}

$v = Invoke-ScriptAnalyzer -Path $directory\TestScript.ps1 -Settings $settings
$v.Count | Should Be 1
}

It "Should use the IncludeDefaultRulePath parameter" {
$settings = @{
CustomRulePath = "$directory\CommunityAnalyzerRules"
IncludeDefaultRules = $true
RecurseCustomRulePath = $false
}

$v = Invoke-ScriptAnalyzer -Path $directory\TestScript.ps1 -Settings $settings
$v.Count | Should Be 2
}

It "Should use the RecurseCustomRulePath parameter" {
$settings = @{
CustomRulePath = "$directory\samplerule"
IncludeDefaultRules = $false
RecurseCustomRulePath = $true
}

$v = Invoke-ScriptAnalyzer -Path $directory\TestScript.ps1 -Settings $settings
$v.Count | Should Be 3
}
}

Context "When used from settings file and command line simulataneusly" {
BeforeAll {
$settings = @{
CustomRulePath = "$directory\samplerule"
IncludeDefaultRules = $false
RecurseCustomRulePath = $false
}
$isaParams = @{
Path = "$directory\TestScript.ps1"
Settings = $settings
}
}

It "Should combine CustomRulePaths" {
$v = Invoke-ScriptAnalyzer @isaParams -CustomRulePath "$directory\CommunityAnalyzerRules"
$v.Count | Should Be 2
}

It "Should override the settings IncludeDefaultRules parameter" {
$v = Invoke-ScriptAnalyzer @isaParams -IncludeDefaultRules
$v.Count | Should Be 2
}

It "Should override the settings RecurseCustomRulePath parameter" {
$v = Invoke-ScriptAnalyzer @isaParams -RecurseCustomRulePath
$v.Count | Should Be 3
}
}
}

Context "When used incorrectly" {
It "file cannot be found" {
Expand Down
65 changes: 65 additions & 0 deletions Tests/Engine/Settings.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,69 @@ Describe "Settings Class" {
$settings.RuleArguments["PSProvideCommentHelp"]["Placement"] | Should Be 'end'
}
}

Context "When CustomRulePath parameter is provided" {
It "Should return an array of 1 item when only 1 path is given in a hashtable" {
$rulePath = "C:\rules\module1"
$settingsHashtable = @{
CustomRulePath = $rulePath
}

$settings = New-Object -TypeName $settingsTypeName -ArgumentList $settingsHashtable
$settings.CustomRulePath.Count | Should Be 1
$settings.CustomRulePath[0] | Should be $rulePath
}

It "Should return an array of n items when n items are given in a hashtable" {
$rulePaths = @("C:\rules\module1", "C:\rules\module2")
$settingsHashtable = @{
CustomRulePath = $rulePaths
}

$settings = New-Object -TypeName $settingsTypeName -ArgumentList $settingsHashtable
$settings.CustomRulePath.Count | Should Be $rulePaths.Count
0..($rulePaths.Count - 1) | ForEach-Object { $settings.CustomRulePath[$_] | Should be $rulePaths[$_] }

}

It "Should detect the parameter in a settings file" {
$settings = New-Object -TypeName $settingsTypeName `
-ArgumentList ([System.IO.Path]::Combine($project1Root, "CustomRulePathSettings.psd1"))
$settings.CustomRulePath.Count | Should Be 2
}
}

@("IncludeDefaultRules", "RecurseCustomRulePath") | ForEach-Object {
$paramName = $_
Context "When $paramName parameter is provided" {
It "Should correctly set the value if a boolean is given - true" {
$settingsHashtable = @{}
$settingsHashtable.Add($paramName, $true)

$settings = New-Object -TypeName $settingsTypeName -ArgumentList $settingsHashtable
$settings."$paramName" | Should Be $true
}

It "Should correctly set the value if a boolean is given - false" {
$settingsHashtable = @{}
$settingsHashtable.Add($paramName, $false)

$settings = New-Object -TypeName $settingsTypeName -ArgumentList $settingsHashtable
$settings."$paramName" | Should Be $false
}

It "Should throw if a non-boolean value is given" {
$settingsHashtable = @{}
$settingsHashtable.Add($paramName, "some random string")

{ New-Object -TypeName $settingsTypeName -ArgumentList $settingsHashtable } | Should Throw
}

It "Should detect the parameter in a settings file" {
$settings = New-Object -TypeName $settingsTypeName `
-ArgumentList ([System.IO.Path]::Combine($project1Root, "CustomRulePathSettings.psd1"))
$settings."$paramName" | Should Be $true
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@{
"CustomRulePath" = @("C:\rules\module1", "C:\rules\module2")
"IncludeDefaultRules" = $true
"RecurseCustomRulePath" = $true
}