Skip to content

Commit bff3b49

Browse files
Merge pull request #1814 from SeeminglyScience/fix-convertto-scriptextent
Fix error when piping `IFilePosition` to `ConvertTo-ScriptExtent`
2 parents 3e0ca95 + ec01a45 commit bff3b49

File tree

3 files changed

+87
-54
lines changed

3 files changed

+87
-54
lines changed

module/PowerShellEditorServices/Commands/Public/ConvertTo-ScriptExtent.ps1

+55-48
Original file line numberDiff line numberDiff line change
@@ -8,77 +8,63 @@ function ConvertTo-ScriptExtent {
88
[CmdletBinding()]
99
[OutputType([System.Management.Automation.Language.IScriptExtent])]
1010
param(
11-
[Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName='ByOffset')]
11+
[Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName = 'ByOffset')]
1212
[Alias('StartOffset', 'Offset')]
13-
[int]
14-
$StartOffsetNumber,
13+
[int] $StartOffsetNumber,
1514

16-
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName='ByOffset')]
15+
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'ByOffset')]
1716
[Alias('EndOffset')]
18-
[int]
19-
$EndOffsetNumber,
17+
[int] $EndOffsetNumber,
2018

21-
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName='ByPosition')]
19+
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'ByPosition')]
2220
[Alias('StartLine', 'Line')]
23-
[int]
24-
$StartLineNumber,
21+
[int] $StartLineNumber,
2522

26-
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName='ByPosition')]
23+
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'ByPosition')]
2724
[Alias('StartColumn', 'Column')]
28-
[int]
29-
$StartColumnNumber,
25+
[int] $StartColumnNumber,
3026

31-
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName='ByPosition')]
27+
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'ByPosition')]
3228
[Alias('EndLine')]
33-
[int]
34-
$EndLineNumber,
29+
[int] $EndLineNumber,
3530

36-
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName='ByPosition')]
31+
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'ByPosition')]
3732
[Alias('EndColumn')]
38-
[int]
39-
$EndColumnNumber,
33+
[int] $EndColumnNumber,
4034

41-
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName='ByPosition')]
42-
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName='ByOffset')]
43-
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName='ByBuffer')]
35+
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'ByPosition')]
36+
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'ByOffset')]
37+
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'ByBuffer')]
4438
[Alias('File', 'FileName')]
45-
[string]
46-
$FilePath = $psEditor.GetEditorContext().CurrentFile.Path,
39+
[string] $FilePath = $psEditor.GetEditorContext().CurrentFile.Path,
4740

48-
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName='ByBuffer')]
41+
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'ByBuffer')]
4942
[Alias('Start')]
50-
[Microsoft.PowerShell.EditorServices.Extensions.IFilePosition, Microsoft.PowerShell.EditorServices]
51-
$StartBuffer,
43+
[Microsoft.PowerShell.EditorServices.Extensions.IFilePosition, Microsoft.PowerShell.EditorServices] $StartBuffer,
5244

53-
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName='ByBuffer')]
45+
[Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'ByBuffer')]
5446
[Alias('End')]
55-
[Microsoft.PowerShell.EditorServices.Extensions.IFilePosition, Microsoft.PowerShell.EditorServices]
56-
$EndBuffer,
57-
58-
[Parameter(Mandatory,
59-
ValueFromPipeline,
60-
ValueFromPipelineByPropertyName,
61-
ParameterSetName='ByExtent')]
62-
[System.Management.Automation.Language.IScriptExtent]
63-
$Extent
47+
[Microsoft.PowerShell.EditorServices.Extensions.IFilePosition, Microsoft.PowerShell.EditorServices] $EndBuffer,
48+
49+
[Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'ByExtent')]
50+
[System.Management.Automation.Language.IScriptExtent] $Extent
6451
)
6552
begin {
6653
$fileContext = $psEditor.GetEditorContext().CurrentFile
6754
$emptyExtent = [Microsoft.PowerShell.EditorServices.Extensions.FileScriptExtent, Microsoft.PowerShell.EditorServices]::Empty
6855
}
69-
7056
process {
7157
# Already a InternalScriptExtent, FileScriptExtent or is empty.
7258
$returnAsIs = $Extent -and
73-
(0 -ne $Extent.StartOffset -or
74-
0 -ne $Extent.EndOffset -or
75-
$Extent -eq $emptyExtent)
59+
($Extent.StartOffset -or $Extent.EndOffset -or $Extent -eq $emptyExtent)
7660

77-
if ($returnAsIs) { return $Extent }
61+
if ($returnAsIs) {
62+
return $Extent
63+
}
7864

7965
if ($StartOffsetNumber) {
8066
$startOffset = $StartOffsetNumber
81-
$endOffset = $EndOffsetNumber
67+
$endOffset = $EndOffsetNumber
8268

8369
# Allow creating a single position extent with just the offset parameter.
8470
if (-not $EndOffsetNumber) {
@@ -92,8 +78,7 @@ function ConvertTo-ScriptExtent {
9278
}
9379

9480
if ($StartBuffer) {
95-
if (-not $EndBuffer)
96-
{
81+
if (-not $EndBuffer) {
9782
$EndBuffer = $StartBuffer
9883
}
9984

@@ -105,12 +90,34 @@ function ConvertTo-ScriptExtent {
10590
$EndBuffer.Column)
10691
}
10792

108-
if (-not $StartColumnNumber) { $StartColumnNumber = 1 }
109-
if (-not $StartLineNumber) { $StartLineNumber = 1 }
110-
if (-not $EndLineNumber) { $EndLineNumber = 1 }
111-
if (-not $EndColumnNumber) { $EndColumnNumber = 1 }
93+
# Allow piping a single line and column to get a zero length script extent.
94+
if ($PSBoundParameters.ContainsKey('StartColumnNumber') -and -not $PSBoundParameters.ContainsKey('EndColumnNumber')) {
95+
$EndColumnNumber = $StartColumnNumber
96+
}
97+
98+
if ($PSBoundParameters.ContainsKey('StartLineNumber') -and -not $PSBoundParameters.ContainsKey('EndLineNumber')) {
99+
$EndLineNumber = $StartLineNumber
100+
}
101+
102+
# Protect against zero as a value since lines and columns start at 1
103+
if (-not $StartColumnNumber) {
104+
$StartColumnNumber = 1
105+
}
106+
107+
if (-not $StartLineNumber) {
108+
$StartLineNumber = 1
109+
}
110+
111+
if (-not $EndLineNumber) {
112+
$EndLineNumber = 1
113+
}
114+
115+
if (-not $EndColumnNumber) {
116+
$EndColumnNumber = 1
117+
}
112118

113119
return [Microsoft.PowerShell.EditorServices.Extensions.FileScriptExtent, Microsoft.PowerShell.EditorServices]::FromPositions(
120+
$fileContext,
114121
$StartLineNumber,
115122
$StartColumnNumber,
116123
$EndLineNumber,

module/PowerShellEditorServices/Commands/Public/Set-ScriptExtent.ps1

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function Set-ScriptExtent {
2525
)
2626
begin {
2727
$fileContext = $psEditor.GetEditorContext().CurrentFile
28-
$extentList = [System.Collections.Generic.List[Microsoft.PowerShell.EditorServices.Extensions.FileScriptExtent, Microsoft.PowerShell.EditorServices]]::new()
28+
$extentList = [System.Collections.Generic.List[[Microsoft.PowerShell.EditorServices.Extensions.FileScriptExtent, Microsoft.PowerShell.EditorServices]]]::new()
2929
}
3030
process {
3131
if ($Extent -isnot [Microsoft.PowerShell.EditorServices.Extensions.FileScriptExtent, Microsoft.PowerShell.EditorServices]) {

src/PowerShellEditorServices/Extensions/EditorFileRanges.cs

+31-5
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,23 @@ public class FileScriptPosition : IScriptPosition, IFilePosition
1515

1616
public static FileScriptPosition FromPosition(FileContext file, int lineNumber, int columnNumber)
1717
{
18+
if (file is null)
19+
{
20+
throw new ArgumentNullException(nameof(file));
21+
}
22+
1823
int offset = 0;
1924
int currLine = 1;
2025
string fileText = file.Ast.Extent.Text;
2126
while (offset < fileText.Length && currLine < lineNumber)
2227
{
23-
offset = fileText.IndexOf('\n', offset);
28+
offset = fileText.IndexOf('\n', offset) + 1;
29+
if (offset is 0)
30+
{
31+
// Line and column passed were not valid and the offset can not be determined.
32+
return new FileScriptPosition(file, lineNumber, columnNumber, offset);
33+
}
34+
2435
currLine++;
2536
}
2637

@@ -31,6 +42,11 @@ public static FileScriptPosition FromPosition(FileContext file, int lineNumber,
3142

3243
public static FileScriptPosition FromOffset(FileContext file, int offset)
3344
{
45+
if (file is null)
46+
{
47+
throw new ArgumentNullException(nameof(file));
48+
}
49+
3450
int line = 1;
3551
string fileText = file.Ast.Extent.Text;
3652

@@ -59,7 +75,7 @@ public static FileScriptPosition FromOffset(FileContext file, int offset)
5975
internal FileScriptPosition(FileContext file, int lineNumber, int columnNumber, int offset)
6076
{
6177
_file = file;
62-
Line = file.GetTextLines()[lineNumber - 1];
78+
Line = file?.GetTextLines()?[lineNumber - 1] ?? string.Empty;
6379
ColumnNumber = columnNumber;
6480
LineNumber = lineNumber;
6581
Offset = offset;
@@ -79,7 +95,7 @@ internal FileScriptPosition(FileContext file, int lineNumber, int columnNumber,
7995

8096
int IFilePosition.Line => LineNumber;
8197

82-
public string GetFullScript() => _file.GetText();
98+
public string GetFullScript() => _file?.GetText() ?? string.Empty;
8399
}
84100

85101
public class FileScriptExtent : IScriptExtent, IFileRange
@@ -94,6 +110,11 @@ public static bool IsEmpty(FileScriptExtent extent)
94110

95111
public static FileScriptExtent FromOffsets(FileContext file, int startOffset, int endOffset)
96112
{
113+
if (file is null)
114+
{
115+
throw new ArgumentNullException(nameof(file));
116+
}
117+
97118
return new FileScriptExtent(
98119
file,
99120
FileScriptPosition.FromOffset(file, startOffset),
@@ -102,6 +123,11 @@ public static FileScriptExtent FromOffsets(FileContext file, int startOffset, in
102123

103124
public static FileScriptExtent FromPositions(FileContext file, int startLine, int startColumn, int endLine, int endColumn)
104125
{
126+
if (file is null)
127+
{
128+
throw new ArgumentNullException(nameof(file));
129+
}
130+
105131
return new FileScriptExtent(
106132
file,
107133
FileScriptPosition.FromPosition(file, startLine, startColumn),
@@ -127,7 +153,7 @@ public FileScriptExtent(FileContext file, FileScriptPosition start, FileScriptPo
127153

128154
public IScriptPosition EndScriptPosition => _end;
129155

130-
public string File => _file.Path;
156+
public string File => _file?.Path ?? string.Empty;
131157

132158
public int StartColumnNumber => _start.ColumnNumber;
133159

@@ -137,7 +163,7 @@ public FileScriptExtent(FileContext file, FileScriptPosition start, FileScriptPo
137163

138164
public IScriptPosition StartScriptPosition => _start;
139165

140-
public string Text => _file.GetText().Substring(_start.Offset, _end.Offset - _start.Offset);
166+
public string Text => _file?.GetText()?.Substring(_start.Offset, _end.Offset - _start.Offset) ?? string.Empty;
141167

142168
IFilePosition IFileRange.Start => _start;
143169

0 commit comments

Comments
 (0)