Skip to content

Add suggested corrections to allow violation fixes #508

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 26 commits into from
Apr 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d8a2a67
Add SuggestdCorrection property to DiagnosticRecord
Mar 23, 2016
c8fe6d6
Set SuggestedCorrection property in AvoidAlias rule
Mar 23, 2016
a18446e
Set SuggestedCorrection property in MisleadingBacktick rule
Mar 23, 2016
50706a1
Add an extent type to encapsulate correction information
Mar 25, 2016
e997906
Modify CorrectionExtent class
Mar 25, 2016
d811566
Modify correction extent of avoid using alias
Mar 30, 2016
eb05a8e
Modify correction extent of misleading backticks rule
Mar 30, 2016
b0a7c57
Add a file that contains helper functions for tests
Mar 30, 2016
8a02fa7
Add correction extent to AvoidUsingPlainTextForPassword rule
Mar 30, 2016
e65b9a9
Refactor some tests that check correction extent
Mar 30, 2016
567b1ae
Fix a bug in a test helper function
Mar 30, 2016
cc68a2e
Refactor MissingModuleManifest Rule
Apr 4, 2016
afccf35
Add correction extent to UseToExportFieldsInManifest rule
Apr 5, 2016
10bcbdc
Add Description property to CorrectionExtent class
Apr 5, 2016
8072873
Add CorrectionExtent description to some rules
Apr 5, 2016
7de186a
Add violation correction to readme
Apr 19, 2016
804ead7
Fix failing tests
Apr 19, 2016
ba7463b
Add violation correction section to about_PSScriptScriptAnalyzer
Apr 20, 2016
40d0708
Add localized strings for correction description
Apr 23, 2016
c62cdca
Change SuggestedCorrections type to IEnumerable
Apr 23, 2016
d85e978
Fix AvoidAlias correction extent
Apr 23, 2016
13c5c3f
Fix AvoidUsingPlainTextForPassword correction extent
Apr 23, 2016
c4065e7
Rename and make static a method in Helper
Apr 23, 2016
6fcf059
Modify UseToExportFieldInManifest rule
Apr 23, 2016
5e29444
Modify a helper method
Apr 23, 2016
091c71d
Resolve merge conflict
Apr 23, 2016
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
144 changes: 144 additions & 0 deletions Engine/Generic/CorrectionExtent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management.Automation.Language;
using System.Text;
using System.Threading.Tasks;

namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic
{
public class CorrectionExtent
{
public int EndColumnNumber
{
get
{
return endColumnNumber;
}
}

public int EndLineNumber
{
get
{
return endLineNumber;
}
}

public string File
{
get
{
return file;
}
}

public int StartColumnNumber
{
get
{
return startColumnNumber;
}
}

public int StartLineNumber
{
get
{
return startLineNumber;
}
}

public string Text
{
get
{
return text;
}
}

public string Description
{
get
{
return description;
}
}

private string file;
private int startLineNumber;
private int endLineNumber;
private int startColumnNumber;
private int endColumnNumber;
private string text;
private string description;

public CorrectionExtent(
int startLineNumber,
int endLineNumber,
int startColumnNumber,
int endColumnNumber,
string text,
string file)
: this(
startLineNumber,
endLineNumber,
startColumnNumber,
endColumnNumber,
text,
file,
null)
{
}

public CorrectionExtent(
int startLineNumber,
int endLineNumber,
int startColumnNumber,
int endColumnNumber,
string text,
string file,
string description)
{
this.startLineNumber = startLineNumber;
this.endLineNumber = endLineNumber;
this.startColumnNumber = startColumnNumber;
this.endColumnNumber = endColumnNumber;
this.file = file;
this.text = text;
this.description = description;
ThrowIfInvalidArguments();
}



private void ThrowIfInvalidArguments()
{
ThrowIfNull<string>(file, "filename");
ThrowIfNull<string>(text, "text");
ThrowIfDecreasing(startLineNumber, endLineNumber, "start line number cannot be less than end line number");
if (startLineNumber == endLineNumber)
{
ThrowIfDecreasing(StartColumnNumber, endColumnNumber, "start column number cannot be less than end column number for a one line extent");
}
}

private void ThrowIfDecreasing(int start, int end, string message)
{
if (start > end)
{
throw new ArgumentException(message);
}
}

private void ThrowIfNull<T>(T arg, string argName)
{
if (arg == null)
{
throw new ArgumentNullException(argName);
}
}

}
}
23 changes: 18 additions & 5 deletions Engine/Generic/DiagnosticRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// THE SOFTWARE.
//

using System.Collections.Generic;
using System.Management.Automation.Language;

namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic
Expand All @@ -26,6 +27,7 @@ public class DiagnosticRecord
private DiagnosticSeverity severity;
private string scriptName;
private string ruleSuppressionId;
private List<CorrectionExtent> suggestedCorrections;

/// <summary>
/// Represents a string from the rule about why this diagnostic was created.
Expand Down Expand Up @@ -91,30 +93,41 @@ public string RuleSuppressionID
set { ruleSuppressionId = value; }
}

/// <summary>
/// Returns suggested correction
/// return value can be null
/// </summary>
public IEnumerable<CorrectionExtent> SuggestedCorrections
{
get { return suggestedCorrections; }
}

/// <summary>
/// DiagnosticRecord: The constructor for DiagnosticRecord class.
/// </summary>
public DiagnosticRecord()
{

}

/// <summary>
/// DiagnosticRecord: The constructor for DiagnosticRecord class.
/// DiagnosticRecord: The constructor for DiagnosticRecord class that takes in suggestedCorrection
/// </summary>
/// <param name="message">A string about why this diagnostic was created</param>
/// <param name="extent">The place in the script this diagnostic refers to</param>
/// <param name="ruleName">The name of the rule that created this diagnostic</param>
/// <param name="severity">The severity of this diagnostic</param>
/// <param name="scriptName">The name of the script file being analyzed</param>
public DiagnosticRecord(string message, IScriptExtent extent, string ruleName, DiagnosticSeverity severity, string scriptName, string ruleId = null)
/// <param name="suggestedCorrections">The correction suggested by the rule to replace the extent text</param>
public DiagnosticRecord(string message, IScriptExtent extent, string ruleName, DiagnosticSeverity severity, string scriptName, string ruleId = null, List<CorrectionExtent> suggestedCorrections = null)
{
Message = string.IsNullOrEmpty(message) ? string.Empty : message;
Message = string.IsNullOrEmpty(message) ? string.Empty : message;
RuleName = string.IsNullOrEmpty(ruleName) ? string.Empty : ruleName;
Extent = extent;
Extent = extent;
Severity = severity;
ScriptName = string.IsNullOrEmpty(scriptName) ? string.Empty : scriptName;
ruleSuppressionId = ruleId;
this.suggestedCorrections = suggestedCorrections;
}
}

Expand Down
61 changes: 58 additions & 3 deletions Engine/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using System.Management.Automation.Language;
using System.Globalization;
using Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic;
using System.Management.Automation.Runspaces;

namespace Microsoft.Windows.PowerShell.ScriptAnalyzer
{
Expand Down Expand Up @@ -104,14 +105,14 @@ internal set
private string[] functionScopes = new string[] { "global:", "local:", "script:", "private:"};

private string[] variableScopes = new string[] { "global:", "local:", "script:", "private:", "variable:", ":"};

#endregion

/// <summary>
/// Initializes the Helper class.
/// </summary>
private Helper()
{

}

/// <summary>
Expand Down Expand Up @@ -229,6 +230,61 @@ public bool IsDscResourceModule(string filePath)

return false;
}

/// <summary>
/// Gets the module manifest
/// </summary>
/// <param name="filePath"></param>
/// <param name="errorRecord"></param>
/// <returns>Returns a object of type PSModuleInfo</returns>
public PSModuleInfo GetModuleManifest(string filePath, out IEnumerable<ErrorRecord> errorRecord)
{
errorRecord = null;
PSModuleInfo psModuleInfo = null;
Collection<PSObject> psObj = null;
var ps = System.Management.Automation.PowerShell.Create();
try
{
ps.AddCommand("Test-ModuleManifest");
ps.AddParameter("Path", filePath);
ps.AddParameter("WarningAction", ActionPreference.SilentlyContinue);
psObj = ps.Invoke();
}
catch (CmdletInvocationException e)
{
// Invoking Test-ModuleManifest on a module manifest that doesn't have all the valid keys
// throws a NullReferenceException. This is probably a bug in Test-ModuleManifest and hence
// we consume it to allow execution of the of this method.
if (e.InnerException == null || e.InnerException.GetType() != typeof(System.NullReferenceException))
{
throw;
}
}
if (ps.HadErrors && ps.Streams != null && ps.Streams.Error != null)
{
var errorRecordArr = new ErrorRecord[ps.Streams.Error.Count];
ps.Streams.Error.CopyTo(errorRecordArr, 0);
errorRecord = errorRecordArr;
}
if (psObj != null && psObj.Any() && psObj[0] != null)
{
psModuleInfo = psObj[0].ImmediateBaseObject as PSModuleInfo;
}
ps.Dispose();
return psModuleInfo;
}

/// <summary>
/// Checks if the error record is MissingMemberException
/// </summary>
/// <param name="errorRecord"></param>
/// <returns>Returns a boolean value indicating the presence of MissingMemberException</returns>
public static bool IsMissingManifestMemberException(ErrorRecord errorRecord)
{
return errorRecord.CategoryInfo != null
&& errorRecord.CategoryInfo.Category == ErrorCategory.ResourceUnavailable
&& string.Equals("MissingMemberException", errorRecord.CategoryInfo.Reason, StringComparison.OrdinalIgnoreCase);
}

/// <summary>
/// Get the list of exported function by analyzing the ast
Expand Down Expand Up @@ -1317,8 +1373,7 @@ public static string[] ProcessCustomRulePaths(string[] rulePaths, SessionState s

}


#endregion
#endregion Methods
}


Expand Down
37 changes: 19 additions & 18 deletions Engine/ScriptAnalyzerEngine.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,23 @@
<RootNamespace>Microsoft.Windows.PowerShell.ScriptAnalyzer</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'PSV3 Debug|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\PSV3 Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;PSV3</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'PSV3 Release|AnyCPU'">
<OutputPath>bin\PSV3 Release\</OutputPath>
<DefineConstants>TRACE;PSV3</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\PSV3 Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;PSV3</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'PSV3 Release|AnyCPU'">
<OutputPath>bin\PSV3 Release\</OutputPath>
<DefineConstants>TRACE;PSV3</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
Expand All @@ -70,6 +70,7 @@
<Compile Include="Commands\InvokeScriptAnalyzerCommand.cs" />
<Compile Include="Generic\AvoidCmdletGeneric.cs" />
<Compile Include="Generic\AvoidParameterGeneric.cs" />
<Compile Include="Generic\CorrectionExtent.cs" />
<Compile Include="Generic\SuppressedRecord.cs" />
<Compile Include="Generic\DiagnosticRecord.cs" />
<Compile Include="Generic\ExternalRule.cs" />
Expand Down Expand Up @@ -101,7 +102,7 @@
<Compile Include="VariableAnalysisBase.cs" />
</ItemGroup>
<ItemGroup>
<None Include="PSScriptAnalyzer.psm1" />
<None Include="PSScriptAnalyzer.psm1" />
<None Include="PSScriptAnalyzer.psd1" />
<None Include="ScriptAnalyzer.format.ps1xml" />
<None Include="ScriptAnalyzer.types.ps1xml" />
Expand Down
Loading