Skip to content

Commit c9010e7

Browse files
committed
Merge pull request #117 from PowerShell/development
Integrate Development to Master
2 parents 4402eae + 0bade57 commit c9010e7

16 files changed

+1008
-2
lines changed

Engine/Helper.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2085,6 +2085,11 @@ public object VisitConvertExpression(ConvertExpressionAst convAst)
20852085
{
20862086
if (convAst != null)
20872087
{
2088+
if (convAst.Type.TypeName.GetReflectionType() != null)
2089+
{
2090+
return convAst.Type.TypeName.GetReflectionType().FullName;
2091+
}
2092+
20882093
return convAst.Type.TypeName.FullName;
20892094
}
20902095

@@ -2135,6 +2140,11 @@ public object VisitTypeConstraint(TypeConstraintAst typeAst)
21352140
{
21362141
if (typeAst != null)
21372142
{
2143+
if (typeAst.TypeName.GetReflectionType() != null)
2144+
{
2145+
return typeAst.TypeName.GetReflectionType().FullName;
2146+
}
2147+
21382148
return typeAst.TypeName.FullName;
21392149
}
21402150

@@ -2160,6 +2170,11 @@ public object VisitTypeExpression(TypeExpressionAst typeExpressionAst)
21602170
{
21612171
if (typeExpressionAst != null)
21622172
{
2173+
if (typeExpressionAst.TypeName.GetReflectionType() != null)
2174+
{
2175+
return typeExpressionAst.TypeName.GetReflectionType().FullName;
2176+
}
2177+
21632178
return typeExpressionAst.TypeName.FullName;
21642179
}
21652180

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#DscExamplesPresent
2+
**Severity Level: Information**
3+
4+
5+
##Description
6+
7+
Checks that DSC examples for given resource are present.
8+
9+
##How to Fix
10+
11+
To fix a violation of this rule, please make sure Examples directory is present:
12+
* For non-class based resources it should exist at the same folder level as DSCResources folder.
13+
* For class based resources it should be present at the same folder level as resource psm1 file.
14+
15+
Examples folder should contain sample configuration for given resource - file name should contain resource's name.
16+
17+
##Example
18+
19+
### Non-class based resource
20+
21+
Let's assume we have non-class based resource with a following file structure:
22+
23+
* xAzure
24+
* DSCResources
25+
* MSFT_xAzureSubscription
26+
* MSFT_xAzureSubscription.psm1
27+
* MSFT_xAzureSubscription.schema.mof
28+
29+
In this case, to fix this warning, we should add examples in a following way:
30+
31+
* xAzure
32+
* DSCResources
33+
* MSFT_xAzureSubscription
34+
* MSFT_xAzureSubscription.psm1
35+
* MSFT_xAzureSubscription.schema.mof
36+
* Examples
37+
* MSFT_xAzureSubscription_AddSubscriptionExample.ps1
38+
* MSFT_xAzureSubscription_RemoveSubscriptionExample.ps1
39+
40+
### Class based resource
41+
42+
Let's assume we have class based resource with a following file structure:
43+
44+
* MyDscResource
45+
* MyDscResource.psm1
46+
* MyDscresource.psd1
47+
48+
In this case, to fix this warning, we should add examples in a following way:
49+
50+
* MyDscResource
51+
* MyDscResource.psm1
52+
* MyDscresource.psd1
53+
* Tests
54+
* MyDscResource_Example1.ps1
55+
* MyDscResource_Example2.ps1

RuleDocumentation/DscTestsPresent.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#DscTestsPresent
2+
**Severity Level: Information**
3+
4+
5+
##Description
6+
7+
Checks that DSC tests for given resource are present.
8+
9+
##How to Fix
10+
11+
To fix a violation of this rule, please make sure Tests directory is present:
12+
* For non-class based resources it should exist at the same folder level as DSCResources folder.
13+
* For class based resources it should be present at the same folder level as resource psm1 file.
14+
15+
Tests folder should contain test script for given resource - file name should contain resource's name.
16+
17+
##Example
18+
19+
### Non-class based resource
20+
21+
Let's assume we have non-class based resource with a following file structure:
22+
23+
* xAzure
24+
* DSCResources
25+
* MSFT_xAzureSubscription
26+
* MSFT_xAzureSubscription.psm1
27+
* MSFT_xAzureSubscription.schema.mof
28+
29+
In this case, to fix this warning, we should add tests in a following way:
30+
31+
* xAzure
32+
* DSCResources
33+
* MSFT_xAzureSubscription
34+
* MSFT_xAzureSubscription.psm1
35+
* MSFT_xAzureSubscription.schema.mof
36+
* Tests
37+
* MSFT_xAzureSubscription_Tests.ps1
38+
39+
### Class based resource
40+
41+
Let's assume we have class based resource with a following file structure:
42+
43+
* MyDscResource
44+
* MyDscResource.psm1
45+
* MyDscresource.psd1
46+
47+
In this case, to fix this warning, we should add tests in a following way:
48+
49+
* MyDscResource
50+
* MyDscResource.psm1
51+
* MyDscresource.psd1
52+
* Tests
53+
* MyDscResource_Tests.ps1
54+
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#UseOutputTypeCorrectly
2+
**Severity Level: Information**
3+
4+
5+
##Description
6+
7+
If a return type is declared, the cmdlet must return that type. If a type is returned, a return type must be declared.
8+
9+
##How to Fix
10+
11+
To fix a violation of this rule, please check the OuputType attribute lists and the types that are returned in your code. You can get more details by running “Get-Help about_Functions_OutputTypeAttribute” command in Windows PowerShell.
12+
13+
##Example
14+
15+
##Example
16+
Wrong:
17+
18+
function Get-Foo
19+
{
20+
[CmdletBinding()]
21+
[OutputType([String])]
22+
Param(
23+
)
24+
return "4
25+
}
26+
27+
Correct:
28+
29+
function Get-Foo
30+
{
31+
[CmdletBinding()]
32+
[OutputType([String])]
33+
Param(
34+
)
35+
36+
return "bar"
37+
}

Rules/DscExamplesPresent.cs

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
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.Collections.Generic;
15+
using System.Linq;
16+
using System.Management.Automation.Language;
17+
using Microsoft.Windows.Powershell.ScriptAnalyzer.Generic;
18+
using System.ComponentModel.Composition;
19+
using System.Globalization;
20+
using System.IO;
21+
using System.Management.Automation;
22+
23+
namespace Microsoft.Windows.Powershell.ScriptAnalyzer.BuiltinRules
24+
{
25+
/// <summary>
26+
/// DscExamplesPresent: Checks that DSC examples for given resource are present.
27+
/// Rule expects directory Examples to be present:
28+
/// For non-class based resources it should exist at the same folder level as DSCResources folder.
29+
/// For class based resources it should be present at the same folder level as resource psm1 file.
30+
/// Examples folder should contain sample configuration for given resource - file name should contain resource's name.
31+
/// </summary>
32+
[Export(typeof(IDSCResourceRule))]
33+
public class DscExamplesPresent : IDSCResourceRule
34+
{
35+
/// <summary>
36+
/// AnalyzeDSCResource: Analyzes given DSC Resource
37+
/// </summary>
38+
/// <param name="ast">The script's ast</param>
39+
/// <param name="fileName">The name of the script file being analyzed</param>
40+
/// <returns>The results of the analysis</returns>
41+
public IEnumerable<DiagnosticRecord> AnalyzeDSCResource(Ast ast, string fileName)
42+
{
43+
String fileNameOnly = Path.GetFileName(fileName);
44+
String resourceName = Path.GetFileNameWithoutExtension(fileNameOnly);
45+
String examplesQuery = String.Format("*{0}*", resourceName);
46+
Boolean examplesPresent = false;
47+
String expectedExamplesPath = Path.Combine(new String[] {fileName, "..", "..", "..", "Examples"});
48+
49+
// Verify examples are present
50+
if (Directory.Exists(expectedExamplesPath))
51+
{
52+
DirectoryInfo examplesFolder = new DirectoryInfo(expectedExamplesPath);
53+
FileInfo[] exampleFiles = examplesFolder.GetFiles(examplesQuery);
54+
if (exampleFiles.Length != 0)
55+
{
56+
examplesPresent = true;
57+
}
58+
}
59+
60+
// Return error if no examples present
61+
if (!examplesPresent)
62+
{
63+
yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.DscExamplesPresentNoExamplesError, resourceName),
64+
ast.Extent, GetName(), DiagnosticSeverity.Information, fileName);
65+
}
66+
}
67+
68+
/// <summary>
69+
/// AnalyzeDSCClass: Analyzes given DSC class
70+
/// </summary>
71+
/// <param name="ast"></param>
72+
/// <param name="fileName"></param>
73+
/// <returns></returns>
74+
public IEnumerable<DiagnosticRecord> AnalyzeDSCClass(Ast ast, string fileName)
75+
{
76+
String resourceName = null;
77+
78+
IEnumerable<Ast> dscClasses = ast.FindAll(item =>
79+
item is TypeDefinitionAst
80+
&& ((item as TypeDefinitionAst).IsClass)
81+
&& (item as TypeDefinitionAst).Attributes.Any(attr => String.Equals("DSCResource", attr.TypeName.FullName, StringComparison.OrdinalIgnoreCase)), true);
82+
83+
foreach (TypeDefinitionAst dscClass in dscClasses)
84+
{
85+
resourceName = dscClass.Name;
86+
87+
String examplesQuery = String.Format("*{0}*", resourceName);
88+
Boolean examplesPresent = false;
89+
String expectedExamplesPath = Path.Combine(new String[] {fileName, "..", "Examples"});
90+
91+
// Verify examples are present
92+
if (Directory.Exists(expectedExamplesPath))
93+
{
94+
DirectoryInfo examplesFolder = new DirectoryInfo(expectedExamplesPath);
95+
FileInfo[] exampleFiles = examplesFolder.GetFiles(examplesQuery);
96+
if (exampleFiles.Length != 0)
97+
{
98+
examplesPresent = true;
99+
}
100+
}
101+
102+
// Return error if no examples present
103+
if (!examplesPresent)
104+
{
105+
yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.DscExamplesPresentNoExamplesError, resourceName),
106+
dscClass.Extent, GetName(), DiagnosticSeverity.Information, fileName);
107+
}
108+
}
109+
}
110+
111+
/// <summary>
112+
/// GetName: Retrieves the name of this rule.
113+
/// </summary>
114+
/// <returns>The name of this rule</returns>
115+
public string GetName()
116+
{
117+
return string.Format(CultureInfo.CurrentCulture, Strings.NameSpaceFormat, GetSourceName(), Strings.DscExamplesPresent);
118+
}
119+
120+
/// <summary>
121+
/// GetCommonName: Retrieves the Common name of this rule.
122+
/// </summary>
123+
/// <returns>The common name of this rule</returns>
124+
public string GetCommonName()
125+
{
126+
return string.Format(CultureInfo.CurrentCulture, Strings.DscExamplesPresentCommonName);
127+
}
128+
129+
/// <summary>
130+
/// GetDescription: Retrieves the description of this rule.
131+
/// </summary>
132+
/// <returns>The description of this rule</returns>
133+
public string GetDescription()
134+
{
135+
return string.Format(CultureInfo.CurrentCulture, Strings.DscExamplesPresentDescription);
136+
}
137+
138+
/// <summary>
139+
/// GetSourceType: Retrieves the type of the rule: builtin, managed or module.
140+
/// </summary>
141+
public SourceType GetSourceType()
142+
{
143+
return SourceType.Builtin;
144+
}
145+
146+
/// <summary>
147+
/// GetSeverity: Retrieves the severity of the rule: error, warning or information.
148+
/// </summary>
149+
/// <returns></returns>
150+
public RuleSeverity GetSeverity()
151+
{
152+
return RuleSeverity.Information;
153+
}
154+
155+
/// <summary>
156+
/// GetSourceName: Retrieves the module/assembly name the rule is from.
157+
/// </summary>
158+
public string GetSourceName()
159+
{
160+
return string.Format(CultureInfo.CurrentCulture, Strings.DSCSourceName);
161+
}
162+
}
163+
164+
}

0 commit comments

Comments
 (0)