Skip to content

Commit 99956f2

Browse files
author
quoctruong
committed
Merge pull request #21 from PowerShell/removeicommandrule
Remove ICommandRule
2 parents a2fff13 + 9c868d3 commit 99956f2

8 files changed

+71
-143
lines changed

Engine/Commands/InvokeScriptAnalyzerCommand.cs

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,6 @@ protected override void BeginProcessing()
170170
#region Verify rules
171171

172172
rules = ScriptAnalyzer.Instance.ScriptRules.Union<IRule>(
173-
ScriptAnalyzer.Instance.CommandRules).Union<IRule>(
174173
ScriptAnalyzer.Instance.TokenRules).Union<IRule>(
175174
ScriptAnalyzer.Instance.ExternalRules ?? Enumerable.Empty<IExternalRule>());
176175

@@ -333,68 +332,6 @@ private void AnalyzeFile(string filePath)
333332

334333
#endregion
335334

336-
#region Run Command Rules
337-
338-
funcDefAsts = ast.FindAll(new Func<Ast, bool>((testAst) => (testAst is FunctionDefinitionAst)), true);
339-
if (funcDefAsts != null)
340-
{
341-
foreach (FunctionDefinitionAst funcDefAst in funcDefAsts)
342-
{
343-
//Create command info object here
344-
var sb = new StringBuilder();
345-
sb.AppendLine(funcDefAst.Extent.Text);
346-
sb.AppendFormat("Get-Command –CommandType Function –Name {0}", funcDefAst.Name);
347-
348-
var funcDefPS = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace);
349-
funcDefPS.AddScript(sb.ToString());
350-
351-
try
352-
{
353-
var commandInfo = funcDefPS.Invoke<CommandInfo>();
354-
355-
foreach (CommandInfo cmdInfo in commandInfo)
356-
{
357-
cmdInfoTable.Add(new KeyValuePair<CommandInfo, IScriptExtent>(cmdInfo as CommandInfo, funcDefAst.Extent));
358-
}
359-
}
360-
catch (ParseException)
361-
{
362-
WriteError(new ErrorRecord(new CommandNotFoundException(),
363-
string.Format(CultureInfo.CurrentCulture, Strings.CommandInfoNotFound, funcDefAst.Name),
364-
ErrorCategory.SyntaxError, funcDefAst));
365-
}
366-
}
367-
}
368-
369-
if (ScriptAnalyzer.Instance.CommandRules != null)
370-
{
371-
foreach (ICommandRule commandRule in ScriptAnalyzer.Instance.CommandRules)
372-
{
373-
if ((includeRule == null || includeRule.Contains(commandRule.GetName(), StringComparer.OrdinalIgnoreCase)) &&
374-
(excludeRule == null || !excludeRule.Contains(commandRule.GetName(), StringComparer.OrdinalIgnoreCase)))
375-
{
376-
foreach (KeyValuePair<CommandInfo, IScriptExtent> commandInfo in cmdInfoTable)
377-
{
378-
WriteVerbose(string.Format(CultureInfo.CurrentCulture, Strings.VerboseRunningMessage, commandRule.GetName()));
379-
380-
// Ensure that any unhandled errors from Rules are converted to non-terminating errors
381-
// We want the Engine to continue functioning even if one or more Rules throws an exception
382-
try
383-
{
384-
diagnostics.AddRange(commandRule.AnalyzeCommand(commandInfo.Key, commandInfo.Value, fileName));
385-
}
386-
catch (Exception commandRuleException)
387-
{
388-
WriteError(new ErrorRecord(commandRuleException, Strings.RuleErrorMessage, ErrorCategory.InvalidOperation, fileName));
389-
continue;
390-
}
391-
}
392-
}
393-
}
394-
}
395-
396-
#endregion
397-
398335
#region Run Token Rules
399336

400337
if (ScriptAnalyzer.Instance.TokenRules != null)

Engine/Generic/ICommandRule.cs

Lines changed: 0 additions & 25 deletions
This file was deleted.

Engine/ScriptAnalyzer.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,6 @@ public static ScriptAnalyzer Instance
5555
[ImportMany]
5656
public IEnumerable<IScriptRule> ScriptRules { get; private set; }
5757

58-
[ImportMany]
59-
public IEnumerable<ICommandRule> CommandRules { get; private set; }
60-
6158
[ImportMany]
6259
public IEnumerable<ITokenRule> TokenRules { get; private set; }
6360

@@ -168,8 +165,7 @@ public IEnumerable<IRule> GetRule(string[] moduleNames, string[] ruleNames)
168165
IEnumerable<IExternalRule> externalRules = null;
169166

170167
// Combines C# rules.
171-
IEnumerable<IRule> rules = ScriptRules.Union<IRule>(CommandRules)
172-
.Union<IRule>(TokenRules)
168+
IEnumerable<IRule> rules = ScriptRules.Union<IRule>(TokenRules)
173169
.Union<IRule>(DSCResourceRules);
174170

175171
// Gets PowerShell Rules.

Engine/ScriptAnalyzerEngine.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
<Compile Include="Generic\AvoidParameterGeneric.cs" />
5555
<Compile Include="Generic\DiagnosticRecord.cs" />
5656
<Compile Include="Generic\ExternalRule.cs" />
57-
<Compile Include="Generic\ICommandRule.cs" />
5857
<Compile Include="Generic\IDSCResourceRule.cs" />
5958
<Compile Include="Generic\IExternalRule.cs" />
6059
<Compile Include="Generic\ILogger.cs" />

Rules/AvoidReservedCharInCmdlet.cs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,33 @@ namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
1717
{
1818

1919
/// <summary>
20-
/// AvoidReservedCharInCmdlet: Analyzes CommandInfos to check for reserved characters in cmdlet names.
20+
/// AvoidReservedCharInCmdlet: Analyzes script to check for reserved characters in cmdlet names.
2121
/// </summary>
22-
[Export(typeof(ICommandRule))]
23-
public class AvoidReservedCharInCmdlet : ICommandRule
22+
[Export(typeof(IScriptRule))]
23+
public class AvoidReservedCharInCmdlet : IScriptRule
2424
{
2525
/// <summary>
26-
/// AnalyzeCommand: Analyzes command infos to check for reserved characters in cmdlet names.
26+
/// Analyze ast to check that all the cmdlet does not use reserved char
2727
/// </summary>
28-
/// <param name="commandInfo">The current command info from the script</param>
29-
/// <param name="extent">The current position in the script</param>
30-
/// <param name="fileName">The script's file name</param>
31-
/// <returns>A List of diagnostic results of this rule</returns>
32-
public IEnumerable<DiagnosticRecord> AnalyzeCommand(CommandInfo commandInfo, IScriptExtent extent, string fileName) {
33-
if (commandInfo == null) throw new ArgumentNullException(Strings.NullAstErrorMessage);
28+
/// <param name="ast"></param>
29+
/// <param name="fileName"></param>
30+
/// <returns></returns>
31+
public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
32+
{
33+
if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage);
34+
35+
IEnumerable<Ast> funcAsts = ast.FindAll(item => item is FunctionDefinitionAst, true);
3436

35-
string funcName = commandInfo.Name;
36-
string reservedChars = Strings.ReserverCmdletChars; //Localize yes or no?
37+
string reservedChars = Strings.ReserverCmdletChars;
3738

38-
if (funcName.Intersect(reservedChars).Count() > 0) {
39-
yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.ReservedCmdletCharError, funcName), extent, GetName(), DiagnosticSeverity.Warning, fileName);
40-
}
39+
foreach (FunctionDefinitionAst funcAst in funcAsts)
40+
{
41+
if (funcAst.Name != null && funcAst.Name.Intersect(reservedChars).Count() > 0)
42+
{
43+
yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.ReservedCmdletCharError, funcAst.Name),
44+
funcAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName);
45+
}
46+
}
4147
}
4248

4349
/// <summary>

Rules/UseApprovedVerbs.cs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,18 @@
1616
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
1717
{
1818
/// <summary>
19-
/// UseApprovedVerbs: Analyzes CommandInfos to check that all defined cmdlets use approved verbs.
19+
/// UseApprovedVerbs: Analyzes scripts to check that all defined functions use approved verbs.
2020
/// </summary>
21-
[Export(typeof(ICommandRule))]
22-
public class UseApprovedVerbs : ICommandRule {
21+
[Export(typeof(IScriptRule))]
22+
public class UseApprovedVerbs : IScriptRule {
2323
/// <summary>
24-
/// AnalyzeCommand: Analyzes command infos to check that all defined cmdlets use approved verbs.
24+
/// Analyze script to check that all defined functions use approved verbs
2525
/// </summary>
26-
/// <param name="commandInfo">The current command info from the script</param>
27-
/// <param name="extent">The current position in the script</param>
28-
/// <param name="fileName">The name of the script</param>
29-
/// <returns>A List of diagnostic results of this rule</returns>
30-
public IEnumerable<DiagnosticRecord> AnalyzeCommand(CommandInfo commandInfo, IScriptExtent extent, string fileName) {
31-
if (commandInfo == null) throw new ArgumentNullException(Strings.NullCommandInfoError);
26+
/// <param name="ast"></param>
27+
/// <param name="fileName"></param>
28+
/// <returns></returns>
29+
public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName) {
30+
if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage);
3231

3332
List<string> approvedVerbs = typeof(VerbsCommon).GetFields().Concat<FieldInfo>(
3433
typeof(VerbsCommunications).GetFields()).Concat<FieldInfo>(
@@ -44,14 +43,22 @@ public IEnumerable<DiagnosticRecord> AnalyzeCommand(CommandInfo commandInfo, ISc
4443
string[] funcNamePieces = new string[2];
4544
string verb;
4645

47-
funcName = commandInfo.Name;
46+
IEnumerable<Ast> funcAsts = ast.FindAll(item => item is FunctionDefinitionAst, true);
4847

49-
if (funcName != null && funcName.Contains('-')) {
50-
funcNamePieces = funcName.Split(funcSeperator);
51-
verb = funcNamePieces[0];
48+
foreach (FunctionDefinitionAst funcAst in funcAsts)
49+
{
50+
funcName = funcAst.Name;
5251

53-
if (!approvedVerbs.Contains(verb, StringComparer.OrdinalIgnoreCase)) {
54-
yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.UseApprovedVerbsError, funcName), extent, GetName(), DiagnosticSeverity.Warning, fileName);
52+
if (funcName != null && funcName.Contains('-'))
53+
{
54+
funcNamePieces = funcName.Split(funcSeperator);
55+
verb = funcNamePieces[0];
56+
57+
if (!approvedVerbs.Contains(verb, StringComparer.OrdinalIgnoreCase))
58+
{
59+
yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.UseApprovedVerbsError, funcName),
60+
funcAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName);
61+
}
5562
}
5663
}
5764
}

Rules/UseSingularNouns.cs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,41 @@
1616
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
1717
{
1818
/// <summary>
19-
/// CmdletSingularNoun: Analyzes CommandInfos to check that all defined cmdlets use singular nouns.
19+
/// CmdletSingularNoun: Analyzes scripts to check that all defined cmdlets use singular nouns.
2020
///
2121
/// </summary>
22-
[Export(typeof(ICommandRule))]
23-
public class CmdletSingularNoun : ICommandRule {
22+
[Export(typeof(IScriptRule))]
23+
public class CmdletSingularNoun : IScriptRule {
2424
/// <summary>
25-
/// AnalyzeCommand: Analyzes command infos to check that all defined cmdlets use singular nouns.
25+
/// Checks that all defined cmdlet use singular noun
2626
/// </summary>
27-
/// <param name="commandInfo">The current command info from the script</param>
28-
/// <param name="extent">The current position in the script</param>
29-
/// <param name="fileName">The name of the script</param>
30-
/// <returns>A List of diagnostic results of this rule</returns>
31-
public IEnumerable<DiagnosticRecord> AnalyzeCommand(CommandInfo commandInfo, IScriptExtent extent, string fileName) {
32-
if (commandInfo == null) throw new ArgumentNullException(Strings.NullCommandInfoError);
27+
/// <param name="ast"></param>
28+
/// <param name="fileName"></param>
29+
/// <returns></returns>
30+
public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName) {
31+
if (ast == null) throw new ArgumentNullException(Strings.NullCommandInfoError);
32+
33+
IEnumerable<Ast> funcAsts = ast.FindAll(item => item is FunctionDefinitionAst, true);
3334

3435
char[] funcSeperator = { '-' };
3536
string[] funcNamePieces = new string[2];
3637

37-
if (commandInfo.Name != null && commandInfo.Name.Contains('-')) {
38-
funcNamePieces = commandInfo.Name.Split(funcSeperator);
39-
String noun = funcNamePieces[1];
40-
var ps = System.Data.Entity.Design.PluralizationServices.PluralizationService.CreateService(CultureInfo.GetCultureInfo("en-us"));
38+
foreach (FunctionDefinitionAst funcAst in funcAsts)
39+
{
40+
if (funcAst.Name != null && funcAst.Name.Contains('-'))
41+
{
42+
funcNamePieces = funcAst.Name.Split(funcSeperator);
43+
String noun = funcNamePieces[1];
44+
var ps = System.Data.Entity.Design.PluralizationServices.PluralizationService.CreateService(CultureInfo.GetCultureInfo("en-us"));
4145

42-
if (ps.IsPlural(noun)) {
43-
yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.UseSingularNounsError, commandInfo.Name), extent, GetName(), DiagnosticSeverity.Warning, fileName);
46+
if (ps.IsPlural(noun))
47+
{
48+
yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.UseSingularNounsError, funcAst.Name),
49+
funcAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName);
50+
}
4451
}
4552
}
53+
4654
}
4755

4856
/// <summary>

Tests/Rules/UseSingularNounsReservedVerbs.tests.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Import-Module ScriptAnalyzer
2-
$nounViolationMessage = "The cmdlet Verb-Files uses a plural noun. A singular noun should be used instead."
3-
$verbViolationMessage = "The cmdlet Verb-Files uses an unapproved verb."
2+
$nounViolationMessage = "The cmdlet 'Verb-Files' uses a plural noun. A singular noun should be used instead."
3+
$verbViolationMessage = "The cmdlet 'Verb-Files' uses an unapproved verb."
44
$nounViolationName = "PSUseSingularNouns"
55
$verbViolationName = "PSUseApprovedVerbs"
66
$directory = Split-Path -Parent $MyInvocation.MyCommand.Path

0 commit comments

Comments
 (0)