From c4e726e1ea6889e01dee66b9fef058e93ad3cc02 Mon Sep 17 00:00:00 2001 From: Patrick Meinecke Date: Wed, 28 Dec 2022 15:59:34 -0500 Subject: [PATCH] Make Set-ScriptExtent not slow When I first wrote this many moons ago I didn't know most things. Like that you can just edit in reverse and side step all positioning issues... This gets rid of the awful "wait for document update" logic and just does it properly. --- .../Commands/Public/Set-ScriptExtent.ps1 | 61 ++++++------------- 1 file changed, 19 insertions(+), 42 deletions(-) diff --git a/module/PowerShellEditorServices/Commands/Public/Set-ScriptExtent.ps1 b/module/PowerShellEditorServices/Commands/Public/Set-ScriptExtent.ps1 index d5bf9dbd1..5f263097f 100644 --- a/module/PowerShellEditorServices/Commands/Public/Set-ScriptExtent.ps1 +++ b/module/PowerShellEditorServices/Commands/Public/Set-ScriptExtent.ps1 @@ -5,27 +5,29 @@ function Set-ScriptExtent { <# .EXTERNALHELP ..\PowerShellEditorServices.Commands-help.xml #> - [CmdletBinding(PositionalBinding=$false, DefaultParameterSetName='__AllParameterSets')] + [CmdletBinding(PositionalBinding = $false, DefaultParameterSetName = '__AllParameterSets')] param( - [Parameter(Position=0, Mandatory)] - [psobject] - $Text, + [Parameter(Position = 0, Mandatory)] + [psobject] $Text, - [Parameter(Mandatory, ParameterSetName='AsString')] + [Parameter(Mandatory, ParameterSetName = 'AsString')] [switch] $AsString, - [Parameter(Mandatory, ParameterSetName='AsArray')] - [switch] - $AsArray, + [Parameter(Mandatory, ParameterSetName = 'AsArray')] + [switch] $AsArray, [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)] - [System.Management.Automation.Language.IScriptExtent] - $Extent = (Find-Ast -AtCursor).Extent + [System.Management.Automation.Language.IScriptExtent] $Extent = (Find-Ast -AtCursor).Extent ) begin { $fileContext = $psEditor.GetEditorContext().CurrentFile - $extentList = [System.Collections.Generic.List[[Microsoft.PowerShell.EditorServices.Extensions.FileScriptExtent, Microsoft.PowerShell.EditorServices]]]::new() + $descendingComparer = [System.Collections.Generic.Comparer[int]]::Create{ + param($x, $y) return $y.CompareTo($x) + } + + $extentList = [System.Collections.Generic.SortedList[int, System.Management.Automation.Language.IScriptExtent]]::new( + $descendingComparer) } process { if ($Extent -isnot [Microsoft.PowerShell.EditorServices.Extensions.FileScriptExtent, Microsoft.PowerShell.EditorServices]) { @@ -34,11 +36,11 @@ function Set-ScriptExtent { $Extent.StartOffset, $Extent.EndOffset) } - $extentList.Add($Extent) + + $extentList.Add($Extent.StartOffset, $Extent) } - # Currently this kills the pipeline because we need to keep track and edit all extents for position tracking. - # TODO: Consider queueing changes in a static property and adding a PassThru switch. end { + $needsIndentFix = $false switch ($PSCmdlet.ParameterSetName) { # Insert text as a single string expression. AsString { @@ -55,41 +57,16 @@ function Set-ScriptExtent { } } - foreach ($aExtent in $extentList) { + foreach ($kvp in $extentList.GetEnumerator()) { + $aExtent = $kvp.Value $aText = $Text if ($needsIndentFix) { - # I'd rather let PSSA handle this when there are more formatting options. $indentOffset = ' ' * ($aExtent.StartColumnNumber - 1) - $aText = $aText -split '\r?\n' ` - -join ([Environment]::NewLine + $indentOffset) + $aText = $aText -split '\r?\n' -join ([Environment]::NewLine + $indentOffset) } - $differenceOffset = $aText.Length - $aExtent.Text.Length - $scriptText = $fileContext.GetText() $fileContext.InsertText($aText, $aExtent) - - $newText = $scriptText.Remove($aExtent.StartOffset, $aExtent.Text.Length).Insert($aExtent.StartOffset, $aText) - - $timeoutLoop = 0 - while ($fileContext.GetText() -ne $newText) { - Start-Sleep -Milliseconds 30 - $timeoutLoop++ - - if ($timeoutLoop -gt 20) { - $PSCmdlet.WriteDebug(('Timed out waiting for change at range {0}, {1}' -f $aExtent.StartOffset, - $aExtent.EndOffset)) - break - } - } - - if ($differenceOffset) { - $extentList.ForEach({ - if ($args[0].StartOffset -ge $aExtent.EndOffset) { - $args[0].AddOffset($differenceOffset) - } - }) - } } } }