Functions/GenXdev.Coding.PowerShell.Modules/Assert-GenXdevCmdlet.ps1
################################################################################ <# .SYNOPSIS Improves GenXdev cmdlet documentation and implementation through AI assistance. .DESCRIPTION This function enhances GenXdev cmdlets by analyzing and improving their code through AI prompts. It can integrate cmdlets into modules, update documentation, and verify proper implementation. The function supports custom prompt templates and can open files in Visual Studio Code or Visual Studio. .PARAMETER CmdletName The name or search pattern of the cmdlet to improve. Supports wildcards. .PARAMETER BaseModuleName Array of GenXdev module names to search within. Must match pattern "GenXdev.*". .PARAMETER PromptKey The key identifying which AI prompt template to use for improvements. .PARAMETER Prompt Custom prompt text to override the template prompt. .PARAMETER NoLocal Skip searching local module versions. .PARAMETER OnlyPublished Only search published module versions. .PARAMETER FromScripts Search in script files rather than module files. .PARAMETER Code Opens the cmdlet in Visual Studio Code. .PARAMETER VisualStudio Opens the cmdlet in Visual Studio. .PARAMETER EditPrompt Only edit the AI prompt template without processing the cmdlet. .PARAMETER Integrate Integrate the cmdlet into a module if it's currently a standalone script. .EXAMPLE Assert-GenXdevCmdlet -CmdletName "Get-Something" -PromptKey "CheckDocs" -Code .EXAMPLE improvecmdlet Get-Something CheckDocs -c #> function Assert-GenXdevCmdlet { [CmdletBinding()] [Alias("improvecmdlet")] param( ######################################################################## [parameter( Mandatory = $false, Position = 0, ValueFromRemainingArguments = $false, HelpMessage = "Search pattern to filter cmdlets" )] [Alias("Filter", "CmdLet", "Cmd", "FunctionName", "Name")] [SupportsWildcards()] [string] $CmdletName = "*", ######################################################################## [parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = "GenXdev module names to search" )] [ValidateNotNullOrEmpty()] [Alias("Module", "ModuleName")] [ValidatePattern("^(GenXdev|GenXde[v]\*|GenXdev(\.\w+)+)+$")] [string[]] $BaseModuleName = @("GenXdev*"), ######################################################################## [parameter( Mandatory = $false, Position = 1, HelpMessage = "The AI prompt key to use for template selection" )] [ValidateNotNullOrEmpty()] [string] $PromptKey = "CheckAllRequirements", ######################################################################## [parameter( Position = 2, HelpMessage = "Custom AI prompt text to use" )] [AllowEmptyString()] [string] $Prompt = "", ######################################################################## [Parameter( Mandatory = $false, HelpMessage = "Skip local module versions" )] [switch] $NoLocal, ######################################################################## [Parameter( Mandatory = $false, HelpMessage = "Only include published versions" )] [switch] $OnlyPublished, ######################################################################## [Parameter( Mandatory = $false, HelpMessage = "Search in script files" )] [switch] $FromScripts, ######################################################################## [Parameter( Mandatory = $false, HelpMessage = "Open in Visual Studio Code" )] [Alias("c")] [switch] $Code, ######################################################################## [Parameter( Mandatory = $false, HelpMessage = "Open in Visual Studio" )] [Alias("vs")] [switch] $VisualStudio, ######################################################################## [parameter( ParameterSetName = "PromptKey", HelpMessage = "Only edit the AI prompt" )] [switch] $EditPrompt, ######################################################################## [parameter( HelpMessage = "Integrate cmdlet into module" )] [switch] $Integrate ) begin { try { # retrieve and validate target cmdlet existence $invocationParams = GenXdev.Helpers\Copy-IdenticalParamValues ` -FunctionName "GenXdev.Helpers\Get-GenXDevCmdlets" ` -BoundParameters $PSBoundParameters # select first matching cmdlet $cmdlet = GenXdev.Helpers\Get-GenXDevCmdlets @invocationParams | Microsoft.PowerShell.Utility\Select-Object -First 1 # validate cmdlet was found if ($null -eq $cmdlet) { throw [System.ArgumentException]::new( "Could not find GenXdev cmdlet matching filter: $CmdletName") } # initialize core variables $CmdletName = $cmdlet.Name $moduleName = "" Microsoft.PowerShell.Utility\Write-Verbose "Processing cmdlet: $CmdletName" # check if integration is needed based on script location $requiresIntegration = $Integrate -and ($cmdlet.ScriptFilePath.StartsWith( (GenXdev.FileSystem\Expand-Path ( "$PSScriptRoot\..\..\..\..\..\Scripts\")))) # warn if integration not needed if ($Integrate -and -not $requiresIntegration) { Microsoft.PowerShell.Utility\Write-Warning ("Cmdlet already integrated into module. " + "Integration step will be skipped.") $Integrate = $false } Microsoft.PowerShell.Utility\Write-Verbose "Integration required: $requiresIntegration" # handle module integration if requested if ($Integrate) { # get full official cmdlet name $CmdletName = [IO.Path]::GetFileNameWithoutExtension(($cmdlet.Name)) # integrate the cmdlet into a module $options = [System.Management.Automation.Host.ChoiceDescription[]] @( . GenXdev.Helpers\Invoke-OnEachGenXdevModule { Microsoft.PowerShell.Management\Get-ChildItem *.psm1 | Microsoft.PowerShell.Core\ForEach-Object { [IO.Path]::GetFileNameWithoutExtension($_) } } ) $selected = @($options | Microsoft.PowerShell.Utility\Out-GridView -Title "Select a module" -PassThru) if ($null -eq $selected) { throw "No module selected" } if ($selected.Count -ne 1) { throw "You should only select a single module" } # move the script file to the module $baseDestinationParts = "$($($selected)[0].Label)".Split("."); $baseDestinationModule = $baseDestinationParts[0] + "." + $baseDestinationParts[1]; $ModuleName = "$($($selected)[0].Label)" $destination = GenXdev.FileSystem\Expand-Path "$PSScriptRoot\..\..\..\..\..\Modules\$baseDestinationModule\1.160.2025\Functions\$ModuleName\$CmdletName.ps1" -CreateDirectory # move the script file GenXdev.FileSystem\Move-ItemWithTracking -Path $cmdlet.ScriptFilePath -Destination $destination [IO.File]::WriteAllText( $destination, ( "function $CmdletName {`r`n" + (GenXdev.Helpers\alignScript -script ( [IO.File]::ReadAllText($destination).Replace( "`$PSScriptRoot\..", "`$PSScriptRoot\..\..\..\..\.." ).Replace( "$($CmdletName).ps1", "$($CmdletName)" ) + "`r`n}" ) -spaces 4) ) ); # also move the test script file if it exists if ([IO.Path]::Exists($cmdlet.ScriptTestFilePath)) { GenXdev.FileSystem\Move-ItemWithTracking -Path $cmdlet.ScriptTestFilePath -Destination ([IO.Path]::ChangeExtension($destination, ".Tests.ps1")) -Force } # add dot source reference to corresponding psm1 file GenXdev.Coding\SplitUpPsm1File -Path "$PSScriptRoot\..\..\..\..\..\Modules\$baseDestinationModule\1.160.2025\$ModuleName.psm1" . GenXdev.Helpers\Invoke-OnEachGenXdevModule { Microsoft.PowerShell.Management\Get-ChildItem ".\*.ps1" -File -Recurse | Microsoft.PowerShell.Core\ForEach-Object { [IO.File]::WriteAllText( $PSItem.FullName, [IO.File]::ReadAllText(($PSItem.FullName)).Replace( "$($CmdletName).ps1", "$($CmdletName)" ) ) } } # retrieve information about the target cmdlet $cmdlet = GenXdev.Helpers\Get-GenXDevCmdlets -CmdletName $CmdletName # retrieve and validate the target cmdlet exists $invocationParams = GenXdev.Helpers\Copy-IdenticalParamValues ` -FunctionName "GenXdev.Helpers\Get-GenXDevCmdlets" ` -BoundParameters $PSBoundParameters $invocationParams.CmdletName = $CmdletName $invocationParams.BaseModuleName = $($ModuleName) $cmdlet = GenXdev.Helpers\Get-GenXDevCmdlets @invocationParams | Microsoft.PowerShell.Utility\Select-Object -First 1 if ($null -eq $cmdlet) { throw "Could not find GenXdev cmdlet $CmdletName" } } # process prompt template if specified if (-not [string]::IsNullOrWhiteSpace($PromptKey)) { # determine template path based on location $promptFilePath = GenXdev.FileSystem\Expand-Path -CreateFile -FilePath ( "$PSScriptRoot\..\..\Prompts\GenXdev.Coding.PowerShell.Modules\" + "Assert-$PromptKey.txt") # check for script-specific template $scriptsPath = GenXdev.FileSystem\Expand-Path "$PSScriptRoot\..\..\..\..\..\Scripts\" ` -CreateDirectory if ($cmdlet.ScriptFilePath -like "$scriptsPath\*.ps1") { $promptFilePath = GenXdev.FileSystem\Expand-Path -CreateFile -FilePath ( "$PSScriptRoot\..\..\Prompts\GenXdev.Coding.PowerShell." + "Modules\Assert-$PromptKey-script.txt") } # load and process template $Prompt = [System.IO.File]::ReadAllText($promptFilePath).Replace( "`$Prompt", $Prompt ) } # replace template variables in prompt text $Prompt = $Prompt.Replace("`$CmdletName", $cmdlet.Name) $Prompt = $Prompt.Replace("`$CmdLetNoTestName", $cmdlet.Name) $Prompt = $Prompt.Replace( "`$FullModuleName", $cmdlet.ModuleName ) $Prompt = $Prompt.Replace( "`$BaseModuleName", [string]::Join(".", ($cmdlet.ModuleName.Split(".") | Microsoft.PowerShell.Utility\Select-Object -First 2 -ErrorAction SilentlyContinue)) ) $Prompt = $Prompt.Replace( "`$ScriptFileName", [System.IO.Path]::GetFileName($cmdlet.ScriptFilePath) ) $Prompt = $Prompt.Replace("`t", " ") # copy final prompt to clipboard for use $previousClipboard = Microsoft.PowerShell.Management\Get-Clipboard $Prompt | Microsoft.PowerShell.Management\Set-Clipboard Microsoft.PowerShell.Utility\Write-Verbose "Prepared prompt and copied to clipboard:" Microsoft.PowerShell.Utility\Write-Verbose $Prompt } catch { Microsoft.PowerShell.Utility\Write-Error -Exception $_.Exception ` -Message "Failed to initialize Assert-GenXdevCmdlet" throw } } process { try { # handle prompt editing if requested if ($EditPrompt) { p -c code $promptFilePath return } # open cmdlet in vscode and insert prompt $invocationParams = GenXdev.Helpers\Copy-IdenticalParamValues ` -FunctionName "GenXdev.Coding\Show-GenXdevCmdLetInIde" ` -BoundParameters $PSBoundParameters $invocationParams.CmdletName = $CmdletName $invocationParams.KeysToSend = @( "^``", "^+i", "^l", "^a", "{DELETE}", "^+i", "{ESCAPE}", "^{F12}", "^v", "{ENTER}", "^{ENTER}" ) GenXdev.Coding\Show-GenXdevCmdLetInIde @invocationParams Microsoft.PowerShell.Utility\Start-Sleep 4; # handle unit test scenarios based on test file existence if ([IO.File]::Exists($cmdlet.ScriptTestFilePath)) { switch ($host.ui.PromptForChoice( "Make a choice", "What to do next?", @("&Stop", "&Run unit-tests for $CmdletName", "Redo &Last"), 0)) { 0 { throw "Stopped" } 1 { return GenXdev.Coding\Assert-GenXdevUnitTest -CmdletName $CmdletName -DebugFailedTests } 2 { return GenXdev.Coding\Assert-GenXdevCmdlet @PSBoundParameters } } } else { switch ($host.ui.PromptForChoice( "Make a choice", "What to do next?", @("&Stop", "&Create unit tests for $CmdletName", "Redo &Last"), 0)) { 0 { throw "Stopped" } 1 { return GenXdev.Coding\Assert-GenXdevCmdletTests -CmdletName $CmdletName } 2 { return GenXdev.Coding\Assert-GenXdevCmdlet @PSBoundParameters } } } } catch { Microsoft.PowerShell.Utility\Write-Error -Exception $_.Exception -Message "Failed to process cmdlet improvements" throw } } end { # restore original clipboard content $null = Microsoft.PowerShell.Management\Set-Clipboard -Value $previousClipboard } } ################################################################################ |