Skip to content

Commit 24982ab

Browse files
🩹 [Patch]: Add Get-ScriptAST, -FunctionAST and FunctionType (#12)
## Description This pull request includes several new functions and refactors existing ones to improve the handling and extraction of function definitions from PowerShell scripts using the Abstract Syntax Tree (AST). The most important changes include the addition of new functions `Get-FunctionAST`, `Get-ScriptAST`, and `Get-FunctionType`, as well as the refactoring of existing functions to utilize these new utilities. ### New Functions: * [`src/functions/public/Core/Get-FunctionAST.ps1`](diffhunk://#diff-ebd4e1ad30387639d36d84e6a48c5b48cb76c42514fa21253a16d440b7cb4021R1-R43): Added a new function `Get-FunctionAST` to retrieve the AST of function definitions from a specified PowerShell script. This function allows filtering by function name and provides detailed documentation and examples. * [`src/functions/public/Core/Get-ScriptAST.ps1`](diffhunk://#diff-dfd1b919296a66069c792bbb32868f85ab37b6952f7646b18ba660edfb779a28R1-R71): Added a new function `Get-ScriptAST` to parse a PowerShell script from a file or string input and return its AST. This function also supports capturing tokens and errors. * [`src/functions/public/Functions/Get-FunctionType.ps1`](diffhunk://#diff-4c982e7ebeb1e1b4552abb41872c1ca4dd2126b8b5cde5ed026f5ceb668fd366R1-R45): Added a new function `Get-FunctionType` to extract function types from a specified PowerShell script using the AST. This function provides detailed documentation and examples. ### Refactored Functions: * [`src/functions/public/Functions/Get-FunctionAlias.ps1`](diffhunk://#diff-e26de7cad073f2ba65d1125962f4c71c7b929e02acea0c4b39d158a34cd3cf57R28-R33): Refactored to use the new `Get-FunctionAST` function for extracting function definitions from the script file. This change simplifies the code and improves maintainability. * [`src/functions/public/Functions/Get-FunctionName.ps1`](diffhunk://#diff-5db9010fc5dab3435eb93a1af8edabf08660687f56a1f9fb96c2c2e3c54f9c18R24-R29): Refactored to use the new `Get-FunctionAST` function for extracting function definitions from the script file. This change simplifies the code and improves maintainability. ## Type of change <!-- Use the check-boxes [x] on the options that are relevant. --> - [ ] 📖 [Docs] - [ ] 🪲 [Fix] - [x] 🩹 [Patch] - [ ] ⚠️ [Security fix] - [ ] 🚀 [Feature] - [ ] 🌟 [Breaking change] ## Checklist <!-- Use the check-boxes [x] on the options that are relevant. --> - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas
1 parent ef82e50 commit 24982ab

6 files changed

Lines changed: 190 additions & 9 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
function Get-FunctionAST {
2+
<#
3+
.SYNOPSIS
4+
Retrieves the abstract syntax tree (AST) of function definitions from a PowerShell script.
5+
6+
.DESCRIPTION
7+
Parses a specified PowerShell script file and extracts function definitions matching the given name.
8+
By default, it returns all function definitions if no specific name is provided.
9+
10+
.EXAMPLE
11+
Get-FunctionAST -Path "C:\Scripts\MyScript.ps1"
12+
13+
Retrieves all function definitions from "MyScript.ps1".
14+
15+
.EXAMPLE
16+
Get-FunctionAST -Name "Get-Data" -Path "C:\Scripts\MyScript.ps1"
17+
18+
Retrieves only the function definition named "Get-Data" from "MyScript.ps1".
19+
#>
20+
[CmdletBinding()]
21+
param (
22+
# The name of the function to search for. Defaults to all functions ('*').
23+
[Parameter()]
24+
[string] $Name = '*',
25+
26+
# The path to the PowerShell script file to be parsed.
27+
[Parameter(Mandatory)]
28+
[ValidateScript({ Test-Path -Path $_ -PathType Leaf })]
29+
[string] $Path
30+
)
31+
32+
begin {}
33+
34+
process {
35+
# Parse the script file into an AST
36+
$ast = Get-ScriptAST -Path $Path
37+
38+
# Extract function definitions
39+
$ast.FindAll({ $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }, $true) | Where-Object { $_.Name -like $Name }
40+
}
41+
42+
end {}
43+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
function Get-ScriptAST {
2+
<#
3+
.SYNOPSIS
4+
Parses a PowerShell script or script file and returns its Abstract Syntax Tree (AST).
5+
6+
.DESCRIPTION
7+
This function parses a PowerShell script from a file or a string input and returns its AST.
8+
It can optionally provide token and error information.
9+
10+
.EXAMPLE
11+
Get-ScriptAST -Path "C:\Scripts\MyScript.ps1"
12+
13+
Parses the PowerShell script at "MyScript.ps1" and returns its AST.
14+
15+
.EXAMPLE
16+
Get-ScriptAST -Script "Get-Process | Select-Object Name"
17+
18+
Parses the provided PowerShell script string and returns its AST.
19+
20+
.EXAMPLE
21+
Get-ScriptAST -Path "C:\Scripts\MyScript.ps1" -Tokens ([ref]$tokens) -Errors ([ref]$errors)
22+
23+
Parses the script file while also capturing tokens and errors.
24+
#>
25+
[outputType([System.Management.Automation.Language.ScriptBlockAst])]
26+
[CmdletBinding()]
27+
param (
28+
# The path to the PowerShell script file to be parsed.
29+
[Parameter(
30+
Mandatory,
31+
ValueFromPipeline,
32+
ValueFromPipelineByPropertyName,
33+
ParameterSetName = 'Path'
34+
)]
35+
# Validate using Test-Path
36+
[ValidateScript({ Test-Path -Path $_ -PathType Leaf })]
37+
[string] $Path,
38+
39+
# The PowerShell script to be parsed.
40+
[Parameter(
41+
Mandatory,
42+
ValueFromPipeline,
43+
ValueFromPipelineByPropertyName,
44+
ParameterSetName = 'Script'
45+
)]
46+
[string] $Script,
47+
48+
# Reference variable to store parsed tokens.
49+
[Parameter()]
50+
[ref] $Tokens,
51+
52+
# Reference variable to store parsing errors.
53+
[Parameter()]
54+
[ref] $Errors
55+
)
56+
57+
begin {}
58+
59+
process {
60+
switch ($PSCmdlet.ParameterSetName) {
61+
'Path' {
62+
[System.Management.Automation.Language.Parser]::ParseFile($Path, [ref]$Tokens, [ref]$Errors)
63+
}
64+
'Script' {
65+
[System.Management.Automation.Language.Parser]::ParseInput($Script, [ref]$Tokens, [ref]$Errors)
66+
}
67+
}
68+
}
69+
70+
end {}
71+
}

src/functions/public/Get-FunctionAlias.ps1 renamed to src/functions/public/Functions/Get-FunctionAlias.ps1

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,12 @@
2525

2626
# The path to the PowerShell script file to be parsed.
2727
[Parameter(Mandatory)]
28+
[ValidateScript({ Test-Path -Path $_ -PathType Leaf })]
2829
[string] $Path
2930
)
3031

31-
# Parse the script file into an AST
32-
$ast = [System.Management.Automation.Language.Parser]::ParseFile($Path, [ref]$null, [ref]$null)
33-
3432
# Extract function definitions
35-
$functions = $ast.FindAll({ $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }, $true)
33+
$functions = Get-FunctionAST -Path $Path
3634

3735
# Process each function and extract aliases
3836
$functions | ForEach-Object {

src/functions/public/Get-FunctionName.ps1 renamed to src/functions/public/Functions/Get-FunctionName.ps1

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,12 @@
2121
param (
2222
# The path to the script file to parse
2323
[Parameter(Mandatory)]
24+
[ValidateScript({ Test-Path -Path $_ -PathType Leaf })]
2425
[string] $Path
2526
)
2627

27-
# Parse the script file into an AST
28-
$ast = [System.Management.Automation.Language.Parser]::ParseFile($Path, [ref]$null, [ref]$null)
29-
3028
# Extract function definitions
31-
$functions = $ast.FindAll({ $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }, $true)
29+
$functions = Get-FunctionAST -Path $Path
3230

3331
# Process each function and extract the name
3432
$functions | ForEach-Object {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
function Get-FunctionType {
2+
<#
3+
.SYNOPSIS
4+
Extracts function types from a specified PowerShell script.
5+
6+
.DESCRIPTION
7+
Parses the given PowerShell script file and retrieves all function types
8+
defined within it. This function utilizes the PowerShell Abstract Syntax Tree (AST)
9+
to analyze the script and extract function definitions.
10+
11+
.EXAMPLE
12+
Get-FunctionType -Path "C:\Scripts\MyScript.ps1"
13+
14+
Retrieves all function types defined in the specified script file.
15+
#>
16+
[OutputType([pscustomobject])]
17+
[CmdletBinding()]
18+
param(
19+
# The path to the PowerShell script file to be parsed.
20+
[Parameter(
21+
Mandatory,
22+
ValueFromPipeline,
23+
ValueFromPipelineByPropertyName,
24+
ParameterSetName = 'Path'
25+
)]
26+
[ValidateScript({ Test-Path -Path $_ -PathType Leaf })]
27+
[string] $Path
28+
)
29+
30+
begin {}
31+
32+
process {
33+
$functionAST = Get-FunctionAST -Path $Path
34+
35+
$functionAST | ForEach-Object {
36+
$type = $_.IsFilter ? 'Filter' : $_.IsWorkflow ? 'Workflow' : $_.IsConfiguration ? 'Configuration' : 'Function'
37+
[pscustomobject]@{
38+
Name = $_.Name
39+
Type = $type
40+
}
41+
}
42+
}
43+
44+
end {}
45+
}

tests/Module.Tests.ps1

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,30 @@
1-
Describe 'Module' {
1+
Describe 'Core' {
2+
Context "Function: 'Get-ScriptAST'" {
3+
It 'Get-ScriptAST gets the script AST' {
4+
$path = Join-Path $PSScriptRoot 'src\Test-Function.ps1'
5+
$ast = Get-ScriptAST -Path $path
6+
$ast | Should -Not -BeNullOrEmpty
7+
$ast | Should -BeOfType [System.Management.Automation.Language.ScriptBlockAst]
8+
}
9+
}
10+
Context "Function: 'Get-FunctionAST'" {
11+
It 'Get-FunctionAST gets the function AST' {
12+
$path = Join-Path $PSScriptRoot 'src\Test-Function.ps1'
13+
$ast = Get-FunctionAST -Path $path
14+
$ast | Should -Not -BeNullOrEmpty
15+
$ast | Should -BeOfType [System.Management.Automation.Language.FunctionDefinitionAst]
16+
}
17+
}
18+
}
19+
20+
Describe 'Functions' {
21+
Context "Function: 'Get-FunctionType'" {
22+
It 'Get-FunctionAlias gets the function alias' {
23+
$path = Join-Path $PSScriptRoot 'src\Test-Function.ps1'
24+
$functionType = Get-FunctionType -Path $path
25+
$functionType.Type | Should -Be 'Function'
26+
}
27+
}
228
Context "Function: 'Get-FunctionName'" {
329
It 'Get-FunctionName gets the function name' {
430
$path = Join-Path $PSScriptRoot 'src\Test-Function.ps1'

0 commit comments

Comments
 (0)