2
2
using System . Linq ;
3
3
using System . Management . Automation . Language ;
4
4
using System . Collections . Generic ;
5
+ using System . Text . RegularExpressions ;
6
+ using System . Globalization ;
5
7
6
8
namespace Microsoft . Windows . Powershell . ScriptAnalyzer . Generic
7
9
{
@@ -10,6 +12,8 @@ namespace Microsoft.Windows.Powershell.ScriptAnalyzer.Generic
10
12
/// </summary>
11
13
public class RuleSuppression
12
14
{
15
+ private string _ruleName ;
16
+
13
17
/// <summary>
14
18
/// The start offset of the rule suppression
15
19
/// </summary>
@@ -33,8 +37,24 @@ public int EndOffset
33
37
/// </summary>
34
38
public string RuleName
35
39
{
36
- get ;
37
- set ;
40
+ get
41
+ {
42
+ return _ruleName ;
43
+ }
44
+
45
+ set
46
+ {
47
+ _ruleName = value ;
48
+ if ( ( ScriptAnalyzer . Instance . ScriptRules != null
49
+ && ScriptAnalyzer . Instance . ScriptRules . Count ( item => String . Equals ( item . GetName ( ) , _ruleName , StringComparison . OrdinalIgnoreCase ) ) == 0 )
50
+ && ( ScriptAnalyzer . Instance . TokenRules != null
51
+ && ScriptAnalyzer . Instance . TokenRules . Count ( item => String . Equals ( item . GetName ( ) , _ruleName , StringComparison . OrdinalIgnoreCase ) ) == 0 )
52
+ && ( ScriptAnalyzer . Instance . ExternalRules != null
53
+ && ScriptAnalyzer . Instance . ExternalRules . Count ( item => String . Equals ( item . GetName ( ) , _ruleName , StringComparison . OrdinalIgnoreCase ) ) == 0 ) )
54
+ {
55
+ Error = String . Format ( Strings . RuleSuppressionRuleNameNotFound , _ruleName ) ;
56
+ }
57
+ }
38
58
}
39
59
40
60
/// <summary>
@@ -46,6 +66,24 @@ public string RuleSuppressionID
46
66
set ;
47
67
}
48
68
69
+ /// <summary>
70
+ /// Scope of the rule suppression
71
+ /// </summary>
72
+ public string Scope
73
+ {
74
+ get ;
75
+ set ;
76
+ }
77
+
78
+ /// <summary>
79
+ /// Target of the rule suppression
80
+ /// </summary>
81
+ public string Target
82
+ {
83
+ get ;
84
+ set ;
85
+ }
86
+
49
87
/// <summary>
50
88
/// Returns error occurred in trying to parse the attribute
51
89
/// </summary>
@@ -55,6 +93,18 @@ public string Error
55
93
set ;
56
94
}
57
95
96
+ private static HashSet < string > scopeSet ;
97
+
98
+ /// <summary>
99
+ /// Initialize the scopeSet
100
+ /// </summary>
101
+ static RuleSuppression ( )
102
+ {
103
+ scopeSet = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) ;
104
+ scopeSet . Add ( "function" ) ;
105
+ scopeSet . Add ( "class" ) ;
106
+ }
107
+
58
108
/// <summary>
59
109
/// Returns rule suppression from an attribute ast that has the type suppressmessageattribute
60
110
/// </summary>
@@ -85,6 +135,14 @@ public RuleSuppression(AttributeAst attrAst, int start, int end)
85
135
{
86
136
switch ( count )
87
137
{
138
+ case 4 :
139
+ Target = ( positionalArguments [ 3 ] as StringConstantExpressionAst ) . Value ;
140
+ goto case 3 ;
141
+
142
+ case 3 :
143
+ Scope = ( positionalArguments [ 2 ] as StringConstantExpressionAst ) . Value ;
144
+ goto case 2 ;
145
+
88
146
case 2 :
89
147
RuleSuppressionID = ( positionalArguments [ 1 ] as StringConstantExpressionAst ) . Value ;
90
148
goto case 1 ;
@@ -134,13 +192,64 @@ public RuleSuppression(AttributeAst attrAst, int start, int end)
134
192
RuleSuppressionID = ( name . Argument as StringConstantExpressionAst ) . Value ;
135
193
goto default ;
136
194
195
+ case "scope" :
196
+ if ( ! String . IsNullOrWhiteSpace ( Scope ) )
197
+ {
198
+ Error = String . Format ( Strings . NamedAndPositionalArgumentsConflictError , name ) ;
199
+ }
200
+
201
+ Scope = ( name . Argument as StringConstantExpressionAst ) . Value ;
202
+
203
+ if ( ! scopeSet . Contains ( Scope ) )
204
+ {
205
+ Error = Strings . WrongScopeArgumentSuppressionAttributeError ;
206
+ }
207
+
208
+ goto default ;
209
+
210
+ case "target" :
211
+ if ( ! String . IsNullOrWhiteSpace ( Target ) )
212
+ {
213
+ Error = String . Format ( Strings . NamedAndPositionalArgumentsConflictError , name ) ;
214
+ }
215
+
216
+ Target = ( name . Argument as StringConstantExpressionAst ) . Value ;
217
+ goto default ;
218
+
137
219
default :
138
220
break ;
139
221
}
140
222
}
141
223
}
224
+
225
+ // Must have scope and target together
226
+ if ( String . IsNullOrWhiteSpace ( Scope ) && ! String . IsNullOrWhiteSpace ( Target ) )
227
+ {
228
+ Error = Strings . TargetWithoutScopeSuppressionAttributeError ;
229
+ }
230
+ }
231
+
232
+ StartOffset = start ;
233
+ EndOffset = end ;
234
+
235
+ if ( ! String . IsNullOrWhiteSpace ( Error ) )
236
+ {
237
+ Error = String . Format ( CultureInfo . CurrentCulture , Strings . RuleSuppressionErrorFormat , attrAst . Extent . StartLineNumber ,
238
+ System . IO . Path . GetFileName ( attrAst . Extent . File ) , Error ) ;
142
239
}
240
+ }
143
241
242
+ /// <summary>
243
+ /// Constructs rule expression from rule name, id, start and end
244
+ /// </summary>
245
+ /// <param name="ruleName"></param>
246
+ /// <param name="ruleSuppressionID"></param>
247
+ /// <param name="start"></param>
248
+ /// <param name="end"></param>
249
+ public RuleSuppression ( string ruleName , string ruleSuppressionID , int start , int end )
250
+ {
251
+ RuleName = ruleName ;
252
+ RuleSuppressionID = ruleSuppressionID ;
144
253
StartOffset = start ;
145
254
EndOffset = end ;
146
255
}
@@ -153,11 +262,11 @@ public RuleSuppression(AttributeAst attrAst, int start, int end)
153
262
/// <param name="start"></param>
154
263
/// <param name="end"></param>
155
264
/// <returns></returns>
156
- public static List < RuleSuppression > GetSuppressions ( IEnumerable < AttributeAst > attrAsts , int start , int end )
265
+ public static List < RuleSuppression > GetSuppressions ( IEnumerable < AttributeAst > attrAsts , int start , int end , Ast scopeAst )
157
266
{
158
267
List < RuleSuppression > result = new List < RuleSuppression > ( ) ;
159
268
160
- if ( attrAsts == null )
269
+ if ( attrAsts == null || scopeAst == null )
161
270
{
162
271
return result ;
163
272
}
@@ -169,8 +278,44 @@ public static List<RuleSuppression> GetSuppressions(IEnumerable<AttributeAst> at
169
278
{
170
279
RuleSuppression ruleSupp = new RuleSuppression ( attributeAst , start , end ) ;
171
280
172
- if ( string . IsNullOrWhiteSpace ( ruleSupp . Error ) )
281
+ // If there is no error and scope is not null
282
+ if ( String . IsNullOrWhiteSpace ( ruleSupp . Error ) && ! String . IsNullOrWhiteSpace ( ruleSupp . Scope ) )
283
+ {
284
+ if ( String . IsNullOrWhiteSpace ( ruleSupp . Target ) )
285
+ {
286
+ ruleSupp . Target = "*" ;
287
+ }
288
+
289
+ // regex for wild card *
290
+ Regex reg = new Regex ( String . Format ( "^{0}$" , Regex . Escape ( ruleSupp . Target ) . Replace ( @"\*" , ".*" ) ) ) ;
291
+ IEnumerable < Ast > targetAsts = null ;
292
+
293
+ switch ( ruleSupp . Scope . ToLower ( ) )
294
+ {
295
+ case "function" :
296
+ targetAsts = scopeAst . FindAll ( item => item is FunctionDefinitionAst && reg . IsMatch ( ( item as FunctionDefinitionAst ) . Name ) , true ) ;
297
+ goto default ;
298
+
299
+ case "class" :
300
+ targetAsts = scopeAst . FindAll ( item => item is TypeDefinitionAst && reg . IsMatch ( ( item as TypeDefinitionAst ) . Name ) , true ) ;
301
+ goto default ;
302
+
303
+ default :
304
+ break ;
305
+ }
306
+
307
+ if ( targetAsts != null )
308
+ {
309
+ foreach ( Ast targetAst in targetAsts )
310
+ {
311
+ result . Add ( new RuleSuppression ( ruleSupp . RuleName , ruleSupp . RuleSuppressionID , targetAst . Extent . StartOffset , targetAst . Extent . EndOffset ) ) ;
312
+ }
313
+ }
314
+
315
+ }
316
+ else
173
317
{
318
+ // this may add rule suppression that contains erro but we will check for this in the engine to throw out error
174
319
result . Add ( ruleSupp ) ;
175
320
}
176
321
}
0 commit comments