Skip to content

Add a Range parameter to Invoke-Formatter cmdlet #780

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 15 commits into from
Jun 14, 2017
Merged
40 changes: 17 additions & 23 deletions Engine/Commands/InvokeFormatterCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

using System;
using System.Globalization;
using System.Linq;
using System.Management.Automation;

namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.Commands
Expand All @@ -26,6 +27,7 @@ public class InvokeFormatterCommand : PSCmdlet, IOutputWriter
{
private const string defaultSettingsPreset = "CodeFormatting";
private Settings inputSettings;
private Range range;

/// <summary>
/// The script text to be formated.
Expand All @@ -43,19 +45,20 @@ public class InvokeFormatterCommand : PSCmdlet, IOutputWriter
[ValidateNotNull]
public object Settings { get; set; } = defaultSettingsPreset;

#if DEBUG
[Parameter(Mandatory = false)]
public Range Range { get; set; }

[Parameter(Mandatory = false, ParameterSetName = "NoRange")]
public int StartLineNumber { get; set; } = -1;
[Parameter(Mandatory = false, ParameterSetName = "NoRange")]
public int StartColumnNumber { get; set; } = -1;
[Parameter(Mandatory = false, ParameterSetName = "NoRange")]
public int EndLineNumber { get; set; } = -1;
[Parameter(Mandatory = false, ParameterSetName = "NoRange")]
public int EndColumnNumber { get; set; } = -1;
/// <summary>
/// The range within which formatting should take place.
///
/// The parameter is an array of integers of length 4 such that the first, second, third and last
/// elements correspond to the start line number, start column number, end line number and
/// end column number. These numbers must be greater than 0.
/// </summary>
/// <returns></returns>
[Parameter(Mandatory = false, Position = 3)]
[ValidateNotNull]
[ValidateCount(4, 4)]
public int[] Range { get; set; }

#if DEBUG
/// <summary>
/// Attaches to an instance of a .Net debugger
/// </summary>
Expand Down Expand Up @@ -85,6 +88,7 @@ protected override void BeginProcessing()
}
#endif

this.range = Range == null ? null : new Range(Range[0], Range[1], Range[2], Range[3]);
try
{
inputSettings = PSSASettings.Create(Settings, this.MyInvocation.PSScriptRoot, this);
Expand All @@ -93,7 +97,7 @@ protected override void BeginProcessing()
{
this.ThrowTerminatingError(new ErrorRecord(
e,
"SETTNGS_ERROR",
"SETTINGS_ERROR",
ErrorCategory.InvalidData,
Settings));
}
Expand All @@ -114,17 +118,7 @@ protected override void ProcessRecord()
{
// todo add tests to check range formatting
string formattedScriptDefinition;
#if DEBUG
var range = Range;
if (this.ParameterSetName.Equals("NoRange"))
{
range = new Range(StartLineNumber, StartColumnNumber, EndLineNumber, EndColumnNumber);
}

formattedScriptDefinition = Formatter.Format(ScriptDefinition, inputSettings, range, this);
#endif // DEBUG

formattedScriptDefinition = Formatter.Format(ScriptDefinition, inputSettings, null, this);
this.WriteObject(formattedScriptDefinition);
}

Expand Down
26 changes: 22 additions & 4 deletions Engine/EditableText.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,27 @@ public EditableText ApplyEdit(TextEdit textEdit)

// TODO Add a method that takes multiple edits, checks if they are unique and applies them.

/// <summary>
/// Checks if the range falls within the bounds of the text.
/// </summary>
/// <param name="range"></param>
/// <returns></returns>
public bool IsValidRange(Range range)
{
if (range == null)
{
throw new ArgumentNullException(nameof(range));
}

return range.Start.Line <= Lines.Length
&& range.End.Line <= Lines.Length
&& range.Start.Column <= Lines[range.Start.Line - 1].Length
&& range.End.Column <= Lines[range.End.Line - 1].Length + 1;
}

/// <summary>
/// Returns the text representation of the object.
/// </summary>
public override string ToString()
{
return Text;
Expand All @@ -123,10 +144,7 @@ private void ValidateTextEdit(TextEdit textEdit)

private void ValidateTextEditExtent(TextEdit textEdit)
{
if (textEdit.StartLineNumber > Lines.Length
|| textEdit.EndLineNumber > Lines.Length
|| textEdit.StartColumnNumber > Lines[textEdit.StartLineNumber - 1].Length
|| textEdit.EndColumnNumber > Lines[textEdit.EndLineNumber - 1].Length + 1)
if (!IsValidRange(textEdit))
{
throw new ArgumentException(String.Format(
CultureInfo.CurrentCulture,
Expand Down
9 changes: 9 additions & 0 deletions Engine/ScriptAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1559,6 +1559,15 @@ public EditableText Fix(EditableText text, Range range, out Range updatedRange)

// todo validate range
var isRangeNull = range == null;
if (!isRangeNull && !text.IsValidRange(range))
{
this.outputWriter.ThrowTerminatingError(new ErrorRecord(
new ArgumentException("Invalid Range", nameof(range)),
"FIX_ERROR",
ErrorCategory.InvalidArgument,
range));
}

range = isRangeNull ? null : SnapToEdges(text, range);
var previousLineCount = text.Lines.Length;
var previousUnusedCorrections = 0;
Expand Down
21 changes: 21 additions & 0 deletions Tests/Engine/InvokeFormatter.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,27 @@ function foo {
Invoke-Formatter $def $settings | Should Be $expected
}
}

Context "When a range is given" {
It "Should format only within the range when a range list is given" {
$def = @"
function foo {
"xyz"
"abc"
}
"@

$expected = @"
function foo {
"xyz"
"abc"
}
"@

Invoke-Formatter -ScriptDefinition $def -Range @(3, 1, 4, 1) | Should Be $expected
}
}

Context "When no settings are given" {
It "Should format using default settings" {
$def = @'
Expand Down
16 changes: 15 additions & 1 deletion docs/markdown/Invoke-Formatter.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Formats a script text based on the input settings or default settings.
## SYNTAX

```
Invoke-Formatter [-ScriptDefinition] <String> [-Settings <object>]
Invoke-Formatter [-ScriptDefinition] <String> [-Settings <object>] [-Range <int[]>]
```

## DESCRIPTION
Expand Down Expand Up @@ -97,3 +97,17 @@ Default value: CodeFormatting
Accept pipeline input: False
Accept wildcard characters: False
```

### -Range
The range within which formatting should take place. The parameter is an array of integers of length 4 such that the first, second, third and last elements correspond to the start line number, start column number, end line number and end column number. These numbers must be greater than 0.

```yaml
Type: int[]
Parameter Sets: (All)

Required: False
Position: 3
Default value:
Accept pipeline input: False
Accept wildcard characters: False
```