@@ -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