Skip to content

Commit 2b6e64b

Browse files
author
Kapil Borle
committed
Merge pull request #558 from PowerShell/development
Take development to master for version 1.6.0 release
2 parents 0c53ffd + f6b918d commit 2b6e64b

File tree

64 files changed

+2884
-885
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+2884
-885
lines changed

CHANGELOG.MD

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,44 @@
1+
## Release v1.6.0
2+
3+
### Engine
4+
- Add `SuggestedCorrections` property to `DiagnosticRecord`
5+
- This property emits text that can rectify the violation which triggered the rule.
6+
- The primary purpose of this feature is to enable quick-fix scenarios in editors (e.g. vscode)
7+
- Add "Name" as a positional parameter in Get-ScriptAnalyzerRule
8+
- Add a `SaveDscDependency` switch to allow `Invoke-ScriptAnalyzer` to download a DSC Resource module from PSGallery in the event of a `ModuleNotFoundDuringParse` parse error. This feature is available only for PSv5 and above.
9+
- Add `remove` verb to `UseShouldProcessForStateChangingFunctions` rule
10+
- Add a `ScriptPath` property to Diagnostic Record that returns the full path of the script
11+
- Add PSv4 (Windows Server 2012 R2) and PSv3 (Windows Server 2012) to build and test matrix on AppVeyor
12+
- Fix the parsing of `Settings` parameter value when a hashtable is given
13+
- Fix writing error record while running rule suppression
14+
- Fix rule suppression in DSC Configuration definitions
15+
- Fix build and tests on PSv4 and v3
16+
17+
### Rules
18+
- Add suggested corrections feature to the following rules.
19+
- `PSAvoidUsingCmdletAliases`
20+
- `PSAvoidUsingPlainTextForPassword`
21+
- `PSMisleadingBacktick`
22+
- `PSUseToExportFieldsInManifest`
23+
- `PSMissingModuleManifestField`
24+
- Fix extent of
25+
- `PSUseSingularNoun`
26+
- `PSUseApprovedVerb`
27+
- `PSAvoidUsernameAndPasswordParams`
28+
- Fix a bug in `PSMissingModuleManifestField` rule caused by .psd1 files that do not contain Hashtable
29+
- Fix documentation of `PSAvoidUsingPlainTextForPassword`
30+
131
## Release v1.5.0 (Mar. 30, 2016)
232

3-
#### Engine
33+
### Engine
434
- Fixed an engine bug that prevented versioned script rule modules from being loaded
535
- Fixed loading issues with custom rules that do not have comment-based help to describe the rule
636
- Fixed a hang issue that appeared when using ScriptAnalyzer engine recursively with a large data set
737
- Housekeeping: Fixed Appveyor config to use VS 2015 and WMF 5.0 RTM image
838
- Community Fix: Updated the Initialize API to process the `-Settings` (formerly `-Profile`) parameter
939
- Perf: Improved rule filtering based on severity before invoking the engine to create tasks (threads)
1040

11-
#### Rules
41+
### Rules
1242
- Fixed `UseToExportFieldsInManifest` rule to improve perf and functionality
1343
- Fixed `AvoidNullOrEmptyHelpMessageAttribute` to use parsed values instead of ast extent
1444
- Fixed inconsistencies in severities of rules
@@ -81,7 +111,7 @@
81111
- Deprecate Internal Url rule based on community feedback, identified additional rules to handle hardcoded paths etc
82112
- Added localhost exceptions for HardCodedComputerName Rule
83113
- Update to Credential based rules to validate the presence of CredentialAttribute and PSCredential type
84-
114+
85115
###Documentation:
86116
- Rule & Cmdlet documentation updates – Cmdlet help file addition
87117

@@ -174,9 +204,9 @@
174204

175205
##Released v1.0.0 on Apr.24, 2015
176206
###Features:
177-
- Finalized three levels of Severity - Error/Warning/Information.
207+
- Finalized three levels of Severity - Error/Warning/Information.
178208
- Improved PSScriptAnalyzer engine behavior: emits non-terminating errors (Ex: for failed ast parse) and continues rule application when running on multiple scripts.
179-
- Added wild card supports for rules in Invoke-ScriptAnalyzer and Get-ScriptAnalyzer. Eg. Invoke-ScriptAnalyzer -IncludeRule PSAvoid* will apply all rules starting with PSAvoid* in built in rule assemblies.
209+
- Added wild card supports for rules in Invoke-ScriptAnalyzer and Get-ScriptAnalyzer. Eg. Invoke-ScriptAnalyzer -IncludeRule PSAvoid* will apply all rules starting with PSAvoid* in built in rule assemblies.
180210
- Added -Severity to Get-ScriptAnalyzerRules. Get-ScriptAnalyzer -Severity will filter rules based on the severity given.
181211
- Added Suppression functionality. Users are now able to specify suppression on certain parts of the scripts by specifying "SupressMessageAttribute" in the scripts. More details and documentations will be coming soon in blog posts. Also comes with this feature is the ability for users to display a list of suppressed messages.
182212

Engine/Commands/GetScriptAnalyzerRuleCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public SwitchParameter RecurseCustomRulePath
5656
/// <summary>
5757
/// Name: The name of a specific rule to list.
5858
/// </summary>
59-
[Parameter(Mandatory = false)]
59+
[Parameter(Mandatory = false, Position = 1)]
6060
[ValidateNotNullOrEmpty]
6161
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
6262
public string[] Name

Engine/Commands/InvokeScriptAnalyzerCommand.cs

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
using System.Threading.Tasks;
2626
using System.Collections.Concurrent;
2727
using System.Threading;
28+
using System.Management.Automation.Runspaces;
2829

2930
namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.Commands
3031
{
@@ -44,7 +45,7 @@ public class InvokeScriptAnalyzerCommand : PSCmdlet, IOutputWriter
4445
[Parameter(Position = 0,
4546
ParameterSetName = "File",
4647
Mandatory = true,
47-
ValueFromPipeline = true,
48+
ValueFromPipeline = true,
4849
ValueFromPipelineByPropertyName = true)]
4950
[ValidateNotNull]
5051
[Alias("PSPath")]
@@ -188,9 +189,21 @@ public object Settings
188189

189190
private bool stopProcessing;
190191

191-
#endregion Parameters
192+
#if !PSV3
193+
/// <summary>
194+
/// Resolve DSC resource dependency
195+
/// </summary>
196+
[Parameter(Mandatory = false)]
197+
public SwitchParameter SaveDscDependency
198+
{
199+
get { return saveDscDependency; }
200+
set { saveDscDependency = value; }
201+
}
202+
private bool saveDscDependency;
203+
#endif // !PSV3
204+
#endregion Parameters
192205

193-
#region Overrides
206+
#region Overrides
194207

195208
/// <summary>
196209
/// Imports all known rules and loggers.
@@ -227,19 +240,23 @@ protected override void ProcessRecord()
227240
return;
228241
}
229242

230-
if (String.Equals(this.ParameterSetName, "File", StringComparison.OrdinalIgnoreCase))
243+
#if !PSV3
244+
// TODO Support dependency resolution for analyzing script definitions
245+
if (saveDscDependency)
231246
{
232-
// throws Item Not Found Exception
233-
Collection<PathInfo> paths = this.SessionState.Path.GetResolvedPSPathFromPSPath(path);
234-
foreach (PathInfo p in paths)
247+
using (var rsp = RunspaceFactory.CreateRunspace())
235248
{
236-
ProcessPathOrScriptDefinition(this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(p.Path));
249+
rsp.Open();
250+
using (var moduleHandler = new ModuleDependencyHandler(rsp))
251+
{
252+
ScriptAnalyzer.Instance.ModuleHandler = moduleHandler;
253+
ProcessInput();
254+
}
237255
}
256+
return;
238257
}
239-
else if (String.Equals(this.ParameterSetName, "ScriptDefinition", StringComparison.OrdinalIgnoreCase))
240-
{
241-
ProcessPathOrScriptDefinition(scriptDefinition);
242-
}
258+
#endif
259+
ProcessInput();
243260
}
244261

245262
protected override void EndProcessing()
@@ -254,33 +271,41 @@ protected override void StopProcessing()
254271
base.StopProcessing();
255272
}
256273

257-
#endregion
258-
259-
#region Methods
274+
#endregion
260275

261-
private void ProcessPathOrScriptDefinition(string pathOrScriptDefinition)
276+
#region Methods
277+
private void ProcessInput()
262278
{
263279
IEnumerable<DiagnosticRecord> diagnosticsList = Enumerable.Empty<DiagnosticRecord>();
264-
265280
if (String.Equals(this.ParameterSetName, "File", StringComparison.OrdinalIgnoreCase))
266281
{
267-
diagnosticsList = ScriptAnalyzer.Instance.AnalyzePath(pathOrScriptDefinition, this.recurse);
282+
// throws Item Not Found Exception
283+
Collection<PathInfo> paths = this.SessionState.Path.GetResolvedPSPathFromPSPath(path);
284+
foreach (PathInfo p in paths)
285+
{
286+
diagnosticsList = ScriptAnalyzer.Instance.AnalyzePath(
287+
this.SessionState.Path.GetUnresolvedProviderPathFromPSPath(p.Path),
288+
this.recurse);
289+
WriteToOutput(diagnosticsList);
290+
}
268291
}
269292
else if (String.Equals(this.ParameterSetName, "ScriptDefinition", StringComparison.OrdinalIgnoreCase))
270293
{
271-
diagnosticsList = ScriptAnalyzer.Instance.AnalyzeScriptDefinition(pathOrScriptDefinition);
294+
diagnosticsList = ScriptAnalyzer.Instance.AnalyzeScriptDefinition(scriptDefinition);
295+
WriteToOutput(diagnosticsList);
272296
}
297+
}
273298

274-
//Output through loggers
299+
private void WriteToOutput(IEnumerable<DiagnosticRecord> diagnosticRecords)
300+
{
275301
foreach (ILogger logger in ScriptAnalyzer.Instance.Loggers)
276302
{
277-
foreach (DiagnosticRecord diagnostic in diagnosticsList)
303+
foreach (DiagnosticRecord diagnostic in diagnosticRecords)
278304
{
279305
logger.LogObject(diagnostic, this);
280306
}
281307
}
282308
}
283-
284-
#endregion
309+
#endregion
285310
}
286311
}

Engine/Generic/CorrectionExtent.cs

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Management.Automation.Language;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
9+
namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic
10+
{
11+
public class CorrectionExtent
12+
{
13+
public int EndColumnNumber
14+
{
15+
get
16+
{
17+
return endColumnNumber;
18+
}
19+
}
20+
21+
public int EndLineNumber
22+
{
23+
get
24+
{
25+
return endLineNumber;
26+
}
27+
}
28+
29+
public string File
30+
{
31+
get
32+
{
33+
return file;
34+
}
35+
}
36+
37+
public int StartColumnNumber
38+
{
39+
get
40+
{
41+
return startColumnNumber;
42+
}
43+
}
44+
45+
public int StartLineNumber
46+
{
47+
get
48+
{
49+
return startLineNumber;
50+
}
51+
}
52+
53+
public string Text
54+
{
55+
get
56+
{
57+
return text;
58+
}
59+
}
60+
61+
public string Description
62+
{
63+
get
64+
{
65+
return description;
66+
}
67+
}
68+
69+
private string file;
70+
private int startLineNumber;
71+
private int endLineNumber;
72+
private int startColumnNumber;
73+
private int endColumnNumber;
74+
private string text;
75+
private string description;
76+
77+
public CorrectionExtent(
78+
int startLineNumber,
79+
int endLineNumber,
80+
int startColumnNumber,
81+
int endColumnNumber,
82+
string text,
83+
string file)
84+
: this(
85+
startLineNumber,
86+
endLineNumber,
87+
startColumnNumber,
88+
endColumnNumber,
89+
text,
90+
file,
91+
null)
92+
{
93+
}
94+
95+
public CorrectionExtent(
96+
int startLineNumber,
97+
int endLineNumber,
98+
int startColumnNumber,
99+
int endColumnNumber,
100+
string text,
101+
string file,
102+
string description)
103+
{
104+
this.startLineNumber = startLineNumber;
105+
this.endLineNumber = endLineNumber;
106+
this.startColumnNumber = startColumnNumber;
107+
this.endColumnNumber = endColumnNumber;
108+
this.file = file;
109+
this.text = text;
110+
this.description = description;
111+
ThrowIfInvalidArguments();
112+
}
113+
114+
115+
116+
private void ThrowIfInvalidArguments()
117+
{
118+
ThrowIfNull<string>(file, "filename");
119+
ThrowIfNull<string>(text, "text");
120+
ThrowIfDecreasing(startLineNumber, endLineNumber, "start line number cannot be less than end line number");
121+
if (startLineNumber == endLineNumber)
122+
{
123+
ThrowIfDecreasing(StartColumnNumber, endColumnNumber, "start column number cannot be less than end column number for a one line extent");
124+
}
125+
}
126+
127+
private void ThrowIfDecreasing(int start, int end, string message)
128+
{
129+
if (start > end)
130+
{
131+
throw new ArgumentException(message);
132+
}
133+
}
134+
135+
private void ThrowIfNull<T>(T arg, string argName)
136+
{
137+
if (arg == null)
138+
{
139+
throw new ArgumentNullException(argName);
140+
}
141+
}
142+
143+
}
144+
}

0 commit comments

Comments
 (0)