From fa51b16b233c002d57e4656b804c92f38168f234 Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Wed, 31 Jul 2019 23:27:44 -0400 Subject: [PATCH 1/5] Clean up potentials that have already been done --- PotentialContribution/ModuleBuilder.psd1 | Bin 5460 -> 0 bytes PotentialContribution/ModuleBuilder.psm1 | 239 ----------------------- 2 files changed, 239 deletions(-) delete mode 100644 PotentialContribution/ModuleBuilder.psd1 delete mode 100644 PotentialContribution/ModuleBuilder.psm1 diff --git a/PotentialContribution/ModuleBuilder.psd1 b/PotentialContribution/ModuleBuilder.psd1 deleted file mode 100644 index 71ce594fb1c11a71d6263d569242b262ec7ba98c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5460 zcmchbYfl?j5QgV-rT&MN_yAOaa0yXbsZuESDxnd%v|oLtZZRgdsS{QG>q+0|j1One zdQA-pm1TQ(&zYHb?sN9@rzQK=zOf}M?4=E?ZP#{T9o_Y zZ#kp;N%TE&Xp3rS%TwM_!jYa{hLwgmcC@RorhT*@^#6w_k<-(Tb#KhS>Y zpV(vD)_2P`Y*TkGlV85i?eFj(k-QdnWLyQ!`kCggWiudYXxGOXox56dD>a09B%Q0=rHyahHC$=xXc+WjLmL%?pp7;9i$X3{}7oy@)+7eYf z!A8+K2@BdB*;{kIF88TDla0UE@22g@yKB1MGM=vKuBGpeuAb?4Lw9SE)RjM2*%C!t zpQi4+738}@2L|`}ZT10EzT0vA9Q5|6E$mF%5VeJ^D4t^s?+C-TtyX03NorqyB+Iac zWB5zfx)j>Q5am2h#j7v+!W`RMar#r=flc)5xfmk_$}7nQJ;hmW=f$v-ZQf7rjvL$8VLzVo zOvwH(PdubH^&YuTbP3*DzCPaVE~Eu{ajpOJus#f#Pu_c7T(LcSp(;&Px?l7;{UVyY3ifUZhffGh zPD~T@2dYm;S7YG=2mRtSXwk7py8BI?>}j~#74o*OpL_x4StPr2an$Ec>dn+7tWTd{ zrtz7LDGn{L^HqqUINeeEd>)8CJ68o8gl-%w8P%8AybNCQzC&H6LSi+iFY|`$`4mb0 z{II0eGhr&%#qxB69_ad9mS4>#!`5MiF`N(IVhrnHrs2+Vj*Ty*& z4OW!#OpTi%l9CUJN$(;|Z1|Ah=&hD?qv!ZE4c;Jryj4l?Z$2*c7~db9422n zQ^Zo$Am-EZ&7AKuFr5?3ooW8~sq2v@(F6Ms@NtIlX^z>1*|Mc*ET7TXeWd4OJ66SP z&a8oJlHt#(ISn2N0~`)RPfOEmd1qe9synf_`>7-3u}(7|lVQxJWPN=-o#lmvu|VSE zz2m#ejJ_w%?NC9+As+6FAm_8F^mmFvI!Pl`^H|HN0C%^+EU!gTaJm5lXPGbYLe6JV z=`Vs$sWF~yUeW2^c`kAmZE5=R>4|eh{d - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseCmdletCorrectly", "")] - param( - # The path to the module folder, manifest or build.psd1 - [Parameter(Position = 0, ValueFromPipelineByPropertyName)] - [ValidateScript( { - if (Test-Path $_) { - $true - } else { - throw "Source must point to a valid module" - } - } )] - [Alias("ModuleManifest")] - [string]$Path, - - # Where to build the module. - # Defaults to a version number folder, adjacent to the module folder - [Alias("Destination")] - [string]$OutputDirectory, - - [version]$ModuleVersion, - - # Folders which should be copied intact to the module output - # Can be relative to the module folder - [AllowEmptyCollection()] - [string[]]$CopyDirectories = @(), - - # A Filter (relative to the module folder) for public functions - # If non-empty, ExportedFunctions will be set with the file BaseNames of matching files - # Defaults to Public\*.ps1 - [AllowEmptyString()] - [string[]]$PublicFilter = "Public\*.ps1", - - # File encoding for output RootModule (defaults to UTF8) - [Microsoft.PowerShell.Commands.FileSystemCmdletProviderEncoding] - $Encoding = "UTF8", - - # A line which will be added at the bottom of the psm1. The intention is to allow you to add an export like: - # Export-ModuleMember -Alias *-QM* -Functions * -Variables QMConstant_* - # - # The default is nothing - $ExportModuleMember, - - # Controls whether or not there is a build or cleanup performed - [ValidateSet("Clean", "Build", "CleanBuild")] - [string]$Target = "CleanBuild", - - # Output the ModuleInfo of the "built" module - [switch]$Passthru - ) - - process { - try { - # If a path is $passed, use that - if ($Path) { - $ModuleBase = Split-Path $Path -Parent - # Do not use GetFileNameWithoutExtension, some module names have dots in them - $ModuleName = (Split-Path $Path -Leaf) -replace ".psd1$" - - # Support passing the path to a module folder - if (Test-Path $Path -PathType Container) { - if ( (Test-Path (Join-Path $Path build.psd1)) -or - (Test-Path (Join-Path $Path "$ModuleName.psd1")) - ) { - $ModuleBase = $Path - $Path = Join-Path $Path "$ModuleName.psd1" - if (Test-Path $Path) { - $PSBoundParameters["Path"] = $Path - } else { - $null = $PSBoundParameters.Remove("Path") - } - } else { - throw "Module not found in $Path. Try passing the full path to the manifest file." - } - } - - # Add support for passing the path to a build.psd1 - if ( (Test-Path $Path -PathType Leaf) -and ($ModuleName -eq "build") ) { - $null = $PSBoundParameters.Remove("Path") - } - - Push-Location $ModuleBase -StackName Optimize-Module - # Otherwise, look for a local build.psd1 - } elseif (Test-Path Build.psd1) { - Push-Location -StackName Optimize-Module - } else { - throw "Build.psd1 not found in PWD. You must specify the -Path to the build" - } - - # Read build.psd1 for defaults - if (Test-Path Build.psd1) { - $BuildInfo = Import-LocalizedData -BaseDirectory $Pwd.Path -FileName Build - } else { - $BuildInfo = @{} - } - - # Overwrite with parameter values - foreach ($property in $PSBoundParameters.Keys) { - $BuildInfo.$property = $PSBoundParameters.$property - } - - $BuildInfo.Path = Resolve-Path $BuildInfo.Path - - # Read Module Manifest for details - $ModuleInfo = Get-Module $BuildInfo.Path -ListAvailable -WarningAction SilentlyContinue -ErrorAction SilentlyContinue -ErrorVariable Problems - if ($Problems) { - $Problems = $Problems.Where{ $_.FullyQualifiedErrorId -notmatch "^Modules_InvalidRequiredModulesinModuleManifest"} - if ($Problems) { - foreach ($problem in $Problems) { - Write-Error $problem - } - throw "Unresolvable problems in module manifest" - } - } - foreach ($property in $BuildInfo.Keys) { - # Note:we can't overwrite the Path from the Build.psd1 - Add-Member -Input $ModuleInfo -Type NoteProperty -Name $property -Value $BuildInfo.$property -ErrorAction SilentlyContinue - } - - # Copy in default parameters - if (!(Get-Member -InputObject $ModuleInfo -Name PublicFilter)) { - Add-Member -Input $ModuleInfo -Type NoteProperty -Name PublicFilter -Value $PublicFilter - } - if (!(Get-Member -InputObject $ModuleInfo -Name Encoding)) { - Add-Member -Input $ModuleInfo -Type NoteProperty -Name Encoding -Value $Encoding - } - # Fix the version before making the folder - if ($ModuleVersion) { - Add-Member -Input $ModuleInfo -Type NoteProperty -Name Version -Value $ModuleVersion -Force - } - - # Ensure OutputDirectory - if (!$ModuleInfo.OutputDirectory) { - $OutputDirectory = Join-Path (Split-Path $ModuleInfo.ModuleBase -Parent) $ModuleInfo.Version - Add-Member -Input $ModuleInfo -Type NoteProperty -Name OutputDirectory -Value $OutputDirectory -Force - } - $OutputDirectory = $ModuleInfo.OutputDirectory - Write-Progress "Building $($ModuleInfo.ModuleBase)" -Status "Use -Verbose for more information" - Write-Verbose "Building $($ModuleInfo.ModuleBase)" - Write-Verbose " Output to: $OutputDirectory" - - if ($Target -match "Clean") { - Write-Verbose "Cleaning $OutputDirectory" - if (Test-Path $OutputDirectory) { - Remove-Item $OutputDirectory -Recurse -Force - } - if ($Target -notmatch "Build") { - return # No build, just cleaning - } - } else { - # If we're not cleaning, skip the build if it's up to date already - Write-Verbose "Target $Target" - $NewestBuild = Get-ChildItem $OutputDirectory -Recurse | - Sort-Object LastWriteTime -Descending | - Select-Object -First 1 -ExpandProperty LastWriteTime - $IsNew = Get-ChildItem $ModuleInfo.ModuleBase -Recurse | - Where-Object LastWriteTime -gt $NewestBuild | - Select-Object -First 1 -ExpandProperty LastWriteTime - if ($null -eq $IsNew) { - return # Skip the build - } - } - $null = mkdir $OutputDirectory -Force - - Write-Verbose "Copy files to $OutputDirectory" - # Copy the files and folders which won't be processed - Copy-Item *.psm1, *.psd1, *.ps1xml -Exclude "build.psd1" -Destination $OutputDirectory -Force - if ($ModuleInfo.CopyDirectories) { - Write-Verbose "Copy Entire Directories: $($ModuleInfo.CopyDirectories)" - Copy-Item -Path $ModuleInfo.CopyDirectories -Recurse -Destination $OutputDirectory -Force - } - - # Output psm1 - $RootModule = Join-Path $OutputDirectory "$($ModuleInfo.Name).psm1" - $OutputManifest = Join-Path $OutputDirectory "$($ModuleInfo.Name).psd1" - - Write-Verbose "Combine scripts to $RootModule" - # Prefer pipeline to speed for the sake of memory and file IO - # SilentlyContinue because there don't *HAVE* to be functions at all - $AllScripts = Get-ChildItem -Path $ModuleInfo.ModuleBase -Exclude $ModuleInfo.CopyDirectories -Directory -ErrorAction SilentlyContinue | - Get-ChildItem -Filter *.ps1 -Recurse -ErrorAction SilentlyContinue - - if ($AllScripts) { - $AllScripts | ForEach-Object { - $SourceName = Resolve-Path $_.FullName -Relative - Write-Verbose "Adding $SourceName" - "# BEGIN $SourceName" - Get-Content $SourceName - "# END $SourceName" - } | Set-Content -Path $RootModule -Encoding $ModuleInfo.Encoding - - if ($ModuleInfo.ExportModuleMember) { - Add-Content -Path $RootModule -Value $ModuleInfo.ExportModuleMember -Encoding $ModuleInfo.Encoding - } - - # If there is a PublicFilter, update ExportedFunctions - if ($ModuleInfo.PublicFilter) { - # SilentlyContinue because there don't *HAVE* to be public functions - if ($PublicFunctions = Get-ChildItem $ModuleInfo.PublicFilter -Recurse -ErrorAction SilentlyContinue | Select-Object -ExpandProperty BaseName) { - # TODO: Remove the _Public hack - Update-Metadata -Path $OutputManifest -PropertyName FunctionsToExport -Value ($PublicFunctions -replace "_Public$") - } - } - } - - Write-Verbose "Update Manifest to $OutputManifest" - - Update-Metadata -Path $OutputManifest -PropertyName Copyright -Value ($ModuleInfo.Copyright -replace "20\d\d", (Get-Date).Year) - - if ($ModuleVersion) { - Update-Metadata -Path $OutputManifest -PropertyName ModuleVersion -Value $ModuleVersion - } - - # This is mostly for testing ... - if ($Passthru) { - Get-Module $OutputManifest -ListAvailable - } - } finally { - Pop-Location -StackName Optimize-Module -ErrorAction SilentlyContinue - } - } -} From ccfe81f46fc144c32ee8c9cc7eb1ce080c4f6e35 Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Wed, 31 Jul 2019 23:31:26 -0400 Subject: [PATCH 2/5] Refactor MoveUsingStatements --- Source/Private/ConvertToAst.ps1 | 36 ++++++++++ Source/Private/MoveUsingStatements.ps1 | 23 +++--- Source/Public/Build-Module.ps1 | 9 ++- Tests/Private/ConvertToAst.Tests.ps1 | 78 +++++++++++++++++++++ Tests/Private/MoveUsingStatements.Tests.ps1 | 49 ++++++++----- Tests/Public/Convert-CodeCoverage.Tests.ps1 | 6 +- Tests/Public/Convert-LineNumber.Tests.ps1 | 9 ++- 7 files changed, 168 insertions(+), 42 deletions(-) create mode 100644 Source/Private/ConvertToAst.ps1 create mode 100644 Tests/Private/ConvertToAst.Tests.ps1 diff --git a/Source/Private/ConvertToAst.ps1 b/Source/Private/ConvertToAst.ps1 new file mode 100644 index 0000000..cc66e26 --- /dev/null +++ b/Source/Private/ConvertToAst.ps1 @@ -0,0 +1,36 @@ +function ConvertToAst { + <# + .SYNOPSIS + Parses the given code and returns an object with the AST, Tokens and ParseErrors + #> + param( + # The script content, or script or module file path to parse + [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] + [Alias("Path", "PSPath", "Definition", "ScriptBlock", "Module")] + $Code + ) + process { + Write-Debug " ENTER: ConvertToAst $Code" + $ParseErrors = $null + $Tokens = $null + if ($Code | Test-Path -ErrorAction SilentlyContinue) { + Write-Debug " Parse Code as Path" + $AST = [System.Management.Automation.Language.Parser]::ParseFile(($Code | Convert-Path), [ref]$Tokens, [ref]$ParseErrors) + } elseif ($Code -is [System.Management.Automation.FunctionInfo]) { + Write-Debug " Parse Code as Function" + $String = "function $($Code.Name) { $($Code.Definition) }" + $AST = [System.Management.Automation.Language.Parser]::ParseInput($String, [ref]$Tokens, [ref]$ParseErrors) + } else { + Write-Debug " Parse Code as String" + $AST = [System.Management.Automation.Language.Parser]::ParseInput([String]$Code, [ref]$Tokens, [ref]$ParseErrors) + } + + Write-Debug " EXIT: ConvertToAst" + [PSCustomObject]@{ + PSTypeName = "PoshCode.ModuleBuilder.ParseResults" + ParseErrors = $ParseErrors + Tokens = $Tokens + AST = $AST + } + } +} diff --git a/Source/Private/MoveUsingStatements.ps1 b/Source/Private/MoveUsingStatements.ps1 index 7ed05e3..1648ecf 100644 --- a/Source/Private/MoveUsingStatements.ps1 +++ b/Source/Private/MoveUsingStatements.ps1 @@ -19,27 +19,24 @@ function MoveUsingStatements { Param( # Path to the PSM1 file to amend [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline)] - $RootModule, + [System.Management.Automation.Language.Ast]$AST, + + [Parameter(ValueFromPipelineByPropertyName, ValueFromPipeline)] + [AllowNull()] + [System.Management.Automation.Language.ParseError[]]$ParseErrors, # The encoding defaults to UTF8 (or UTF8NoBom on Core) [Parameter(DontShow)] [string]$Encoding = $(if ($IsCoreCLR) { "UTF8NoBom" } else { "UTF8" }) ) - $ParseError = $null - $AST = [System.Management.Automation.Language.Parser]::ParseFile( - $RootModule, - [ref]$null, - [ref]$ParseError - ) - # Avoid modifying the file if there's no Parsing Error caused by Using Statements or other errors - if (!$ParseError.Where{$_.ErrorId -eq 'UsingMustBeAtStartOfScript'}) { + if (!$ParseErrors.Where{$_.ErrorId -eq 'UsingMustBeAtStartOfScript'}) { Write-Debug "No Using Statement Error found." return } # Avoid modifying the file if there's other parsing errors than Using Statements misplaced - if ($ParseError.Where{$_.ErrorId -ne 'UsingMustBeAtStartOfScript'}) { + if ($ParseErrors.Where{$_.ErrorId -ne 'UsingMustBeAtStartOfScript'}) { Write-Warning "Parsing errors found. Skipping Moving Using statements." return } @@ -70,13 +67,13 @@ function MoveUsingStatements { $null = [System.Management.Automation.Language.Parser]::ParseInput( $ScriptText, [ref]$null, - [ref]$ParseError + [ref]$ParseErrors ) - if ($ParseError) { + if ($ParseErrors) { Write-Warning "Oops, it seems that we introduced parsing error(s) while moving the Using Statements. Cancelling changes." } else { $null = Set-Content -Value $ScriptText -Path $RootModule -Encoding $Encoding } -} \ No newline at end of file +} diff --git a/Source/Public/Build-Module.ps1 b/Source/Public/Build-Module.ps1 index 7363ea8..01000ba 100644 --- a/Source/Public/Build-Module.ps1 +++ b/Source/Public/Build-Module.ps1 @@ -42,6 +42,7 @@ function Build-Module { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseApprovedVerbs", "", Justification="Build is approved now")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseCmdletCorrectly", "")] [CmdletBinding(DefaultParameterSetName="SemanticVersion")] + [Alias("build")] param( # The path to the module folder, manifest or build.psd1 [Parameter(Position = 0, ValueFromPipelineByPropertyName)] @@ -96,7 +97,7 @@ function Build-Module { ), # A Filter (relative to the module folder) for public functions - # If non-empty, ExportedFunctions will be set with the file BaseNames of matching files + # If non-empty, FunctionsToExport will be set with the file BaseNames of matching files # Defaults to Public\*.ps1 [AllowEmptyString()] [string[]]$PublicFilter = "Public\*.ps1", @@ -197,17 +198,19 @@ function Build-Module { # SilentlyContinue because there don't *HAVE* to be functions at all $AllScripts = Get-ChildItem -Path @($ModuleInfo.SourceDirectories).ForEach{ Join-Path $ModuleInfo.ModuleBase $_ } -Filter *.ps1 -Recurse -ErrorAction SilentlyContinue + # We have to force the Encoding to string because PowerShell Core made up encodings SetModuleContent -Source (@($ModuleInfo.Prefix) + $AllScripts.FullName + @($ModuleInfo.Suffix)).Where{$_} -Output $RootModule -Encoding "$($ModuleInfo.Encoding)" - MoveUsingStatements -RootModule $RootModule -Encoding "$($ModuleInfo.Encoding)" # If there is a PublicFilter, update ExportedFunctions if ($ModuleInfo.PublicFilter) { # SilentlyContinue because there don't *HAVE* to be public functions - if ($PublicFunctions = Get-ChildItem $ModuleInfo.PublicFilter -Recurse -ErrorAction SilentlyContinue | Select-Object -ExpandProperty BaseName) { + if (($PublicFunctions = Get-ChildItem $ModuleInfo.PublicFilter -Recurse -ErrorAction SilentlyContinue | Select-Object -ExpandProperty BaseName)) { Update-Metadata -Path $OutputManifest -PropertyName FunctionsToExport -Value $PublicFunctions } } + $ParseResult = ConvertToAst $RootModule + $ParseResult | MoveUsingStatements -Encoding "$($ModuleInfo.Encoding)" try { if ($Version) { Write-Verbose "Update Manifest at $OutputManifest with version: $Version" diff --git a/Tests/Private/ConvertToAst.Tests.ps1 b/Tests/Private/ConvertToAst.Tests.ps1 new file mode 100644 index 0000000..67ec90f --- /dev/null +++ b/Tests/Private/ConvertToAst.Tests.ps1 @@ -0,0 +1,78 @@ +Describe "ConvertToAst" { + Import-Module ModuleBuilder -DisableNameChecking -Verbose:$False + + Context "It returns a ParseResult for file paths" { + $ParseResult = InModuleScope ModuleBuilder { + ConvertToAst $PSCommandPath -Debug + } + + It "Returns a ParseResult object" { + $ParseResult.PSTypeNames[0] | Should -Match .*\.ParseResult + } + It "Has an AST property" { + $ParseResult.AST | Should -BeOfType [System.Management.Automation.Language.Ast] + } + It "Has a ParseErrors property" { + $ParseResult.ParseErrors | Should -BeNullOrEmpty # [System.Management.Automation.Language.ParseError[]] + } + It "Has a Tokens property" { + $ParseResult.Tokens | Should -BeOfType [System.Management.Automation.Language.Token] + } + + } + + Context "It parses piped in commands" { + $ParseResult = InModuleScope ModuleBuilder { + Get-Command ConvertToAst | ConvertToAst -Debug + } + + It "Returns a ParseResult object with the AST" { + $ParseResult.PSTypeNames[0] | Should -Match .*\.ParseResult + $ParseResult.AST | Should -BeOfType [System.Management.Automation.Language.Ast] + } + } + + Context "It parses piped in modules" { + $ParseResult = InModuleScope ModuleBuilder { + Get-Module ModuleBuilder | ConvertToAst -Debug + } + + It "Returns a ParseResult object with the AST" { + $ParseResult.PSTypeNames[0] | Should -Match .*\.ParseResult + $ParseResult.AST | Should -BeOfType [System.Management.Automation.Language.Ast] + } + } + +<# + param( + # The script content, or script or module file path to parse + [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] + [Alias("Path", "PSPath", "Definition", "ScriptBlock", "Module")] + $Code + ) + process { + Write-Debug " ENTER: ConvertToAst $Code" + $ParseErrors = $null + $Tokens = $null + if ($Code | Test-Path -ErrorAction SilentlyContinue) { + Write-Debug " Parse Code as Path" + $AST = [System.Management.Automation.Language.Parser]::ParseFile(($Code | Convert-Path), [ref]$Tokens, [ref]$ParseErrors) + } elseif ($Code -is [System.Management.Automation.FunctionInfo]) { + Write-Debug " Parse Code as Function" + $String = "function $($Code.Name) { $($Code.Definition) }" + $AST = [System.Management.Automation.Language.Parser]::ParseInput($String, [ref]$Tokens, [ref]$ParseErrors) + } else { + Write-Debug " Parse Code as String" + $AST = [System.Management.Automation.Language.Parser]::ParseInput([String]$Code, [ref]$Tokens, [ref]$ParseErrors) + } + + Write-Debug " EXIT: ConvertToAst" + [PSCustomObject]@{ + PSTypeName = "PoshCode.ModuleBuilder.ParseResults" + ParseErrors = $ParseErrors + Tokens = $Tokens + AST = $AST + } + } + #> +} diff --git a/Tests/Private/MoveUsingStatements.Tests.ps1 b/Tests/Private/MoveUsingStatements.Tests.ps1 index 5c9e0f2..4513e83 100644 --- a/Tests/Private/MoveUsingStatements.Tests.ps1 +++ b/Tests/Private/MoveUsingStatements.Tests.ps1 @@ -3,10 +3,11 @@ Describe "MoveUsingStatements" { Context "Necessary Parameters" { $CommandInfo = InModuleScope ModuleBuilder { Get-Command MoveUsingStatements } - It 'has a mandatory RootModule parameter' { - $RootModule = $CommandInfo.Parameters['RootModule'] - $RootModule | Should -Not -BeNullOrEmpty - $RootModule.Attributes.Where{$_ -is [Parameter]}.Mandatory | Should -Be $true + It 'has a mandatory AST parameter' { + $AST = $CommandInfo.Parameters['AST'] + $AST | Should -Not -BeNullOrEmpty + $AST.ParameterType | Should -Be ([System.Management.Automation.Language.Ast]) + $AST.Attributes.Where{ $_ -is [Parameter] }.Mandatory | Should -Be $true } It "has an optional string Encoding parameter" { @@ -18,42 +19,54 @@ Describe "MoveUsingStatements" { } Context "Moving Using Statements to the beginning of the file" { + $MoveUsingStatementsCmd = InModuleScope ModuleBuilder { - $null = Mock Write-Warning {} - Get-Command MoveUsingStatements + $null = Mock Write-Warning { } + { param($RootModule) + ConvertToAst $RootModule | MoveUsingStatements + } } $TestCases = @( @{ - TestCaseName = '2xUsingMustBeAtStartOfScript Fixed' + TestCaseName = 'Move all using statements in `n terminated files to the top' + PSM1File = "function x {`n}`n" + + "using namespace System.IO`n`n" + #UsingMustBeAtStartOfScript + "function y {`n}`n" + + "using namespace System.Drawing" #UsingMustBeAtStartOfScript + ErrorBefore = 2 + ErrorAfter = 0 + }, + @{ + TestCaseName = 'Move all using statements in `r`n terminated files to the top' PSM1File = "function x {`r`n}`r`n" + - "Using namespace System.io`r`n`r`n" + #UsingMustBeAtStartOfScript + "USING namespace System.IO`r`n`r`n" + #UsingMustBeAtStartOfScript "function y {`r`n}`r`n" + - "Using namespace System.Drawing" #UsingMustBeAtStartOfScript + "USING namespace System.Drawing" #UsingMustBeAtStartOfScript ErrorBefore = 2 ErrorAfter = 0 }, @{ - TestCaseName = 'NoErrors Do Nothing' - PSM1File = "Using namespace System.io`r`n`r`n" + - "Using namespace System.Drawing`r`n" + + TestCaseName = 'Not change the content again if there are no out-of-place using statements' + PSM1File = "using namespace System.IO`r`n`r`n" + + "using namespace System.Drawing`r`n" + "function x { `r`n}`r`n" + "function y { `r`n}`r`n" ErrorBefore = 0 ErrorAfter = 0 }, @{ - TestCaseName = 'NotValidPowerShel Do Nothing' - PSM1File = "Using namespace System.io`r`n`r`n" + + TestCaseName = 'Not move anything if there are (other) parse errors' + PSM1File = "using namespace System.IO`r`n`r`n" + "function x { `r`n}`r`n" + - "Using namespace System.Drawing`r`n" + # UsingMustBeAtStartOfScript + "using namespace System.Drawing`r`n" + # UsingMustBeAtStartOfScript "function y { `r`n}`r`n}" # Extra } at the end ErrorBefore = 2 ErrorAfter = 2 } ) - It 'Should succeed test: "" from to parsing errors' -TestCases $TestCases { + It 'It should ' -TestCases $TestCases { param($TestCaseName, $PSM1File, $ErrorBefore, $ErrorAfter) $testModuleFile = "$TestDrive/MyModule.psm1" @@ -85,7 +98,9 @@ Describe "MoveUsingStatements" { $null = Mock Set-Content {} $null = Mock Write-Debug {} -ParameterFilter {$Message -eq "No Using Statement Error found." } - Get-Command MoveUsingStatements + { param($RootModule) + ConvertToAst $RootModule | MoveUsingStatements + } } It 'Should Warn and skip when there are Parsing errors other than Using Statements' { diff --git a/Tests/Public/Convert-CodeCoverage.Tests.ps1 b/Tests/Public/Convert-CodeCoverage.Tests.ps1 index de5d42b..df6f42d 100644 --- a/Tests/Public/Convert-CodeCoverage.Tests.ps1 +++ b/Tests/Public/Convert-CodeCoverage.Tests.ps1 @@ -16,9 +16,6 @@ Describe "Convert-CodeCoverage" { $PesterResults = [PSCustomObject]@{ CodeCoverage = [PSCustomObject]@{ MissedCommands = [PSCustomObject]@{ - # Note these don't really matter - Command = $ModuleContent[25] - Function = 'CopyReadMe' # these are pipeline bound File = $ModulePath Line = 26 # 1 offset with the Using Statement introduced in MoveUsingStatements @@ -28,7 +25,8 @@ Describe "Convert-CodeCoverage" { $SourceLocation = $PesterResults | Convert-CodeCoverage -SourceRoot $ModuleSource - $SourceLocation.SourceFile | Should -Be ".\Private\CopyReadMe.ps1" + # Needs to match the actual module source (on line 25) + $SourceLocation.SourceFile | Should -Be ".\Private\ConvertToAst.ps1" $SourceLocation.Line | Should -Be 25 } } diff --git a/Tests/Public/Convert-LineNumber.Tests.ps1 b/Tests/Public/Convert-LineNumber.Tests.ps1 index e5337c6..f4b662e 100644 --- a/Tests/Public/Convert-LineNumber.Tests.ps1 +++ b/Tests/Public/Convert-LineNumber.Tests.ps1 @@ -51,9 +51,8 @@ Describe "Convert-LineNumber" { It 'Should pass through InputObject for updating objects like CodeCoverage or ErrorRecord' { $PesterMiss = [PSCustomObject]@{ - # Note these don't really matter - Command = $ModuleContent[25] - Function = 'CopyReadMe' + # Note these don't really matter, but they're passed through + Function = 'TotalNonsense' # these are pipeline bound File = $ModulePath Line = 26 # 1 offset with the Using Statement introduced in MoveUsingStatements @@ -61,8 +60,8 @@ Describe "Convert-LineNumber" { $SourceLocation = $PesterMiss | Convert-LineNumber -Passthru # This test is assuming you built the code on Windows. Should Convert-LineNumber convert the path? - $SourceLocation.SourceFile | Should -Be ".\Private\CopyReadMe.ps1" + $SourceLocation.SourceFile | Should -Be ".\Private\ConvertToAst.ps1" $SourceLocation.SourceLineNumber | Should -Be 25 - $SourceLocation.Function | Should -Be 'CopyReadMe' + $SourceLocation.Function | Should -Be 'TotalNonsense' } } From 36972693a2d8535381eda17df1ba5b63f50b6b0e Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Wed, 31 Jul 2019 23:59:42 -0400 Subject: [PATCH 3/5] Add Alias Exporting GetCommandAlias Add integration tests --- Source/ModuleBuilder.psd1 | 1 + Source/Private/GetCommandAlias.ps1 | 23 ++++++++ Source/Public/Build-Module.ps1 | 13 +++++ Tests/Integration/Source1.Tests.ps1 | 24 +++++++- .../Integration/Source1/Public/Get-Finale.ps1 | 7 +++ .../Integration/Source1/Public/Get-Source.ps1 | 5 +- Tests/Integration/Source1/Source1.psd1 | 1 + Tests/Private/GetCommandAlias.Tests.ps1 | 57 +++++++++++++++++++ Tests/Public/Build-Module.Tests.ps1 | 26 +++++++++ 9 files changed, 153 insertions(+), 4 deletions(-) create mode 100644 Source/Private/GetCommandAlias.ps1 create mode 100644 Tests/Integration/Source1/Public/Get-Finale.ps1 create mode 100644 Tests/Private/GetCommandAlias.Tests.ps1 diff --git a/Source/ModuleBuilder.psd1 b/Source/ModuleBuilder.psd1 index a926c23..af6a68e 100644 --- a/Source/ModuleBuilder.psd1 +++ b/Source/ModuleBuilder.psd1 @@ -37,6 +37,7 @@ # Always define FunctionsToExport as an empty @() which will be replaced on build FunctionsToExport = @() + AliasesToExport = @() # ID used to uniquely identify this module GUID = '4775ad56-8f64-432f-8da7-87ddf7a34653' diff --git a/Source/Private/GetCommandAlias.ps1 b/Source/Private/GetCommandAlias.ps1 new file mode 100644 index 0000000..e5580f2 --- /dev/null +++ b/Source/Private/GetCommandAlias.ps1 @@ -0,0 +1,23 @@ +function GetCommandAlias { + [CmdletBinding()] + param( + # Path to the PSM1 file to amend + [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline)] + [System.Management.Automation.Language.Ast]$AST + ) + begin { + $Result = [Ordered]@{} + } + process { + foreach($function in $AST.FindAll( + { $Args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }, + $false ) + ) { + $Result[$function.Name] = $function.Body.ParamBlock.Attributes.Where{ + $_.TypeName.Name -eq "Alias" }.PositionalArguments.Value + } + } + end { + $Result + } +} diff --git a/Source/Public/Build-Module.ps1 b/Source/Public/Build-Module.ps1 index 01000ba..3c50ff3 100644 --- a/Source/Public/Build-Module.ps1 +++ b/Source/Public/Build-Module.ps1 @@ -102,6 +102,12 @@ function Build-Module { [AllowEmptyString()] [string[]]$PublicFilter = "Public\*.ps1", + # A switch that allows you to disable the update of the AliasesToExport + # By default, (if PublicFilter is not empty, and this is not set) + # Build-Module updates the module manifest FunctionsToExport and AliasesToExport + # with the combination of all the values in [Alias()] attributes on public functions in the module + [switch]$IgnoreAliasAttribute, + # File encoding for output RootModule (defaults to UTF8) # Converted to System.Text.Encoding for PowerShell 6 (and something else for PowerShell 5) [ValidateSet("UTF8","UTF7","ASCII","Unicode","UTF32")] @@ -211,6 +217,13 @@ function Build-Module { $ParseResult = ConvertToAst $RootModule $ParseResult | MoveUsingStatements -Encoding "$($ModuleInfo.Encoding)" + + if ($PublicFunctions -and -not $ModuleInfo.IgnoreAliasAttribute) { + if (($AliasesToExport = ($ParseResult | GetCommandAlias)[$PublicFunctions] | Select-Object -Unique)) { + Update-Metadata -Path $OutputManifest -PropertyName AliasesToExport -Value $AliasesToExport + } + } + try { if ($Version) { Write-Verbose "Update Manifest at $OutputManifest with version: $Version" diff --git a/Tests/Integration/Source1.Tests.ps1 b/Tests/Integration/Source1.Tests.ps1 index 3f61469..28bee8d 100644 --- a/Tests/Integration/Source1.Tests.ps1 +++ b/Tests/Integration/Source1.Tests.ps1 @@ -1,13 +1,31 @@ #requires -Module ModuleBuilder Describe "Build-Module With Source1" { - Write-Host "Current Modules`n$(Get-Module | Out-String)" + Write-Host "Current Modules: `n$(Get-Module | Out-String)" -ForegroundColor DarkGreen -BackgroundColor Yellow Context "When we call Build-Module" { $Output = Build-Module $PSScriptRoot\Source1\build.psd1 -Passthru + $Module = [IO.Path]::ChangeExtension($Output.Path, "psm1") It "Should not put the module's DefaultCommandPrefix into the psm1 as code. Duh!" { - [IO.Path]::ChangeExtension($Output.Path, "psm1") | - Should -Not -FileContentMatch '^Source$' + $Module | Should -Not -FileContentMatch '^Source$' + } + + $Metadata = Import-Metadata $Output.Path + + It "Should update FunctionsToExport in the manifest" { + $Metadata.FunctionsToExport | Should -Be @("Get-Finale", "Get-Source") + } + + It "Should update AliasesToExport in the manifest" { + $Metadata.AliasesToExport | Should -Be @("GS") + } + + It "Should de-dupe and move using statements to the top of the file" { + Select-String -Pattern "^using" -Path $Module | ForEach-Object LineNumber | Should -Be 1 + } + + It "Will comment out the original using statements in their original positions" { + (Select-String -Pattern "^#\s*using" -Path $Module).Count | Should -Be 2 } } } diff --git a/Tests/Integration/Source1/Public/Get-Finale.ps1 b/Tests/Integration/Source1/Public/Get-Finale.ps1 new file mode 100644 index 0000000..f2e2fbf --- /dev/null +++ b/Tests/Integration/Source1/Public/Get-Finale.ps1 @@ -0,0 +1,7 @@ +using module ModuleBuilder + +function Get-Finale { + [CmdletBinding()] + [Alias("gs")] + param() +} diff --git a/Tests/Integration/Source1/Public/Get-Source.ps1 b/Tests/Integration/Source1/Public/Get-Source.ps1 index 7182287..5e145c6 100644 --- a/Tests/Integration/Source1/Public/Get-Source.ps1 +++ b/Tests/Integration/Source1/Public/Get-Source.ps1 @@ -1,4 +1,7 @@ +using module ModuleBuilder + function Get-Source { [CmdletBinding()] + [Alias("gs")] param() -} \ No newline at end of file +} diff --git a/Tests/Integration/Source1/Source1.psd1 b/Tests/Integration/Source1/Source1.psd1 index 1f56d07..ece8450 100644 --- a/Tests/Integration/Source1/Source1.psd1 +++ b/Tests/Integration/Source1/Source1.psd1 @@ -39,6 +39,7 @@ # Always define FunctionsToExport as an empty @() which will be replaced on build FunctionsToExport = @() + AliasesToExport = @() # ID used to uniquely identify this module GUID = 'a264e183-e0f7-4219-bc80-c30d14e0e98e' diff --git a/Tests/Private/GetCommandAlias.Tests.ps1 b/Tests/Private/GetCommandAlias.Tests.ps1 new file mode 100644 index 0000000..422cc97 --- /dev/null +++ b/Tests/Private/GetCommandAlias.Tests.ps1 @@ -0,0 +1,57 @@ +Describe "GetCommandAlias" { + Import-Module ModuleBuilder -DisableNameChecking -Verbose:$False + + Context "Mandatory Parameter" { + $CommandInfo = InModuleScope ModuleBuilder { Get-Command GetCommandAlias } + + It 'has a mandatory AST parameter' { + $AST = $CommandInfo.Parameters['AST'] + $AST | Should -Not -BeNullOrEmpty + $AST.ParameterType | Should -Be ([System.Management.Automation.Language.Ast]) + $AST.Attributes.Where{ $_ -is [Parameter] }.Mandatory | Should -Be $true + } + + } + + Context "Parsing Code" { + It "returns a hashtable of command names to aliases" { + $Result = InModuleScope ModuleBuilder { + GetCommandAlias -Ast { + function Test-Alias { + [Alias("Foo","Bar","Alias")] + param() + } + }.Ast + } + + $Result["Test-Alias"] | Should -Be @("Foo", "Bar", "Alias") + } + } + + Context "Parsing Code" { + It "Parses only top-level functions, and returns them in order" { + $Result = InModuleScope ModuleBuilder { + GetCommandAlias -Ast { + function Test-Alias { + [Alias("TA", "TAlias")] + param() + } + + function TestAlias { + [Alias("T")] + param() + + function Test-Negative { + [Alias("TN")] + param() + } + } + }.Ast + } + + $Result.Keys | Should -Be "Test-Alias", "TestAlias" + $Result["Test-Alias"] | Should -Be "TA","TAlias" + $Result["TestAlias"] | Should -Be "T" + } + } +} diff --git a/Tests/Public/Build-Module.Tests.ps1 b/Tests/Public/Build-Module.Tests.ps1 index d5725e3..bdd5f14 100644 --- a/Tests/Public/Build-Module.Tests.ps1 +++ b/Tests/Public/Build-Module.Tests.ps1 @@ -61,6 +61,16 @@ Describe "Build-Module" { New-Item -ItemType Directory -Path TestDrive:\1.0.0\ -Force Mock SetModuleContent -ModuleName ModuleBuilder {} + Mock ConvertToAst -ModuleName ModuleBuilder { + [PSCustomObject]@{ + PSTypeName = "PoshCode.ModuleBuilder.ParseResults" + ParseErrors = $null + Tokens = $null + AST = { }.AST + } + } + Mock GetCommandAlias -ModuleName ModuleBuilder { @{'Get-MyInfo' = @('GMI') } } + Mock MoveUsingStatements -ModuleName ModuleBuilder {} Mock Update-Metadata -ModuleName ModuleBuilder {} Mock InitializeBuild -ModuleName ModuleBuilder { # These are actually all the values that we need @@ -111,6 +121,16 @@ Describe "Build-Module" { } } + It "Should call ConvertToAst to parse the module" { + Assert-MockCalled ConvertToAst -ModuleName ModuleBuilder + } + + It "Should call MoveUsingStatements to move the using statements, just in case" { + Assert-MockCalled MoveUsingStatements -ModuleName ModuleBuilder -Parameter { + $AST.Extent.Text -eq "{ }" + } + } + It "Should call SetModuleContent to combine the source files" { Assert-MockCalled SetModuleContent -ModuleName ModuleBuilder } @@ -120,6 +140,12 @@ Describe "Build-Module" { $PropertyName -eq "FunctionsToExport" } } + + It "Should call Update-Metadata to set the AliasesToExport" { + Assert-MockCalled Update-Metadata -ModuleName ModuleBuilder -Parameter { + $PropertyName -eq "AliasesToExport" + } + } } Context "When run without 'Clean' in the target" { From c636e903b230d92307acba492bd42b59af045830 Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Fri, 2 Aug 2019 00:06:31 -0400 Subject: [PATCH 4/5] Add some tests for SourceDirectories Caught a bug in the exports and fixed that --- Source/Public/Build-Module.ps1 | 2 +- Tests/Integration/Source1.Tests.ps1 | 53 ++++++++++++++++++- .../Get-Finale.ps1 => Private/GetFinale.ps1} | 4 +- .../Source1/Private/GetPreview.ps1 | 7 +++ Tests/Integration/build.psd1 | 5 ++ 5 files changed, 66 insertions(+), 5 deletions(-) rename Tests/Integration/Source1/{Public/Get-Finale.ps1 => Private/GetFinale.ps1} (61%) create mode 100644 Tests/Integration/Source1/Private/GetPreview.ps1 create mode 100644 Tests/Integration/build.psd1 diff --git a/Source/Public/Build-Module.ps1 b/Source/Public/Build-Module.ps1 index 3c50ff3..44c6426 100644 --- a/Source/Public/Build-Module.ps1 +++ b/Source/Public/Build-Module.ps1 @@ -210,7 +210,7 @@ function Build-Module { # If there is a PublicFilter, update ExportedFunctions if ($ModuleInfo.PublicFilter) { # SilentlyContinue because there don't *HAVE* to be public functions - if (($PublicFunctions = Get-ChildItem $ModuleInfo.PublicFilter -Recurse -ErrorAction SilentlyContinue | Select-Object -ExpandProperty BaseName)) { + if (($PublicFunctions = Get-ChildItem $ModuleInfo.PublicFilter -Recurse -ErrorAction SilentlyContinue | Where-Object BaseName -in $AllScripts.BaseName | Select-Object -ExpandProperty BaseName)) { Update-Metadata -Path $OutputManifest -PropertyName FunctionsToExport -Value $PublicFunctions } } diff --git a/Tests/Integration/Source1.Tests.ps1 b/Tests/Integration/Source1.Tests.ps1 index 28bee8d..9b49428 100644 --- a/Tests/Integration/Source1.Tests.ps1 +++ b/Tests/Integration/Source1.Tests.ps1 @@ -1,7 +1,6 @@ #requires -Module ModuleBuilder Describe "Build-Module With Source1" { - Write-Host "Current Modules: `n$(Get-Module | Out-String)" -ForegroundColor DarkGreen -BackgroundColor Yellow Context "When we call Build-Module" { $Output = Build-Module $PSScriptRoot\Source1\build.psd1 -Passthru $Module = [IO.Path]::ChangeExtension($Output.Path, "psm1") @@ -13,7 +12,7 @@ Describe "Build-Module With Source1" { $Metadata = Import-Metadata $Output.Path It "Should update FunctionsToExport in the manifest" { - $Metadata.FunctionsToExport | Should -Be @("Get-Finale", "Get-Source") + $Metadata.FunctionsToExport | Should -Be @("Get-Source") } It "Should update AliasesToExport in the manifest" { @@ -25,6 +24,56 @@ Describe "Build-Module With Source1" { } It "Will comment out the original using statements in their original positions" { + (Select-String -Pattern "^#\s*using" -Path $Module).Count | Should -Be 3 + } + } + + Context "Regression test for #55: I can pass SourceDirectories" { + $Output = Build-Module $PSScriptRoot\Source1\build.psd1 -SourceDirectories "Private" -Passthru + $Module = [IO.Path]::ChangeExtension($Output.Path, "psm1") + + It "Should not put the module's DefaultCommandPrefix into the psm1 as code. Duh!" { + $Module | Should -Not -FileContentMatch '^Source$' + } + + $Metadata = Import-Metadata $Output.Path + + It "Should not have any FunctionsToExport if SourceDirectories don't match the PublicFilter" { + $Metadata.FunctionsToExport | Should -Be @() + } + + It "Should de-dupe and move using statements to the top of the file" { + Select-String -Pattern "^using" -Path $Module | ForEach-Object LineNumber | Should -Be 1 + } + + It "Will comment out the original using statement in the original positions" { + (Select-String -Pattern "^#\s*using" -Path $Module).Count | Should -Be 2 + } + } + + Context "Regression test for #55: I can pass SourceDirectories and PublicFilter" { + $Output = Build-Module $PSScriptRoot\Source1\build.psd1 -SourceDirectories "Private" -PublicFilter "P*\*" -Passthru + $Module = [IO.Path]::ChangeExtension($Output.Path, "psm1") + + It "Should not put the module's DefaultCommandPrefix into the psm1 as code. Duh!" { + $Module | Should -Not -FileContentMatch '^Source$' + } + + $Metadata = Import-Metadata $Output.Path + + It "Should not have any FunctionsToExport if SourceDirectories don't match the PublicFilter" { + $Metadata.FunctionsToExport | Should -Be @("GetFinale", "GetPreview") + } + + It "Should update AliasesToExport in the manifest" { + $Metadata.AliasesToExport | Should -Be @("GF", "GP") + } + + It "Should de-dupe and move using statements to the top of the file" { + Select-String -Pattern "^using" -Path $Module | ForEach-Object LineNumber | Should -Be 1 + } + + It "Will comment out the original using statement in the original positions" { (Select-String -Pattern "^#\s*using" -Path $Module).Count | Should -Be 2 } } diff --git a/Tests/Integration/Source1/Public/Get-Finale.ps1 b/Tests/Integration/Source1/Private/GetFinale.ps1 similarity index 61% rename from Tests/Integration/Source1/Public/Get-Finale.ps1 rename to Tests/Integration/Source1/Private/GetFinale.ps1 index f2e2fbf..6c89c2e 100644 --- a/Tests/Integration/Source1/Public/Get-Finale.ps1 +++ b/Tests/Integration/Source1/Private/GetFinale.ps1 @@ -1,7 +1,7 @@ using module ModuleBuilder -function Get-Finale { +function GetFinale { [CmdletBinding()] - [Alias("gs")] + [Alias("gf")] param() } diff --git a/Tests/Integration/Source1/Private/GetPreview.ps1 b/Tests/Integration/Source1/Private/GetPreview.ps1 new file mode 100644 index 0000000..05f6c05 --- /dev/null +++ b/Tests/Integration/Source1/Private/GetPreview.ps1 @@ -0,0 +1,7 @@ +using module ModuleBuilder + +function GetPreview { + [CmdletBinding()] + [Alias("gp")] + param() +} diff --git a/Tests/Integration/build.psd1 b/Tests/Integration/build.psd1 new file mode 100644 index 0000000..c47bdfe --- /dev/null +++ b/Tests/Integration/build.psd1 @@ -0,0 +1,5 @@ +@{ + Path = "Source1\Source1.psd1" + OutputDirectory = "..\Result1" + VersionedOutputDirectory = $true +} From bdef9c71a024f56704c867a604bcbf2ae90ac34b Mon Sep 17 00:00:00 2001 From: Joel Bennett Date: Fri, 2 Aug 2019 00:28:55 -0400 Subject: [PATCH 5/5] Remove -Debug from tests It causes failures in NonInteractive mode --- Tests/Private/ConvertToAst.Tests.ps1 | 39 +++------------------------- 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/Tests/Private/ConvertToAst.Tests.ps1 b/Tests/Private/ConvertToAst.Tests.ps1 index 67ec90f..0715b8f 100644 --- a/Tests/Private/ConvertToAst.Tests.ps1 +++ b/Tests/Private/ConvertToAst.Tests.ps1 @@ -3,7 +3,7 @@ Describe "ConvertToAst" { Context "It returns a ParseResult for file paths" { $ParseResult = InModuleScope ModuleBuilder { - ConvertToAst $PSCommandPath -Debug + ConvertToAst $PSCommandPath } It "Returns a ParseResult object" { @@ -23,7 +23,7 @@ Describe "ConvertToAst" { Context "It parses piped in commands" { $ParseResult = InModuleScope ModuleBuilder { - Get-Command ConvertToAst | ConvertToAst -Debug + Get-Command ConvertToAst | ConvertToAst } It "Returns a ParseResult object with the AST" { @@ -34,7 +34,7 @@ Describe "ConvertToAst" { Context "It parses piped in modules" { $ParseResult = InModuleScope ModuleBuilder { - Get-Module ModuleBuilder | ConvertToAst -Debug + Get-Module ModuleBuilder | ConvertToAst } It "Returns a ParseResult object with the AST" { @@ -42,37 +42,4 @@ Describe "ConvertToAst" { $ParseResult.AST | Should -BeOfType [System.Management.Automation.Language.Ast] } } - -<# - param( - # The script content, or script or module file path to parse - [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] - [Alias("Path", "PSPath", "Definition", "ScriptBlock", "Module")] - $Code - ) - process { - Write-Debug " ENTER: ConvertToAst $Code" - $ParseErrors = $null - $Tokens = $null - if ($Code | Test-Path -ErrorAction SilentlyContinue) { - Write-Debug " Parse Code as Path" - $AST = [System.Management.Automation.Language.Parser]::ParseFile(($Code | Convert-Path), [ref]$Tokens, [ref]$ParseErrors) - } elseif ($Code -is [System.Management.Automation.FunctionInfo]) { - Write-Debug " Parse Code as Function" - $String = "function $($Code.Name) { $($Code.Definition) }" - $AST = [System.Management.Automation.Language.Parser]::ParseInput($String, [ref]$Tokens, [ref]$ParseErrors) - } else { - Write-Debug " Parse Code as String" - $AST = [System.Management.Automation.Language.Parser]::ParseInput([String]$Code, [ref]$Tokens, [ref]$ParseErrors) - } - - Write-Debug " EXIT: ConvertToAst" - [PSCustomObject]@{ - PSTypeName = "PoshCode.ModuleBuilder.ParseResults" - ParseErrors = $ParseErrors - Tokens = $Tokens - AST = $AST - } - } - #> }