Skip to content

Commit 44574b5

Browse files
committed
Add new ProvideDefaultParameterValue rule.
Per @rkeithhill suggestion in #133
1 parent 9539455 commit 44574b5

File tree

4 files changed

+167
-1
lines changed

4 files changed

+167
-1
lines changed

Rules/ProvideDefaultParameterValue.cs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
//
2+
// Copyright (c) Microsoft Corporation.
3+
//
4+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
10+
// THE SOFTWARE.
11+
//
12+
13+
using System;
14+
using System.Linq;
15+
using System.Collections.Generic;
16+
using System.Management.Automation.Language;
17+
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
18+
using System.ComponentModel.Composition;
19+
using System.Globalization;
20+
21+
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
22+
{
23+
/// <summary>
24+
/// ProvideDefaultParameterValue: Check if any uninitialized variable is used.
25+
/// </summary>
26+
[Export(typeof(IScriptRule))]
27+
public class ProvideDefaultParameterValue : IScriptRule
28+
{
29+
/// <summary>
30+
/// AnalyzeScript: Check if any uninitialized variable is used.
31+
/// </summary>
32+
public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
33+
{
34+
if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage);
35+
36+
// Finds all functionAst
37+
IEnumerable<Ast> functionAsts = ast.FindAll(testAst => testAst is FunctionDefinitionAst, true);
38+
39+
foreach (FunctionDefinitionAst funcAst in functionAsts)
40+
{
41+
// Finds all ParamAsts.
42+
IEnumerable<Ast> varAsts = funcAst.FindAll(testAst => testAst is VariableExpressionAst, true);
43+
44+
// Iterrates all ParamAsts and check if their names are on the list.
45+
46+
HashSet<string> paramVariables = new HashSet<string>();
47+
// only raise the rules for variables in the param block.
48+
if (funcAst.Body != null && funcAst.Body.ParamBlock != null && funcAst.Body.ParamBlock.Parameters != null)
49+
{
50+
paramVariables.UnionWith(funcAst.Body.ParamBlock.Parameters.Select(paramAst => paramAst.Name.VariablePath.UserPath));
51+
}
52+
53+
// Iterates all VariableExpressionAst and check the command name.
54+
foreach (VariableExpressionAst varAst in varAsts)
55+
{
56+
if (Helper.Instance.IsUninitialized(varAst, funcAst) && paramVariables.Contains(varAst.VariablePath.UserPath))
57+
{
58+
yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.ProvideDefaultParameterValueError, varAst.VariablePath.UserPath),
59+
varAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName, varAst.VariablePath.UserPath);
60+
}
61+
}
62+
}
63+
}
64+
65+
/// <summary>
66+
/// GetName: Retrieves the name of this rule.
67+
/// </summary>
68+
/// <returns>The name of this rule</returns>
69+
public string GetName()
70+
{
71+
return string.Format(CultureInfo.CurrentCulture, Strings.NameSpaceFormat, GetSourceName(), Strings.ProvideDefaultParameterValueName);
72+
}
73+
74+
/// <summary>
75+
/// GetCommonName: Retrieves the common name of this rule.
76+
/// </summary>
77+
/// <returns>The common name of this rule</returns>
78+
public string GetCommonName()
79+
{
80+
return string.Format(CultureInfo.CurrentCulture, Strings.ProvideDefaultParameterValueCommonName);
81+
}
82+
83+
/// <summary>
84+
/// GetDescription: Retrieves the description of this rule.
85+
/// </summary>
86+
/// <returns>The description of this rule</returns>
87+
public string GetDescription()
88+
{
89+
return string.Format(CultureInfo.CurrentCulture, Strings.ProvideDefaultParameterValueDescription);
90+
}
91+
92+
/// <summary>
93+
/// Method: Retrieves the type of the rule: builtin, managed or module.
94+
/// </summary>
95+
public SourceType GetSourceType()
96+
{
97+
return SourceType.Builtin;
98+
}
99+
100+
/// <summary>
101+
/// GetSeverity: Retrieves the severity of the rule: error, warning of information.
102+
/// </summary>
103+
/// <returns></returns>
104+
public RuleSeverity GetSeverity()
105+
{
106+
return RuleSeverity.Warning;
107+
}
108+
109+
/// <summary>
110+
/// Method: Retrieves the module/assembly name the rule is from.
111+
/// </summary>
112+
public string GetSourceName()
113+
{
114+
return string.Format(CultureInfo.CurrentCulture, Strings.SourceName);
115+
}
116+
}
117+
}

Rules/ScriptAnalyzerBuiltinRules.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
<Compile Include="AvoidReservedParams.cs" />
6060
<Compile Include="AvoidShouldContinueWithoutForce.cs" />
6161
<Compile Include="AvoidTrapStatement.cs" />
62+
<Compile Include="ProvideDefaultParameterValue.cs" />
6263
<Compile Include="AvoidUninitializedVariable.cs" />
6364
<Compile Include="AvoidUsernameAndPasswordParams.cs" />
6465
<Compile Include="AvoidUsingComputerNameHardcoded.cs" />

Rules/Strings.Designer.cs

Lines changed: 37 additions & 1 deletion
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
@@ -714,4 +714,16 @@
714714
<data name="DscExamplesPresentNoExamplesError" xml:space="preserve">
715715
<value>No examples found for resource '{0}'</value>
716716
</data>
717+
<data name="ProvideDefaultParameterValueCommonName" xml:space="preserve">
718+
<value>Default Parameter Values</value>
719+
</data>
720+
<data name="ProvideDefaultParameterValueDescription" xml:space="preserve">
721+
<value>Parameters must have a default value. To fix a violation of this rule, please initialize non-global variables.</value>
722+
</data>
723+
<data name="ProvideDefaultParameterValueError" xml:space="preserve">
724+
<value>Parameter '{0}' is not initialized. Non-global variables must be initialized. To fix a violation of this rule, please initialize non-global variables.</value>
725+
</data>
726+
<data name="ProvideDefaultParameterValueName" xml:space="preserve">
727+
<value>ProvideDefaultParameterValue</value>
728+
</data>
717729
</root>

0 commit comments

Comments
 (0)