src/public/Format-ScriptExpandTypeAccelerators.ps1
function Format-ScriptExpandTypeAccelerators { <# .SYNOPSIS Converts shorthand type accelerators to their full name. .DESCRIPTION Converts shorthand type accelerators to their full name. .PARAMETER Code Multi-line or piped lines of code to process. .PARAMETER AllTypes Include system type accelerators. .PARAMETER SkipPostProcessingValidityCheck After modifications have been made a check will be performed that the code has no errors. Use this switch to bypass this check (This is not recommended!) .EXAMPLE PS > $testfile = 'C:\temp\test.ps1' PS > $test = Get-Content $testfile -raw PS > $test | Format-ScriptExpandTypeAccelerators -AllTypes | clip Description ----------- Takes C:\temp\test.ps1 as input, converts all type accelerators to their full name and places the result in the clipboard to be pasted elsewhere for review. .NOTES Author: Zachary Loeber Site: http://www.the-little-things.net/ Requires: Powershell 3.0 Version History 1.0.0 - Initial release #> [CmdletBinding()] param ( [parameter(Position = 0, Mandatory = $true, ValueFromPipeline=$true, HelpMessage='Lines of code to to process.')] [AllowEmptyString()] [string[]]$Code, [parameter(Position = 1, HelpMessage='Expand all type accelerators to make your code look really complex!')] [switch]$AllTypes, [parameter(Position = 2, HelpMessage='Bypass code validity check after modifications have been made.')] [switch]$SkipPostProcessingValidityCheck ) begin { # Pull in all the caller verbose,debug,info,warn and other preferences if ($script:ThisModuleLoaded -eq $true) { Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState } $FunctionName = $MyInvocation.MyCommand.Name Write-Verbose "$($FunctionName): Begin." # Get all of our accelerator objects $accelerators = [PSObject].Assembly.GetType('System.Management.Automation.TypeAccelerators') # All accelerators returned to a hash $accelhash = $accelerators::get # Now filter all the accelerators we will be expanding. $usedhash = @{} $usedarray = @() $accelhash.Keys | Foreach { if ($AllTypes) { # Get all the accelerator types $usedhash.$_ = $accelhash[$_].FullName $usedarray += $_ } # Get just the non-system accelerators elseif ($accelhash[$_].FullName -notlike "System.*") { $usedhash.$_ = $accelhash[$_].FullName $usedarray += $_ } } $Codeblock = @() $CurrentLevel = 0 $ParseError = $null $Tokens = $null $Indent = (' ' * $Depth) } process { $Codeblock += $Code } end { $ScriptText = $Codeblock | Out-String $AST = [System.Management.Automation.Language.Parser]::ParseInput($ScriptText, [ref]$Tokens, [ref]$ParseError) if($ParseError) { $ParseError | Write-Error throw "$($FunctionName): The parser will not work properly with errors in the script, please modify based on the above errors and retry." } for($t = $Tokens.Count - 2; $t -ge 1; $t--) { $Token = $Tokens[$t] $NextToken = $Tokens[$t-1] if (($token.Kind -match 'identifier') -and ($token.TokenFlags -match 'TypeName')) { if ($usedarray -contains $Token.Text) { $replaceval = $usedhash[$Token.Text] Write-Verbose "$($FunctionName):....Updating to $($replaceval)" $RemoveStart = ($Token.Extent).StartOffset $RemoveEnd = ($Token.Extent).EndOffset - $RemoveStart $ScriptText = $ScriptText.Remove($RemoveStart,$RemoveEnd).Insert($RemoveStart,$replaceval) } } } # Validate our returned code doesn't have any unintentionally introduced parsing errors. if (-not $SkipPostProcessingValidityCheck) { if (-not (Format-ScriptTestCodeBlock -Code $ScriptText)) { throw "$($FunctionName): Modifications made to the scriptblock resulted in code with parsing errors!" } } $ScriptText Write-Verbose "$($FunctionName): End." } } |