From ae5480888c4b0d44cbe16c5624a7d2d64e49b8d3 Mon Sep 17 00:00:00 2001 From: Quoc Truong Date: Wed, 10 Feb 2016 10:53:50 -0800 Subject: [PATCH] Fix a bug where deprecated manifest fields are raised even if powershellversion 2.0 is used --- Rules/AvoidUsingDeprecatedManifestFields.cs | 45 ++++++- ...oidUsingDeprecatedManifestFields.tests.ps1 | 11 +- ...tDeprecatedManifestFieldsWithVersion2.psd1 | 120 ++++++++++++++++++ .../Rules/TestGoodModule/TestGoodModule.psd1 | Bin 6564 -> 6566 bytes 4 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 Tests/Rules/TestGoodModule/TestDeprecatedManifestFieldsWithVersion2.psd1 diff --git a/Rules/AvoidUsingDeprecatedManifestFields.cs b/Rules/AvoidUsingDeprecatedManifestFields.cs index 8ec58ca60..b314ae8e5 100644 --- a/Rules/AvoidUsingDeprecatedManifestFields.cs +++ b/Rules/AvoidUsingDeprecatedManifestFields.cs @@ -17,6 +17,7 @@ using Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic; using System.ComponentModel.Composition; using System.Globalization; +using System.Linq; namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules { @@ -43,6 +44,49 @@ public IEnumerable AnalyzeScript(Ast ast, string fileName) { var ps = System.Management.Automation.PowerShell.Create(); IEnumerable result = null; + + // hash table in psd1 + var hashTableAst = ast.FindAll(item => item is HashtableAst, false).FirstOrDefault(); + + // no hash table means not a module manifest + if (hashTableAst == null) + { + yield break; + } + + var table = hashTableAst as HashtableAst; + + // needs to find the PowerShellVersion key + foreach (var kvp in table.KeyValuePairs) + { + if (kvp.Item1 != null && kvp.Item1 is StringConstantExpressionAst) + { + var key = (kvp.Item1 as StringConstantExpressionAst).Value; + + // find the powershellversion key in the hashtable + if (string.Equals(key, "PowerShellVersion", StringComparison.OrdinalIgnoreCase) && kvp.Item2 != null) + { + // get the string value of the version + var value = kvp.Item2.Find(item => item is StringConstantExpressionAst, false); + + if (value != null) + { + Version psVersion = null; + + // get the version + if (Version.TryParse((value as StringConstantExpressionAst).Value, out psVersion)) + { + // if version exists and version less than 3, don't raise rule + if (psVersion.Major < 3) + { + yield break; + } + } + } + } + } + } + try { ps.AddCommand("Test-ModuleManifest"); @@ -54,7 +98,6 @@ public IEnumerable AnalyzeScript(Ast ast, string fileName) ps.AddParameter("WarningVariable", "Message"); ps.AddScript("$Message"); result = ps.Invoke(); - } catch {} diff --git a/Tests/Rules/AvoidUsingDeprecatedManifestFields.tests.ps1 b/Tests/Rules/AvoidUsingDeprecatedManifestFields.tests.ps1 index f5729024b..723ad6524 100644 --- a/Tests/Rules/AvoidUsingDeprecatedManifestFields.tests.ps1 +++ b/Tests/Rules/AvoidUsingDeprecatedManifestFields.tests.ps1 @@ -1,8 +1,9 @@ Import-Module PSScriptAnalyzer $violationName = "PSAvoidUsingDeprecatedManifestFields" $directory = Split-Path -Parent $MyInvocation.MyCommand.Path -$violations = Invoke-ScriptAnalyzer $directory\TestBadModule\TestDeprecatedManifestFields.psd1 | Where-Object {$_.RuleName -eq $violationName} -$noViolations = Invoke-ScriptAnalyzer $directory\TestGoodModule\TestGoodModule.psd1 | Where-Object {$_.RuleName -eq $violationName} +$violations = Invoke-ScriptAnalyzer "$directory\TestBadModule\TestDeprecatedManifestFields.psd1" | Where-Object {$_.RuleName -eq $violationName} +$noViolations = Invoke-ScriptAnalyzer "$directory\TestGoodModule\TestGoodModule.psd1" | Where-Object {$_.RuleName -eq $violationName} +$noViolations2 = Invoke-ScriptAnalyzer "$directory\TestGoodModule\TestDeprecatedManifestFieldsWithVersion2.psd1" | Where-Object {$_.RuleName -eq $violationName} Describe "AvoidUsingDeprecatedManifestFields" { Context "When there are violations" { @@ -12,7 +13,11 @@ Describe "AvoidUsingDeprecatedManifestFields" { } Context "When there are no violations" { - It "returns no violations" { + It "returns no violations if no deprecated fields are used" { + $noViolations.Count | Should Be 0 + } + + It "returns no violations if deprecated fields are used but psVersion is less than 3.0" { $noViolations.Count | Should Be 0 } } diff --git a/Tests/Rules/TestGoodModule/TestDeprecatedManifestFieldsWithVersion2.psd1 b/Tests/Rules/TestGoodModule/TestDeprecatedManifestFieldsWithVersion2.psd1 new file mode 100644 index 000000000..c868183e2 --- /dev/null +++ b/Tests/Rules/TestGoodModule/TestDeprecatedManifestFieldsWithVersion2.psd1 @@ -0,0 +1,120 @@ +# +# Module manifest for module 'Deprecated Module manifest fields" +# +# Generated by: Microsoft PowerShell Team +# +# Generated on: 5/18/2015 +# + +@{ + +# Script module or binary module file associated with this manifest. +ModuleToProcess ='psscriptanalyzer' + +# Version number of this module. +ModuleVersion = '1.0' + +# ID used to uniquely identify this module +GUID = 'a9f79c02-4503-4300-a022-5e8c01f3449f' + +# Author of this module +Author = '' + +# Company or vendor of this module +CompanyName = '' + +# Copyright statement for this module +Copyright = '(c) 2015 Microsoft. All rights reserved.' + +# Description of the functionality provided by this module +# Description = '' + +# Minimum version of the Windows PowerShell engine required by this module +PowerShellVersion = '2.0' + +# Name of the Windows PowerShell host required by this module +# PowerShellHostName = '' + +# Minimum version of the Windows PowerShell host required by this module +# PowerShellHostVersion = '' + +# Minimum version of Microsoft .NET Framework required by this module +# DotNetFrameworkVersion = '' + +# Minimum version of the common language runtime (CLR) required by this module +# CLRVersion = '' + +# Processor architecture (None, X86, Amd64) required by this module +# ProcessorArchitecture = '' + +# Modules that must be imported into the global environment prior to importing this module +# RequiredModules = @() + +# Assemblies that must be loaded prior to importing this module +# RequiredAssemblies = @() + +# Script files (.ps1) that are run in the caller's environment prior to importing this module. +# ScriptsToProcess = @() + +# Type files (.ps1xml) to be loaded when importing this module +# TypesToProcess = @() + +# Format files (.ps1xml) to be loaded when importing this module +# FormatsToProcess = @() + +# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess +# NestedModules = @() + +# Functions to export from this module +FunctionsToExport = '*' + +# Cmdlets to export from this module +CmdletsToExport = '*' + +# Variables to export from this module +VariablesToExport = '*' + +# Aliases to export from this module +AliasesToExport = '*' + +# DSC resources to export from this module +# DscResourcesToExport = @() + +# List of all modules packaged with this module +# ModuleList = @() + +# List of all files packaged with this module +# FileList = @() + +# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable +#with additional module metadata used by PowerShell. +PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + # ProjectUri = '' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + } # End of PSData hashtable + +} # End of PrivateData hashtable + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} \ No newline at end of file diff --git a/Tests/Rules/TestGoodModule/TestGoodModule.psd1 b/Tests/Rules/TestGoodModule/TestGoodModule.psd1 index b3731edbc0facf8605831cd4e521802fadfd5b57..7175598a16a179d8d5ebfda3f44ec74caae87c9b 100644 GIT binary patch delta 26 icmZ2tyv%sR0@lfw*hD7pU=?FEX3%3W*nF1tx-bBP7YOhG delta 24 gcmZ2xyu^6J0@le9Y!Z{Vu!>Fo$HKSy9_tBV0C<@Rg#Z8m