Skip to content

Commit b061db2

Browse files
author
Kapil Borle
committed
Merge branch 'development' into AddSuggestedCorrections
Conflicts: Engine/Generic/DiagnosticRecord.cs Engine/Helper.cs * Fix the merge conflict * Handle scriptblock inputs for getting correction extents. Creating a CorrectionExtent instance would throw a null argument exception when filename is null, i.e., for scriptblock input
2 parents 091c71d + a467aff commit b061db2

19 files changed

+474
-162
lines changed

Engine/Generic/DiagnosticRecord.cs

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
// THE SOFTWARE.
1111
//
1212

13+
14+
15+
using System;
1316
using System.Collections.Generic;
1417
using System.Management.Automation.Language;
1518

@@ -25,7 +28,7 @@ public class DiagnosticRecord
2528
private IScriptExtent extent;
2629
private string ruleName;
2730
private DiagnosticSeverity severity;
28-
private string scriptName;
31+
private string scriptPath;
2932
private string ruleSuppressionId;
3033
private List<CorrectionExtent> suggestedCorrections;
3134

@@ -35,7 +38,7 @@ public class DiagnosticRecord
3538
public string Message
3639
{
3740
get { return message; }
38-
set { message = value; }
41+
protected set { message = string.IsNullOrEmpty(value) ? string.Empty : value; }
3942
}
4043

4144
/// <summary>
@@ -44,7 +47,7 @@ public string Message
4447
public IScriptExtent Extent
4548
{
4649
get { return extent; }
47-
set { extent = value; }
50+
protected set { extent = value; }
4851
}
4952

5053
/// <summary>
@@ -53,7 +56,7 @@ public IScriptExtent Extent
5356
public string RuleName
5457
{
5558
get { return ruleName; }
56-
set { ruleName = value; }
59+
protected set { ruleName = string.IsNullOrEmpty(value) ? string.Empty : value; }
5760
}
5861

5962
/// <summary>
@@ -70,18 +73,16 @@ public DiagnosticSeverity Severity
7073
/// </summary>
7174
public string ScriptName
7275
{
73-
get { return scriptName; }
74-
//Trim down to the leaf element of the filePath and pass it to Diagnostic Record
75-
set {
76-
if (!string.IsNullOrWhiteSpace(value))
77-
{
78-
scriptName = System.IO.Path.GetFileName(value);
79-
}
80-
else
81-
{
82-
scriptName = string.Empty;
83-
}
84-
}
76+
get { return string.IsNullOrEmpty(scriptPath) ? string.Empty : System.IO.Path.GetFileName(scriptPath);}
77+
}
78+
79+
/// <summary>
80+
/// Returns the path of the script.
81+
/// </summary>
82+
public string ScriptPath
83+
{
84+
get { return scriptPath; }
85+
protected set { scriptPath = string.IsNullOrEmpty(value) ? string.Empty : value; }
8586
}
8687

8788
/// <summary>
@@ -117,18 +118,19 @@ public DiagnosticRecord()
117118
/// <param name="extent">The place in the script this diagnostic refers to</param>
118119
/// <param name="ruleName">The name of the rule that created this diagnostic</param>
119120
/// <param name="severity">The severity of this diagnostic</param>
120-
/// <param name="scriptName">The name of the script file being analyzed</param>
121+
/// <param name="scriptPath">The full path of the script file being analyzed</param>
121122
/// <param name="suggestedCorrections">The correction suggested by the rule to replace the extent text</param>
122-
public DiagnosticRecord(string message, IScriptExtent extent, string ruleName, DiagnosticSeverity severity, string scriptName, string ruleId = null, List<CorrectionExtent> suggestedCorrections = null)
123+
public DiagnosticRecord(string message, IScriptExtent extent, string ruleName, DiagnosticSeverity severity, string scriptPath, string ruleId = null, List<CorrectionExtent> suggestedCorrections = null)
123124
{
124-
Message = string.IsNullOrEmpty(message) ? string.Empty : message;
125-
RuleName = string.IsNullOrEmpty(ruleName) ? string.Empty : ruleName;
126-
Extent = extent;
125+
Message = message;
126+
RuleName = ruleName;
127+
Extent = extent;
127128
Severity = severity;
128-
ScriptName = string.IsNullOrEmpty(scriptName) ? string.Empty : scriptName;
129-
ruleSuppressionId = ruleId;
129+
ScriptPath = scriptPath;
130+
RuleSuppressionID = ruleId;
130131
this.suggestedCorrections = suggestedCorrections;
131132
}
133+
132134
}
133135

134136

Engine/Generic/SuppressedRecord.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public SuppressedRecord(DiagnosticRecord record, RuleSuppression suppression)
4040
Message = record.Message;
4141
Extent = record.Extent;
4242
Severity = record.Severity;
43-
ScriptName = record.ScriptName;
43+
ScriptPath = record.ScriptPath;
4444
RuleSuppressionID = record.RuleSuppressionID;
4545
}
4646
}

Engine/Helper.cs

Lines changed: 157 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -712,22 +712,30 @@ public IScriptExtent GetScriptExtentForFunctionName(FunctionDefinitionAst functi
712712
if (null == functionDefinitionAst)
713713
{
714714
return null;
715-
}
716-
717-
// Obtain the index where the function name is in Tokens
718-
int funcTokenIndex = Tokens.Select((s, index) => new { s, index })
719-
.Where(x => x.s.Extent.StartOffset == functionDefinitionAst.Extent.StartOffset)
720-
.Select(x => x.index).FirstOrDefault();
715+
}
716+
var funcNameTokens = Tokens.Where(
717+
token =>
718+
ContainsExtent(functionDefinitionAst.Extent, token.Extent)
719+
&& token.Text.Equals(functionDefinitionAst.Name));
720+
var funcNameToken = funcNameTokens.FirstOrDefault();
721+
return funcNameToken == null ? null : funcNameToken.Extent;
722+
}
721723

722-
if (funcTokenIndex > 0 && funcTokenIndex < Helper.Instance.Tokens.Count())
724+
/// <summary>
725+
/// Return true if subset is contained in set
726+
/// </summary>
727+
/// <param name="set"></param>
728+
/// <param name="subset"></param>
729+
/// <returns>True or False</returns>
730+
private bool ContainsExtent(IScriptExtent set, IScriptExtent subset)
731+
{
732+
if (set == null || subset == null)
723733
{
724-
// return the extent of the next token - this is the extent for the function name
725-
return Tokens[++funcTokenIndex].Extent;
734+
return false;
726735
}
727-
728-
return null;
736+
return set.StartOffset <= subset.StartOffset
737+
&& set.EndOffset >= subset.EndOffset;
729738
}
730-
731739
private void FindClosingParenthesis(string keyword)
732740
{
733741
if (Tokens == null || Tokens.Length == 0)
@@ -1246,12 +1254,16 @@ internal List<RuleSuppression> GetSuppressionsClass(TypeDefinitionAst typeAst)
12461254
/// </summary>
12471255
/// <param name="ruleSuppressions"></param>
12481256
/// <param name="diagnostics"></param>
1249-
public Tuple<List<SuppressedRecord>, List<DiagnosticRecord>> SuppressRule(string ruleName, Dictionary<string, List<RuleSuppression>> ruleSuppressionsDict, List<DiagnosticRecord> diagnostics)
1257+
public Tuple<List<SuppressedRecord>, List<DiagnosticRecord>> SuppressRule(
1258+
string ruleName,
1259+
Dictionary<string, List<RuleSuppression>> ruleSuppressionsDict,
1260+
List<DiagnosticRecord> diagnostics,
1261+
out List<ErrorRecord> errorRecords)
12501262
{
12511263
List<SuppressedRecord> suppressedRecords = new List<SuppressedRecord>();
12521264
List<DiagnosticRecord> unSuppressedRecords = new List<DiagnosticRecord>();
12531265
Tuple<List<SuppressedRecord>, List<DiagnosticRecord>> result = Tuple.Create(suppressedRecords, unSuppressedRecords);
1254-
1266+
errorRecords = new List<ErrorRecord>();
12551267
if (diagnostics == null || diagnostics.Count == 0)
12561268
{
12571269
return result;
@@ -1317,8 +1329,8 @@ public Tuple<List<SuppressedRecord>, List<DiagnosticRecord>> SuppressRule(string
13171329
ruleSuppression.Error = String.Format(CultureInfo.CurrentCulture, Strings.RuleSuppressionErrorFormat, ruleSuppression.StartAttributeLine,
13181330
System.IO.Path.GetFileName(diagnostics.First().Extent.File), String.Format(Strings.RuleSuppressionIDError, ruleSuppression.RuleSuppressionID));
13191331
}
1320-
1321-
this.outputWriter.WriteError(new ErrorRecord(new ArgumentException(ruleSuppression.Error), ruleSuppression.Error, ErrorCategory.InvalidArgument, ruleSuppression));
1332+
errorRecords.Add(new ErrorRecord(new ArgumentException(ruleSuppression.Error), ruleSuppression.Error, ErrorCategory.InvalidArgument, ruleSuppression));
1333+
//this.outputWriter.WriteError(new ErrorRecord(new ArgumentException(ruleSuppression.Error), ruleSuppression.Error, ErrorCategory.InvalidArgument, ruleSuppression));
13221334
}
13231335
}
13241336

@@ -1372,6 +1384,135 @@ public static string[] ProcessCustomRulePaths(string[] rulePaths, SessionState s
13721384
return outPaths.ToArray();
13731385

13741386
}
1387+
1388+
/// <summary>
1389+
/// Check if the function name starts with one of potentailly state changing verbs
1390+
/// </summary>
1391+
/// <param name="functionName"></param>
1392+
/// <returns>true if the function name starts with a state changing verb, otherwise false</returns>
1393+
public bool IsStateChangingFunctionName(string functionName)
1394+
{
1395+
if (functionName == null)
1396+
{
1397+
throw new ArgumentNullException("functionName");
1398+
}
1399+
// Array of verbs that can potentially change the state of a system
1400+
string[] stateChangingVerbs =
1401+
{
1402+
"Restart-",
1403+
"Stop-",
1404+
"New-",
1405+
"Set-",
1406+
"Update-",
1407+
"Reset-",
1408+
"Remove-"
1409+
};
1410+
foreach (var verb in stateChangingVerbs)
1411+
{
1412+
if (functionName.StartsWith(verb, StringComparison.OrdinalIgnoreCase))
1413+
{
1414+
return true;
1415+
}
1416+
}
1417+
return false;
1418+
}
1419+
1420+
/// <summary>
1421+
/// Get the SupportShouldProcess attribute ast
1422+
/// </summary>
1423+
/// <param name="attributeAsts"></param>
1424+
/// <returns>Returns SupportShouldProcess attribute ast if it exists, otherwise returns null</returns>
1425+
public NamedAttributeArgumentAst GetShouldProcessAttributeAst(IEnumerable<AttributeAst> attributeAsts)
1426+
{
1427+
if (attributeAsts == null)
1428+
{
1429+
throw new ArgumentNullException("attributeAsts");
1430+
}
1431+
var cmdletBindingAttributeAst = this.GetCmdletBindingAttributeAst(attributeAsts);
1432+
if (cmdletBindingAttributeAst == null
1433+
|| cmdletBindingAttributeAst.NamedArguments == null)
1434+
{
1435+
return null;
1436+
}
1437+
foreach (var namedAttributeAst in cmdletBindingAttributeAst.NamedArguments)
1438+
{
1439+
if (namedAttributeAst != null
1440+
&& namedAttributeAst.ArgumentName.Equals(
1441+
"SupportsShouldProcess",
1442+
StringComparison.OrdinalIgnoreCase))
1443+
{
1444+
return namedAttributeAst;
1445+
}
1446+
}
1447+
return null;
1448+
}
1449+
1450+
/// <summary>
1451+
/// Get the CmdletBinding attribute ast
1452+
/// </summary>
1453+
/// <param name="attributeAsts"></param>
1454+
/// <returns>Returns CmdletBinding attribute ast if it exists, otherwise returns null</returns>
1455+
public AttributeAst GetCmdletBindingAttributeAst(IEnumerable<AttributeAst> attributeAsts)
1456+
{
1457+
if (attributeAsts == null)
1458+
{
1459+
throw new ArgumentNullException("attributeAsts");
1460+
}
1461+
foreach (var attributeAst in attributeAsts)
1462+
{
1463+
if (attributeAst == null || attributeAst.NamedArguments == null)
1464+
{
1465+
continue;
1466+
}
1467+
if (attributeAst.TypeName.GetReflectionAttributeType()
1468+
== typeof(CmdletBindingAttribute))
1469+
{
1470+
return attributeAst;
1471+
}
1472+
}
1473+
return null;
1474+
}
1475+
1476+
/// <summary>
1477+
/// Get the boolean value of the named attribute argument
1478+
/// </summary>
1479+
/// <param name="namedAttributeArgumentAst"></param>
1480+
/// <returns>Boolean value of the named attribute argument</returns>
1481+
public bool GetNamedArgumentAttributeValue(NamedAttributeArgumentAst namedAttributeArgumentAst)
1482+
{
1483+
if (namedAttributeArgumentAst == null)
1484+
{
1485+
throw new ArgumentNullException("namedAttributeArgumentAst");
1486+
}
1487+
if (namedAttributeArgumentAst.ExpressionOmitted)
1488+
{
1489+
return true;
1490+
}
1491+
else
1492+
{
1493+
var varExpAst = namedAttributeArgumentAst.Argument as VariableExpressionAst;
1494+
if (varExpAst == null)
1495+
{
1496+
var constExpAst = namedAttributeArgumentAst.Argument as ConstantExpressionAst;
1497+
if (constExpAst == null)
1498+
{
1499+
return false;
1500+
}
1501+
bool constExpVal;
1502+
if (LanguagePrimitives.TryConvertTo<bool>(constExpAst.Value, out constExpVal))
1503+
{
1504+
return constExpVal;
1505+
}
1506+
}
1507+
else
1508+
{
1509+
return varExpAst.VariablePath.UserPath.Equals(
1510+
bool.TrueString,
1511+
StringComparison.OrdinalIgnoreCase);
1512+
}
1513+
}
1514+
return false;
1515+
}
13751516

13761517
#endregion Methods
13771518
}

0 commit comments

Comments
 (0)