Skip to content

Commit da0f883

Browse files
🩹 [Patch]: Add function Get-ScriptCommand (#13)
## Description This pull request introduces a new function `Get-ScriptCommand` to the PowerShell script and adds corresponding tests to ensure its functionality. The new function analyzes a specified PowerShell script to extract command invocations and optionally includes call operators. ### New Functionality: * [`src/functions/public/Scripts/Get-ScriptCommands.ps1`](diffhunk://#diff-c59ca712a6ccbcb05a5ae179a1d551bc55f9835feb3f4d73dad9e261e3d579b9R1-R56): Added a new function `Get-ScriptCommand` that retrieves commands used within a specified PowerShell script, including details such as command name, position, and file reference. It also provides an option to include call operators in the results. ### Tests: * [`tests/Module.Tests.ps1`](diffhunk://#diff-a94f0e90abaaff044e3cb0327ce3a63a10cd61551269a414e4dc40ad2af8a951R45-R56): Added a new test context for the `Get-ScriptCommands` function to verify that it retrieves script commands correctly, ensuring the results are not null or empty, are of the correct type, and contain expected command names. ## 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 24982ab commit da0f883

3 files changed

Lines changed: 120 additions & 0 deletions

File tree

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
function Get-ScriptCommand {
2+
<#
3+
.SYNOPSIS
4+
Retrieves the commands used within a specified PowerShell script.
5+
6+
.DESCRIPTION
7+
Analyzes a given PowerShell script and extracts all command invocations.
8+
Optionally includes call operators (& and .) in the results.
9+
Returns details such as command name, position, and file reference.
10+
11+
.EXAMPLE
12+
Get-ScriptCommand -Path "C:\Scripts\example.ps1"
13+
14+
Extracts and lists all commands found in the specified PowerShell script.
15+
16+
.EXAMPLE
17+
Get-ScriptCommand -Path "C:\Scripts\example.ps1" -IncludeCallOperators
18+
19+
Extracts all commands, including those executed with call operators (& and .).
20+
#>
21+
[Alias('Get-ScriptCommands')]
22+
[CmdletBinding()]
23+
param (
24+
# The path to the PowerShell script file to be parsed.
25+
[Parameter(Mandatory)]
26+
[ValidateScript({ Test-Path -Path $_ -PathType Leaf })]
27+
[string] $Path,
28+
29+
# Include call operators in the results, i.e. & and .
30+
[Parameter()]
31+
[switch] $IncludeCallOperators
32+
)
33+
34+
# Extract function definitions
35+
$ast = Get-ScriptAST -Path $Path
36+
37+
# Gather CommandAsts
38+
$commandAST = $ast.FindAll({ $args[0] -is [System.Management.Automation.Language.CommandAst] }, $true)
39+
40+
if (-not $IncludeCallOperators) {
41+
$commandAST = $commandAST | Where-Object { $_.InvocationOperator -notin 'Ampersand', 'Dot' }
42+
}
43+
44+
$commandAST | ForEach-Object {
45+
$invocationOperator = switch ($_.InvocationOperator) {
46+
'Ampersand' { '&' }
47+
'Dot' { '.' }
48+
}
49+
$_.CommandElements[0].Extent | ForEach-Object {
50+
[pscustomobject]@{
51+
Name = [string]::IsNullOrEmpty($invocationOperator) ? $_.Text : $invocationOperator
52+
StartLineNumber = $_.StartLineNumber
53+
StartColumnNumber = $_.StartColumnNumber
54+
EndLineNumber = $_.EndLineNumber
55+
EndColumnNumber = $_.EndColumnNumber
56+
File = $_.File
57+
}
58+
}
59+
}
60+
}

tests/Module.Tests.ps1

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,32 @@ Describe 'Functions' {
4242
}
4343
}
4444
}
45+
46+
Describe 'Scripts' {
47+
Context "Function: 'Get-ScriptCommands'" {
48+
It 'Get-ScriptCommands gets the script commands' {
49+
$path = Join-Path $PSScriptRoot 'src\Test-Function.ps1'
50+
$commands = Get-ScriptCommand -Path $path
51+
$commands | Should -Not -BeNullOrEmpty
52+
$commands | Should -BeOfType [pscustomobject]
53+
$commands.Name | Should -Contain 'ForEach-Object'
54+
$commands.Name | Should -Contain 'Get-Process'
55+
$commands.Name | Should -Contain 'ipmo'
56+
$commands.Name | Should -Contain 'Register-ArgumentCompleter'
57+
$commands.Name | Should -Not -Contain '.'
58+
$commands.Name | Should -Not -Contain '&'
59+
}
60+
It 'Get-ScriptCommands gets the script commands with call operators' {
61+
$path = Join-Path $PSScriptRoot 'src\Test-Function.ps1'
62+
$commands = Get-ScriptCommand -Path $path -IncludeCallOperators
63+
$commands | Should -Not -BeNullOrEmpty
64+
$commands | Should -BeOfType [pscustomobject]
65+
$commands.Name | Should -Contain 'ForEach-Object'
66+
$commands.Name | Should -Contain 'Get-Process'
67+
$commands.Name | Should -Contain 'ipmo'
68+
$commands.Name | Should -Contain 'Register-ArgumentCompleter'
69+
$commands.Name | Should -Contain '.'
70+
$commands.Name | Should -Contain '&'
71+
}
72+
}
73+
}

tests/src/Test-Function.ps1

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,42 @@
1010
#>
1111
[Alias('Test', 'TestFunc')]
1212
[Alias('Test-Func')]
13+
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
14+
'PSAvoidUsingCmdletAliases', '', Scope = 'Function',
15+
Justification = 'This is a test :)'
16+
)]
1317
[CmdletBinding()]
1418
param (
1519
# Name of the person to greet.
1620
[Parameter(Mandatory)]
1721
[string] $Name
1822
)
1923
Write-Output "Hello, $Name!"
24+
25+
Get-Process | Select-Object -First 5
26+
27+
$hash = @{
28+
'Key1' = 'Value1'
29+
'Key2' = 'Value2'
30+
}
31+
32+
$hash.GetEnumerator() | ForEach-Object {
33+
Write-Output "Key: $($_.Key), Value: $($_.Value)"
34+
}
35+
36+
. Get-Alias | ForEach-Object {
37+
Write-Output "Alias: $($_.Name), Definition: $($_.Definition)"
38+
}
39+
40+
& {
41+
Write-Output 'Hello, World!'
42+
}
43+
44+
ipmo Microsoft.PowerShell.Utility
45+
}
46+
47+
Register-ArgumentCompleter -CommandName Test-Function -ParameterName Name -ScriptBlock {
48+
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
49+
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters
50+
Get-Process | Where-Object { $_.Name -like "$wordToComplete*" } | Select-Object -ExpandProperty Name
2051
}

0 commit comments

Comments
 (0)