Skip to content

Improve settings implementation #717

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 29 commits into from
Feb 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d027b4e
Move GetShippedSettingsDirectory to helper
Dec 14, 2016
1dbf68a
Allow settings paramter to take preset value
Dec 14, 2016
84dd808
Make setting preset related methods public
Dec 14, 2016
d05f9f9
Add argument completer for settings parameter
Dec 14, 2016
33bb0a9
Add argument completers to cmdlets
Dec 14, 2016
8fb56b4
Fix argument completer for settings parameter
Dec 14, 2016
4568076
Update verbose messages of invoke-scriptanalyzer
Dec 14, 2016
fe17cb1
Add copyright header to correctionsextent
Dec 14, 2016
02db72f
Add Settings class to manage pssa settings
Dec 15, 2016
1469738
Add filepath property to settings class
Dec 16, 2016
5de5d8e
Add tests for settings class
Dec 16, 2016
d720b6b
Add enum type to indicate settings mode
Feb 16, 2017
c5b7edd
Add method to find settings mode
Feb 16, 2017
f830fc3
Determine settings mode before processing settings
Feb 16, 2017
aee3f2b
Add method to get value from hashtable ast
Feb 16, 2017
4279c8c
Parse constants from settings hashtable ast
Feb 23, 2017
bfd5080
Implement own value getter from hashtable ast
Feb 23, 2017
46b14fb
Make ConvertToRuleArgumentType private
Feb 23, 2017
a46da26
Add method to update settings
Feb 23, 2017
f371b98
Use Settings class to parse input settings
Feb 23, 2017
24fce48
Update Settings.Severity to Settings.Severities
Feb 23, 2017
5513dcc
Move SettingsMode to Settings.cs
Feb 23, 2017
d7b23a9
Move settings method from Helper to Settings
Feb 23, 2017
080e872
Move settings method to Settings.cs
Feb 23, 2017
73a1e7b
Update tests for PS v3 and v4 compatibility
Feb 24, 2017
fde62eb
Add tests to verify int and boolean type parsing
Feb 24, 2017
9375ac3
Localize settings related error messages
Feb 28, 2017
b9da9c5
Move Settings class to Engine/ from Engine/Generic/
Feb 28, 2017
5c12137
Update changelog
Feb 28, 2017
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
17 changes: 16 additions & 1 deletion CHANGELOG.MD
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
## [1.10.0](https://github.com/PowerShell/PSScriptAnalyzer/tree/1.10.0) - 2017-01-19
## unreleased

### Added
- Built-in settings presets to specify settings from command line. Currently, PSSA ships with `PSGallery`, `CodeFormatting`, `DSC`, and other setting presets. All of them can be found in the `Settings/` directory in the module. To use them just pass them as an argument to the `Settings` parameters. For example, if you want to run rules that *powershellgallery* runs, then use the following command.
```powershell
PS> Invoke-ScriptAnalyzer -Path /path/to/your/module -Settings PSGallery
```
- Argument completion for built-in settings presets.
- Argument completion for `IncludeRule` and `ExcludeRule` parameters.

### Fixed

### Changed
- Settings implementation to decouple it from engine.

## [1.10.0](https://github.com/PowerShell/PSScriptAnalyzer/tree/1.10.0) - 2017-01-19
### Added
- Three rules to enable code formatting feature in vscode (#690)
- [PSPlaceOpenBrace](https://github.com/PowerShell/PSScriptAnalyzer/blob/03a6e2b4ee24894bf574a8a8ce911d03680da607/RuleDocumentation/PlaceOpenBrace.md)
Expand Down
120 changes: 65 additions & 55 deletions Engine/Commands/InvokeScriptAnalyzerCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,9 @@ public SwitchParameter SaveDscDependency
}
private bool saveDscDependency;
#endif // !PSV3
#endregion Parameters
#endregion Parameters

#region Overrides
#region Overrides

/// <summary>
/// Imports all known rules and loggers.
Expand All @@ -227,67 +227,74 @@ protected override void BeginProcessing()
Helper.Instance.SetPSVersionTable(psVersionTable);
}

string[] rulePaths = Helper.ProcessCustomRulePaths(customRulePath,
this.SessionState, recurseCustomRulePath);
string[] rulePaths = Helper.ProcessCustomRulePaths(
customRulePath,
this.SessionState,
recurseCustomRulePath);

if (IsFileParameterSet())
{
ProcessPath();
}

var settingFileHasErrors = false;
if (settings == null
&& processedPaths != null
&& processedPaths.Count == 1)
object settingsFound;
var settingsMode = PowerShell.ScriptAnalyzer.Settings.FindSettingsMode(
this.settings,
processedPaths == null || processedPaths.Count == 0 ? null : processedPaths[0],
out settingsFound);

switch (settingsMode)
{
// add a directory separator character because if there is no trailing separator character, it will return the parent
var directory = processedPaths[0].TrimEnd(System.IO.Path.DirectorySeparatorChar);
if (File.Exists(directory))
{
// if given path is a file, get its directory
directory = System.IO.Path.GetDirectoryName(directory);
}
case SettingsMode.Auto:
this.WriteVerbose(
String.Format(
CultureInfo.CurrentCulture,
Strings.SettingsNotProvided,
path));
this.WriteVerbose(
String.Format(
CultureInfo.CurrentCulture,
Strings.SettingsAutoDiscovered,
(string)settingsFound));
break;

this.WriteVerbose(
String.Format(
"Settings not provided. Will look for settings file in the given path {0}.",
path));
var settingsFileAutoDiscovered = false;
if (Directory.Exists(directory))
{
// if settings are not provided explicitly, look for it in the given path
// check if pssasettings.psd1 exists
var settingsFilename = "PSScriptAnalyzerSettings.psd1";
var settingsFilepath = System.IO.Path.Combine(directory, settingsFilename);
if (File.Exists(settingsFilepath))
{
settingsFileAutoDiscovered = true;
this.WriteVerbose(
String.Format(
"Found {0} in {1}. Will use it to provide settings for this invocation.",
settingsFilename,
directory));
settingFileHasErrors = !ScriptAnalyzer.Instance.ParseProfile(settingsFilepath, this.SessionState.Path, this);
}
}
case SettingsMode.Preset:
case SettingsMode.File:
this.WriteVerbose(
String.Format(
CultureInfo.CurrentCulture,
Strings.SettingsUsingFile,
(string)settingsFound));
break;

if (!settingsFileAutoDiscovered)
{
case SettingsMode.Hashtable:
this.WriteVerbose(
String.Format(
"Cannot find a settings file in the given path {0}.",
path));
}
}
else
{
settingFileHasErrors = !ScriptAnalyzer.Instance.ParseProfile(this.settings, this.SessionState.Path, this);
CultureInfo.CurrentCulture,
Strings.SettingsUsingHashtable));
break;

default: // case SettingsMode.None
this.WriteVerbose(
String.Format(
CultureInfo.CurrentCulture,
Strings.SettingsCannotFindFile));
break;
}

if (settingFileHasErrors)
if (settingsMode != SettingsMode.None)
{
this.WriteWarning("Cannot parse settings. Will abort the invocation.");
stopProcessing = true;
return;
try
{
var settingsObj = new Settings(settingsFound);
ScriptAnalyzer.Instance.UpdateSettings(settingsObj);
}
catch
{
this.WriteWarning(String.Format(CultureInfo.CurrentCulture, Strings.SettingsNotParsable));
stopProcessing = true;
return;
}
}

ScriptAnalyzer.Instance.Initialize(
Expand Down Expand Up @@ -323,7 +330,8 @@ protected override void ProcessRecord()
ScriptAnalyzer.Instance.ModuleHandler = moduleHandler;
this.WriteVerbose(
String.Format(
"Temporary module location: {0}",
CultureInfo.CurrentCulture,
Strings.ModuleDepHandlerTempLocation,
moduleHandler.TempModulePath));
ProcessInput();
}
Expand All @@ -346,9 +354,10 @@ protected override void StopProcessing()
base.StopProcessing();
}

#endregion
#endregion

#region Private Methods

#region Methods
private void ProcessInput()
{
IEnumerable<DiagnosticRecord> diagnosticsList = Enumerable.Empty<DiagnosticRecord>();
Expand Down Expand Up @@ -392,6 +401,7 @@ private bool IsFileParameterSet()
{
return String.Equals(this.ParameterSetName, "File", StringComparison.OrdinalIgnoreCase);
}
#endregion

#endregion // Private Methods
}
}
}
14 changes: 13 additions & 1 deletion Engine/Generic/CorrectionExtent.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
using System;
//
// Copyright (c) Microsoft Corporation.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand Down
1 change: 1 addition & 0 deletions Engine/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic;
using System.Management.Automation.Runspaces;
using System.Collections;
using System.Reflection;

namespace Microsoft.Windows.PowerShell.ScriptAnalyzer
{
Expand Down
25 changes: 24 additions & 1 deletion Engine/PSScriptAnalyzer.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ else
{
if ($PSVersionTable.PSVersion -lt [Version]'5.0') {
$binaryModuleRoot = Join-Path -Path $PSModuleRoot -ChildPath 'PSv3'
}
}
}

$binaryModulePath = Join-Path -Path $binaryModuleRoot -ChildPath 'Microsoft.Windows.PowerShell.ScriptAnalyzer.dll'
Expand All @@ -27,4 +27,27 @@ $binaryModule = Import-Module -Name $binaryModulePath -PassThru
# When the module is unloaded, remove the nested binary module that was loaded with it
$PSModule.OnRemove = {
Remove-Module -ModuleInfo $binaryModule
}

if (Get-Command Register-ArgumentCompleter -ErrorAction Ignore)
{
Register-ArgumentCompleter -CommandName 'Invoke-ScriptAnalyzer' -ParameterName 'Settings' -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParmeter)

[Microsoft.Windows.PowerShell.ScriptAnalyzer.Settings]::GetSettingPresets() | `
Where-Object {$_ -like "$wordToComplete*"} | `
ForEach-Object { New-Object System.Management.Automation.CompletionResult $_ }
}

Function RuleNameCompleter
{
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParmeter)

Get-ScriptAnalyzerRule *$wordToComplete* | `
ForEach-Object { New-Object System.Management.Automation.CompletionResult $_.RuleName }
}

Register-ArgumentCompleter -CommandName 'Invoke-ScriptAnalyzer' -ParameterName 'IncludeRule' -ScriptBlock $Function:RuleNameCompleter
Register-ArgumentCompleter -CommandName 'Invoke-ScriptAnalyzer' -ParameterName 'ExcludeRule' -ScriptBlock $Function:RuleNameCompleter
Register-ArgumentCompleter -CommandName 'Get-ScriptAnalyzerRule' -ParameterName 'Name' -ScriptBlock $Function:RuleNameCompleter
}
24 changes: 24 additions & 0 deletions Engine/ScriptAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,30 @@ public void CleanUp()
suppressedOnly = false;
}

/// <summary>
/// Update includerules, excluderules, severity and rule arguments.
/// </summary>
/// <param name="settings">An object of type Settings</param>
public void UpdateSettings(Settings settings)
{
if (settings == null)
{
throw new ArgumentNullException(nameof(settings));
}

this.severity = (!settings.Severities.Any()) ? null : settings.Severities.ToArray();
this.includeRule = (!settings.IncludeRules.Any()) ? null : settings.IncludeRules.ToArray();
this.excludeRule = (!settings.ExcludeRules.Any()) ? null : settings.ExcludeRules.ToArray();
if (settings.RuleArguments != null)
{
Helper.Instance.SetRuleArguments(
settings.RuleArguments.ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value as object,
StringComparer.OrdinalIgnoreCase));
}
}

internal bool ParseProfile(object profileObject, PathIntrinsics path, IOutputWriter writer)
{
// profile was not given
Expand Down
1 change: 1 addition & 0 deletions Engine/ScriptAnalyzerEngine.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
<Compile Include="Generic\ConfigurableRule.cs" />
<Compile Include="Generic\ModuleDependencyHandler.cs" />
<Compile Include="Generic\CorrectionExtent.cs" />
<Compile Include="Settings.cs" />
<Compile Include="Generic\SuppressedRecord.cs" />
<Compile Include="Generic\DiagnosticRecord.cs" />
<Compile Include="Generic\ExternalRule.cs" />
Expand Down
Loading