Skip to content

Commit 31f09fd

Browse files
author
Kapil Borle
committed
Move some methods to Helper class
Refactors and moves some methods from UseShouldProcessForStateChangingFunctions to Helper class to allow reusability. These methods can potentially be used by other rules that deal with the SupportShouldProcess attribute.
1 parent 96fa8d0 commit 31f09fd

File tree

2 files changed

+137
-72
lines changed

2 files changed

+137
-72
lines changed

Engine/Helper.cs

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,6 +1329,134 @@ public static string[] ProcessCustomRulePaths(string[] rulePaths, SessionState s
13291329

13301330
}
13311331

1332+
/// <summary>
1333+
/// Check if the function name starts with one of potentailly state changing verbs
1334+
/// </summary>
1335+
/// <param name="functionName"></param>
1336+
/// <returns>true if the function name starts with a state changing verb, otherwise false</returns>
1337+
public bool IsStateChangingFunctionName(string functionName)
1338+
{
1339+
if (functionName == null)
1340+
{
1341+
throw new ArgumentNullException("functionName");
1342+
}
1343+
// Array of verbs that can potentially change the state of a system
1344+
string[] stateChangingVerbs =
1345+
{
1346+
"Restart-",
1347+
"Stop-",
1348+
"New-",
1349+
"Set-",
1350+
"Update-",
1351+
"Reset-",
1352+
"Remove-"
1353+
};
1354+
foreach (var verb in stateChangingVerbs)
1355+
{
1356+
if (functionName.StartsWith(verb, StringComparison.OrdinalIgnoreCase))
1357+
{
1358+
return true;
1359+
}
1360+
}
1361+
return false;
1362+
}
1363+
1364+
/// <summary>
1365+
/// Get the SupportShouldProcess attribute ast
1366+
/// </summary>
1367+
/// <param name="attributeAsts"></param>
1368+
/// <returns>Returns SupportShouldProcess attribute ast if it exists, otherwise returns null</returns>
1369+
public NamedAttributeArgumentAst GetShouldProcessAttributeAst(IEnumerable<AttributeAst> attributeAsts)
1370+
{
1371+
if (attributeAsts == null)
1372+
{
1373+
throw new ArgumentNullException("attributeAsts");
1374+
}
1375+
var cmdletBindingAttributeAst = this.GetCmdletBindingAttributeAst(attributeAsts);
1376+
if (cmdletBindingAttributeAst == null
1377+
|| cmdletBindingAttributeAst.NamedArguments == null)
1378+
{
1379+
return null;
1380+
}
1381+
foreach (var namedAttributeAst in cmdletBindingAttributeAst.NamedArguments)
1382+
{
1383+
if (namedAttributeAst != null
1384+
&& namedAttributeAst.ArgumentName.Equals(
1385+
"SupportsShouldProcess",
1386+
StringComparison.OrdinalIgnoreCase))
1387+
{
1388+
return namedAttributeAst;
1389+
}
1390+
}
1391+
return null;
1392+
}
1393+
1394+
/// <summary>
1395+
/// Get the CmdletBinding attribute ast
1396+
/// </summary>
1397+
/// <param name="attributeAsts"></param>
1398+
/// <returns>Returns CmdletBinding attribute ast if it exists, otherwise returns null</returns>
1399+
public AttributeAst GetCmdletBindingAttributeAst(IEnumerable<AttributeAst> attributeAsts)
1400+
{
1401+
if (attributeAsts == null)
1402+
{
1403+
throw new ArgumentNullException("attributeAsts");
1404+
}
1405+
foreach (var attributeAst in attributeAsts)
1406+
{
1407+
if (attributeAst == null || attributeAst.NamedArguments == null)
1408+
{
1409+
continue;
1410+
}
1411+
if (attributeAst.TypeName.GetReflectionAttributeType()
1412+
== typeof(CmdletBindingAttribute))
1413+
{
1414+
return attributeAst;
1415+
}
1416+
}
1417+
return null;
1418+
}
1419+
1420+
/// <summary>
1421+
/// Get the boolean value of the named attribute argument
1422+
/// </summary>
1423+
/// <param name="namedAttributeArgumentAst"></param>
1424+
/// <returns>Boolean value of the named attribute argument</returns>
1425+
public bool GetNamedArgumentAttributeValue(NamedAttributeArgumentAst namedAttributeArgumentAst)
1426+
{
1427+
if (namedAttributeArgumentAst == null)
1428+
{
1429+
throw new ArgumentNullException("namedAttributeArgumentAst");
1430+
}
1431+
if (namedAttributeArgumentAst.ExpressionOmitted)
1432+
{
1433+
return true;
1434+
}
1435+
else
1436+
{
1437+
var varExpAst = namedAttributeArgumentAst.Argument as VariableExpressionAst;
1438+
if (varExpAst == null)
1439+
{
1440+
var constExpAst = namedAttributeArgumentAst.Argument as ConstantExpressionAst;
1441+
if (constExpAst == null)
1442+
{
1443+
return false;
1444+
}
1445+
bool constExpVal;
1446+
if (LanguagePrimitives.TryConvertTo<bool>(constExpAst.Value, out constExpVal))
1447+
{
1448+
return constExpVal;
1449+
}
1450+
}
1451+
else if (varExpAst.VariablePath.UserPath.Equals(
1452+
bool.TrueString,
1453+
StringComparison.OrdinalIgnoreCase))
1454+
{
1455+
return true;
1456+
}
1457+
}
1458+
return false;
1459+
}
13321460

13331461
#endregion
13341462
}

Rules/UseShouldProcessForStateChangingFunctions.cs

Lines changed: 9 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -75,88 +75,25 @@ private bool IsStateChangingFunctionWithNoShouldProcessAttribute(Ast ast)
7575
{
7676
return false;
7777
}
78-
string funcName = funcDefAst.Name;
79-
var targetFuncName = this.stateChangingVerbs.Where(
80-
elem => funcName.StartsWith(
81-
elem,
82-
StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
83-
if (targetFuncName == null
84-
|| funcDefAst.Body.ParamBlock == null
85-
|| funcDefAst.Body.ParamBlock.Attributes == null)
86-
{
87-
return false;
88-
}
89-
return !HasShouldProcessTrue(funcDefAst.Body.ParamBlock.Attributes);
78+
return Helper.Instance.IsStateChangingFunctionName(funcDefAst.Name)
79+
&& (funcDefAst.Body.ParamBlock == null
80+
|| funcDefAst.Body.ParamBlock.Attributes == null
81+
|| !HasShouldProcessTrue(funcDefAst.Body.ParamBlock.Attributes));
9082
}
91-
83+
9284
/// <summary>
9385
/// Checks if an attribute has SupportShouldProcess set to $true
9486
/// </summary>
9587
/// <param name="attributeAsts"></param>
9688
/// <returns>Returns true or false</returns>
9789
private bool HasShouldProcessTrue(IEnumerable<AttributeAst> attributeAsts)
9890
{
99-
foreach (var attributeAst in attributeAsts)
100-
{
101-
if (attributeAst == null || attributeAst.NamedArguments == null)
102-
{
103-
continue;
104-
}
105-
if (attributeAst.TypeName.GetReflectionAttributeType()
106-
== typeof(CmdletBindingAttribute))
107-
{
108-
foreach (var namedAttributeAst in attributeAst.NamedArguments)
109-
{
110-
if (namedAttributeAst == null
111-
|| !namedAttributeAst.ArgumentName.Equals(
112-
"SupportsShouldProcess",
113-
StringComparison.OrdinalIgnoreCase))
114-
{
115-
continue;
116-
}
117-
return IsShouldProcessTrue(namedAttributeAst);
118-
}
119-
}
120-
}
121-
// Cannot find any SupportShouldProcess attribute
122-
return false;
123-
}
124-
125-
/// <summary>
126-
/// Checks if the SupportShouldProcess attribute is true
127-
/// </summary>
128-
/// <param name="namedAttributeArgumentAst"></param>
129-
/// <returns>Returns true or false</returns>
130-
private bool IsShouldProcessTrue(NamedAttributeArgumentAst namedAttributeArgumentAst)
131-
{
132-
if (namedAttributeArgumentAst.ExpressionOmitted)
91+
var shouldProcessAttributeAst = Helper.Instance.GetShouldProcessAttributeAst(attributeAsts);
92+
if (shouldProcessAttributeAst == null)
13393
{
134-
return true;
135-
}
136-
else
137-
{
138-
var varExpAst = namedAttributeArgumentAst.Argument as VariableExpressionAst;
139-
if (varExpAst == null)
140-
{
141-
var constExpAst = namedAttributeArgumentAst.Argument as ConstantExpressionAst;
142-
if (constExpAst == null)
143-
{
144-
return false;
145-
}
146-
bool constExpVal;
147-
if (LanguagePrimitives.TryConvertTo<bool>(constExpAst.Value, out constExpVal))
148-
{
149-
return constExpVal;
150-
}
151-
}
152-
else if (varExpAst.VariablePath.UserPath.Equals(
153-
bool.TrueString,
154-
StringComparison.OrdinalIgnoreCase))
155-
{
156-
return true;
157-
}
94+
return false;
15895
}
159-
return false;
96+
return Helper.Instance.GetNamedArgumentAttributeValue(shouldProcessAttributeAst);
16097
}
16198

16299
/// <summary>

0 commit comments

Comments
 (0)