Skip to content

Commit 034780e

Browse files
committed
Fix the conflicts in Strings.Designer.cs
2 parents 849442c + cd4cc99 commit 034780e

File tree

4 files changed

+165
-2
lines changed

4 files changed

+165
-2
lines changed

Rules/ScriptAnalyzerBuiltinRules.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
33
<PropertyGroup>
44
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -83,6 +83,7 @@
8383
<Compile Include="UseIdenticalParametersDSC.cs" />
8484
<Compile Include="UsePSCredentialType.cs" />
8585
<Compile Include="UseShouldProcessCorrectly.cs" />
86+
<Compile Include="UseShouldProcessForStateChangingFunctions.cs" />
8687
<Compile Include="UseSingularNouns.cs" />
8788
<Compile Include="UseStandardDSCFunctionsInResource.cs" />
8889
<Compile Include="ReturnCorrectTypesForDSCFunctions.cs" />
@@ -108,4 +109,4 @@
108109
<PostBuildEvent>mkdir "$(SolutionDir)$(SolutionName)"
109110
copy /y "$(TargetPath)" "$(SolutionDir)$(SolutionName)"</PostBuildEvent>
110111
</PropertyGroup>
111-
</Project>
112+
</Project>

Rules/Strings.Designer.cs

Lines changed: 36 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Rules/Strings.resx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,4 +654,16 @@
654654
<data name="ReturnCorrectTypesForSetTargetResourceFunctionsDSCError" xml:space="preserve">
655655
<value>Set-TargetResource function in DSC Resource should not output anything to the pipeline.</value>
656656
</data>
657+
<data name="UseShouldProcessForStateChangingFunctionsCommonName" xml:space="preserve">
658+
<value>Use ShouldProcess For State Changing Functions</value>
659+
</data>
660+
<data name="UseShouldProcessForStateChangingFunctionsDescrption" xml:space="preserve">
661+
<value>Functions that have verbs like New, Start, Stop, Set, Reset that change systme state should support 'ShouldProcess'</value>
662+
</data>
663+
<data name="UseShouldProcessForStateChangingFunctionsError" xml:space="preserve">
664+
<value>Function ’{0}’ has verb that could change system state. Therefore, the function has to support 'ShouldProcess'</value>
665+
</data>
666+
<data name="UseShouldProcessForStateChangingFunctionsName" xml:space="preserve">
667+
<value>UseShouldProcessForStateChangingFunctions</value>
668+
</data>
657669
</root>
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Management.Automation;
5+
using System.Management.Automation.Language;
6+
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
7+
using System.ComponentModel.Composition;
8+
using System.Globalization;
9+
10+
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
11+
{/// <summary>
12+
/// UseShouldProcessCorrectly: Analyzes the ast to check that if the ShouldProcess attribute is present, the function calls ShouldProcess and vice versa.
13+
/// </summary>
14+
[Export(typeof(IScriptRule))]
15+
public class UseShouldProcessForStateChangingFunctions : IScriptRule
16+
{
17+
/// <summary>
18+
/// AnalyzeScript: Analyzes the ast to check if ShouldProcess is included in Advanced functions if the Verb of the function could change system state.
19+
/// </summary>
20+
/// <param name="ast">The script's ast</param>
21+
/// <param name="fileName">The script's file name</param>
22+
/// <returns>A List of diagnostic results of this rule</returns>
23+
public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
24+
{
25+
if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage);
26+
27+
IEnumerable<Ast> funcDefAsts = ast.FindAll(testAst => testAst is FunctionDefinitionAst, true);
28+
string supportsShouldProcess = "SupportsShouldProcess";
29+
string trueString = "$true";
30+
foreach (FunctionDefinitionAst funcDefAst in funcDefAsts)
31+
{
32+
string funcName = funcDefAst.Name;
33+
bool hasShouldProcessAttribute = false;
34+
35+
if (funcName.IndexOf("Get", StringComparison.OrdinalIgnoreCase) >= 0 ||
36+
funcName.IndexOf("Stop", StringComparison.OrdinalIgnoreCase) >= 0 ||
37+
funcName.IndexOf("New", StringComparison.OrdinalIgnoreCase) >= 0 ||
38+
funcName.IndexOf("Set", StringComparison.OrdinalIgnoreCase) >= 0 ||
39+
funcName.IndexOf("Update", StringComparison.OrdinalIgnoreCase) >= 0 ||
40+
funcName.IndexOf("Reset", StringComparison.OrdinalIgnoreCase) >= 0)
41+
{
42+
IEnumerable<Ast> attributeAsts = funcDefAst.FindAll(testAst => testAst is NamedAttributeArgumentAst, true);
43+
if (funcDefAst.Body != null && funcDefAst.Body.ParamBlock != null
44+
&& funcDefAst.Body.ParamBlock.Attributes != null &&
45+
funcDefAst.Body.ParamBlock.Parameters != null)
46+
{
47+
if (!funcDefAst.Body.ParamBlock.Attributes.Any(attr => attr.TypeName.GetReflectionType() == typeof (CmdletBindingAttribute)))
48+
{
49+
continue;
50+
}
51+
52+
foreach (NamedAttributeArgumentAst attributeAst in attributeAsts)
53+
{
54+
if (attributeAst.ArgumentName.Equals(supportsShouldProcess, StringComparison.OrdinalIgnoreCase) && attributeAst.Argument.Extent.Text.Equals(trueString, StringComparison.OrdinalIgnoreCase))
55+
{
56+
hasShouldProcessAttribute = true;
57+
}
58+
}
59+
60+
if (!hasShouldProcessAttribute)
61+
{
62+
yield return
63+
new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture,Strings.UseShouldProcessForStateChangingFunctionsError, funcName),funcDefAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName);
64+
}
65+
}
66+
}
67+
}
68+
}
69+
70+
/// <summary>
71+
/// GetName: Retrieves the name of this rule.
72+
/// </summary>
73+
/// <returns>The name of this rule</returns>
74+
public string GetName()
75+
{
76+
return string.Format(CultureInfo.CurrentCulture, Strings.NameSpaceFormat, GetSourceName(), Strings.UseShouldProcessForStateChangingFunctionsName);
77+
}
78+
79+
/// <summary>
80+
/// GetCommonName: Retrieves the Common name of this rule.
81+
/// </summary>
82+
/// <returns>The common name of this rule</returns>
83+
public string GetCommonName()
84+
{
85+
return string.Format(CultureInfo.CurrentCulture, Strings.UseShouldProcessForStateChangingFunctionsCommonName);
86+
}
87+
88+
/// <summary>
89+
/// GetDescription: Retrieves the description of this rule.
90+
/// </summary>
91+
/// <returns>The description of this rule</returns>
92+
public string GetDescription()
93+
{
94+
return string.Format(CultureInfo.CurrentCulture, Strings.UseShouldProcessForStateChangingFunctionsDescrption);
95+
}
96+
97+
/// <summary>
98+
/// GetSourceType: Retrieves the type of the rule: builtin, managed or module.
99+
/// </summary>
100+
public SourceType GetSourceType()
101+
{
102+
return SourceType.Builtin;
103+
}
104+
105+
/// <summary>
106+
/// GetSourceName: Retrieves the module/assembly name the rule is from.
107+
/// </summary>
108+
public string GetSourceName()
109+
{
110+
return string.Format(CultureInfo.CurrentCulture, Strings.SourceName);
111+
}
112+
}
113+
114+
}

0 commit comments

Comments
 (0)