Skip to content

Commit

Permalink
🩹 [Patch]: Add function Get-ScriptCommand (#13)
Browse files Browse the repository at this point in the history
## 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
  • Loading branch information
MariusStorhaug authored Jan 30, 2025
1 parent 24982ab commit da0f883
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 0 deletions.
60 changes: 60 additions & 0 deletions src/functions/public/Scripts/Get-ScriptCommand.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
function Get-ScriptCommand {
<#
.SYNOPSIS
Retrieves the commands used within a specified PowerShell script.
.DESCRIPTION
Analyzes a given PowerShell script and extracts all command invocations.
Optionally includes call operators (& and .) in the results.
Returns details such as command name, position, and file reference.
.EXAMPLE
Get-ScriptCommand -Path "C:\Scripts\example.ps1"
Extracts and lists all commands found in the specified PowerShell script.
.EXAMPLE
Get-ScriptCommand -Path "C:\Scripts\example.ps1" -IncludeCallOperators
Extracts all commands, including those executed with call operators (& and .).
#>
[Alias('Get-ScriptCommands')]
[CmdletBinding()]
param (
# The path to the PowerShell script file to be parsed.
[Parameter(Mandatory)]
[ValidateScript({ Test-Path -Path $_ -PathType Leaf })]
[string] $Path,

# Include call operators in the results, i.e. & and .
[Parameter()]
[switch] $IncludeCallOperators
)

# Extract function definitions
$ast = Get-ScriptAST -Path $Path

# Gather CommandAsts
$commandAST = $ast.FindAll({ $args[0] -is [System.Management.Automation.Language.CommandAst] }, $true)

if (-not $IncludeCallOperators) {
$commandAST = $commandAST | Where-Object { $_.InvocationOperator -notin 'Ampersand', 'Dot' }
}

$commandAST | ForEach-Object {
$invocationOperator = switch ($_.InvocationOperator) {
'Ampersand' { '&' }
'Dot' { '.' }
}
$_.CommandElements[0].Extent | ForEach-Object {
[pscustomobject]@{
Name = [string]::IsNullOrEmpty($invocationOperator) ? $_.Text : $invocationOperator
StartLineNumber = $_.StartLineNumber
StartColumnNumber = $_.StartColumnNumber
EndLineNumber = $_.EndLineNumber
EndColumnNumber = $_.EndColumnNumber
File = $_.File
}
}
}
}
29 changes: 29 additions & 0 deletions tests/Module.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,32 @@ Describe 'Functions' {
}
}
}

Describe 'Scripts' {
Context "Function: 'Get-ScriptCommands'" {
It 'Get-ScriptCommands gets the script commands' {
$path = Join-Path $PSScriptRoot 'src\Test-Function.ps1'
$commands = Get-ScriptCommand -Path $path
$commands | Should -Not -BeNullOrEmpty
$commands | Should -BeOfType [pscustomobject]
$commands.Name | Should -Contain 'ForEach-Object'
$commands.Name | Should -Contain 'Get-Process'
$commands.Name | Should -Contain 'ipmo'
$commands.Name | Should -Contain 'Register-ArgumentCompleter'
$commands.Name | Should -Not -Contain '.'
$commands.Name | Should -Not -Contain '&'
}
It 'Get-ScriptCommands gets the script commands with call operators' {
$path = Join-Path $PSScriptRoot 'src\Test-Function.ps1'
$commands = Get-ScriptCommand -Path $path -IncludeCallOperators
$commands | Should -Not -BeNullOrEmpty
$commands | Should -BeOfType [pscustomobject]
$commands.Name | Should -Contain 'ForEach-Object'
$commands.Name | Should -Contain 'Get-Process'
$commands.Name | Should -Contain 'ipmo'
$commands.Name | Should -Contain 'Register-ArgumentCompleter'
$commands.Name | Should -Contain '.'
$commands.Name | Should -Contain '&'
}
}
}
31 changes: 31 additions & 0 deletions tests/src/Test-Function.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,42 @@
#>
[Alias('Test', 'TestFunc')]
[Alias('Test-Func')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
'PSAvoidUsingCmdletAliases', '', Scope = 'Function',
Justification = 'This is a test :)'
)]
[CmdletBinding()]
param (
# Name of the person to greet.
[Parameter(Mandatory)]
[string] $Name
)
Write-Output "Hello, $Name!"

Get-Process | Select-Object -First 5

$hash = @{
'Key1' = 'Value1'
'Key2' = 'Value2'
}

$hash.GetEnumerator() | ForEach-Object {
Write-Output "Key: $($_.Key), Value: $($_.Value)"
}

. Get-Alias | ForEach-Object {
Write-Output "Alias: $($_.Name), Definition: $($_.Definition)"
}

& {
Write-Output 'Hello, World!'
}

ipmo Microsoft.PowerShell.Utility
}

Register-ArgumentCompleter -CommandName Test-Function -ParameterName Name -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters
Get-Process | Where-Object { $_.Name -like "$wordToComplete*" } | Select-Object -ExpandProperty Name
}

0 comments on commit da0f883

Please sign in to comment.