Skip to content

Make Set-ScriptExtent not slow #1981

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it intentional that $AsString, is still kept on its own line here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah not intentional, just missed it


[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()
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before this point is all style fixes

$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]) {
Expand All @@ -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.
Comment on lines -39 to -40
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't kill the pipeline, it just stops streaming behavior. Doesn't really need a comment.

Also the TODO doesn't make any sense

end {
$needsIndentFix = $false
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defensively assigning to avoid potentially getting a variable with the same name from a parent scope

switch ($PSCmdlet.ParameterSetName) {
# Insert text as a single string expression.
AsString {
Expand All @@ -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)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just formatting. The rest of this should probably be revisited at some point as well, but not actively bad afaik

}
$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)
}
})
}
}
}
}