Skip to content

Commit

Permalink
Added ExclusiveParameterCondition
Browse files Browse the repository at this point in the history
See also: #1
  • Loading branch information
AnderssonPeter committed Jan 11, 2022
1 parent 7e4d20a commit ec9ee93
Show file tree
Hide file tree
Showing 12 changed files with 209 additions and 46 deletions.
43 changes: 43 additions & 0 deletions PowerType.Tests/ConditionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,47 @@ public void LesserOrEqualThanCondition(object firstValue, object secondValue, bo
var condition = new LesserOrEqualCondition(firstValue, secondValue);
condition.Evaluate(parameters).Should().Be(expected);
}


[InlineData(new string[] { "message" }, false)]
[InlineData(new string[] { "test", "message" }, false)]
[InlineData(new string[] { "test" }, true)]
[Theory]
public void ExclusiveParameterConditionTrue(string[] parameterNames, bool expected)
{
var condition = new ExclusiveParameterCondition(parameterNames);
var arguments = PowerShellString.FromRawSmart(new string[] { "git", "checkout", "-m", "'message'" }).ToArray();
var dictionaryParsingContext = new DictionaryParsingContext("", arguments)
{
Command = new Command("git", null)
};
dictionaryParsingContext.Parameters.Add(new ParameterWithValue(arguments[1], new CommandParameter() { Name = "checkout" }));
dictionaryParsingContext.Parameters.Add(new ParameterWithValue(arguments[2], new ValueParameter() { Name = "message" }, arguments[3]));
var result = condition.Evaluate(new Dictionary<string, object>
{
{ nameof(DictionaryParsingContext), dictionaryParsingContext}
});
result.Should().Be(expected);
}

[Fact]
public void ExclusiveParameterConditionArgumentNullException()
{
var a = () =>
{
new ExclusiveParameterCondition((string[])null);
};
a.Should().Throw<ArgumentNullException>();
}


[Fact]
public void ExclusiveParameterConditionArgumentOutOfRangeException()
{
var a = () =>
{
new ExclusiveParameterCondition();
};
a.Should().Throw<ArgumentOutOfRangeException>();
}
}
37 changes: 37 additions & 0 deletions PowerType.Tests/PowerTypePredictionSummaryCollectorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation.Subsystem.Prediction;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using Xunit;

namespace PowerType.Tests;

public class PowerTypePredictionSummaryCollectorTests
{

[Fact]
public void TestGetOne()
{
var collector = new PowerTypePredictionSummaryCollector();
var suggestionPackage = new SuggestionPackage(new List<PredictiveSuggestion> { new PredictiveSuggestion("git checkout main") });
collector.Add(DateTime.Now, PredictionContext.Create("git checkout"), null, suggestionPackage, TimeSpan.Zero);
var result = collector.Get();
result.Count.Should().Be(1);
}

[Fact]
public void TestGetCap()
{
var collector = new PowerTypePredictionSummaryCollector(5);
for (var i = 0; i < 10; i++)
{
var suggestionPackage = new SuggestionPackage(new List<PredictiveSuggestion> { new PredictiveSuggestion("git checkout main") });
collector.Add(DateTime.Now, PredictionContext.Create("git checkout"), null, suggestionPackage, TimeSpan.Zero);
}
var result = collector.Get();
result.Count.Should().Be(5);
}
}
74 changes: 62 additions & 12 deletions PowerType/Dictionaries/git.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,13 @@ $stashes = [DynamicSource]@{
Keys = @("--all", "-A", "--no-ignore-removal");
Name = "no-ignore-removal";
Description = "Update the index not only where the working tree has a file matching <pathspec> but also where the index already has an entry. This adds, modifies, and removes index entries to match the working tree.";
Condition = [ExclusiveParameterCondition]::new("ignore-removal")
},
[FlagParameter]@{
Keys = @("--ignore-removal", "--no-all");
Name = "ignore-removal";
Description = "Update the index by adding new files that are unknown to the index and files modified in the working tree, but ignore files that have been removed from the working tree. This option is a no-op when no <pathspec> is used.";
Condition = [ExclusiveParameterCondition]::new("no-ignore-removal")
},
[FlagParameter]@{
Keys = @("--intent-to-add", "-N");
Expand Down Expand Up @@ -306,13 +308,20 @@ $stashes = [DynamicSource]@{
[ValueParameter]@{
Keys = @("--trailer");
Name = "trailer";
Description = "Specify a (<token>, <value>) pair that should be applied as a trailer. (e.g. git commit --trailer `"Signed-off-by:C O Mitter \ &lt;[email protected]&gt;`" --trailer `"Helped-by:C O Mitter \ &lt;[email protected]&gt;`" will add the `"Signed-off-by`" trailer and the `"Helped-by`" trailer to the commit message.) The trailer.* configuration variables ( git-interpret-trailers1 ) can be used to define if a duplicated trailer is omitted, where in the run of trailers each trailer would appear, and other details.";
Description = "Specify a (<token>, <value>) pair that should be applied as a trailer. (e.g. git commit --trailer `"Signed-off-by:C O Mitter \ <[email protected]>`" --trailer `"Helped-by:C O Mitter \ &lt;[email protected]&gt;`" will add the `"Signed-off-by`" trailer and the `"Helped-by`" trailer to the commit message.) The trailer.* configuration variables ( git-interpret-trailers1 ) can be used to define if a duplicated trailer is omitted, where in the run of trailers each trailer would appear, and other details.";
Condition = [LargerOrEqualCondition]::new($version, [Version]'2.32.0')
},
[FlagParameter]@{
Keys = @("--verify", "--no-verify", "-n");
Keys = @("--verify");
Name = "verify";
Description = "By default, the pre-commit and commit-msg hooks are run. When any of --no-verify or -n is given, these are bypassed. See also githooks5 .";
Description = "By default, the pre-commit and commit-msg hooks are run. When any of --no-verify or -n is given, these are bypassed. See also githooks.";
Condition = [ExclusiveParameterCondition]::new("no verify")
},
[FlagParameter]@{
Keys = @("--no-verify", "-n");
Name = "no verify";
Description = "By default, the pre-commit and commit-msg hooks are run. When any of --no-verify or -n is given, these are bypassed. See also githooks.";
Condition = [ExclusiveParameterCondition]::new("verify")
},
[FlagParameter]@{
Keys = @("--allow-empty");
Expand All @@ -334,11 +343,13 @@ $stashes = [DynamicSource]@{
Keys = @("--edit", "-e");
Name = "edit";
Description = "The message taken from file with -F, command line with -m, and from commit object with -C are usually used as the commit log message unmodified. This option lets you further edit the message taken from these sources.";
Condition = [ExclusiveParameterCondition]::new("no-edit")
},
[FlagParameter]@{
Keys = @("--no-edit");
Name = "no-edit";
Description = "Use the selected commit message without launching an editor. For example, git commit --amend --no-edit amends a commit without changing its commit message.";
Condition = [ExclusiveParameterCondition]::new("edit")
},
[FlagParameter]@{
Keys = @("--amend");
Expand Down Expand Up @@ -412,21 +423,25 @@ $stashes = [DynamicSource]@{
Keys = @("--status");
Name = "status";
Description = "Include the output of git-status1 in the commit message template when using an editor to prepare the commit message. Defaults to on, but can be used to override configuration variable commit.status.";
Condition = [ExclusiveParameterCondition]::new("no-status")
},
[FlagParameter]@{
Keys = @("--no-status");
Name = "no-status";
Description = "Do not include the output of git-status1 in the commit message template when using an editor to prepare the default commit message.";
Condition = [ExclusiveParameterCondition]::new("status")
},
[ValueParameter]@{
Keys = @("--gpg-sign", "-S");
Name = "gpg-sign";
Description = "GPG-sign commits. The keyid argument is optional and defaults to the committer identity; if specified, it must be stuck to the option without a space. --no-gpg-sign is useful to countermand both commit.gpgSign configuration variable, and earlier --gpg-sign.";
Condition = [ExclusiveParameterCondition]::new("no-gpg-sign")
},
[FlagParameter]@{
Keys = @("--no-gpg-sign");
Name = "no-gpg-sign";
Description = "Don't gpg sign";
Condition = [ExclusiveParameterCondition]::new("gpg-sign")
},
[FlagParameter]@{
Keys = @("--");
Expand Down Expand Up @@ -481,16 +496,25 @@ $stashes = [DynamicSource]@{
Keys = @("--track", "-t");
Name = "track";
Description = "When creating a new branch, set up `"upstream`" configuration. See `"--track`" in git-branch1 for details.";
Condition = [ExclusiveParameterCondition]::new("no-track")
},
[FlagParameter]@{
Keys = @("--no-track");
Name = "no-track";
Description = "Do not set up `"upstream`" configuration, even if the branch.autoSetupMerge configuration variable is true.";
Condition = [ExclusiveParameterCondition]::new("track")
},
[FlagParameter]@{
Keys = @("--no-guess", "--guess");
Keys = @("--guess");
Name = "guess";
Description = "If <branch> is not found but there does exist a tracking branch in exactly one remote (call it <remote>) with a matching name, treat as equivalent to";
Condition = [ExclusiveParameterCondition]::new("no-guess")
},
[FlagParameter]@{
Keys = @("--no-guess");
Name = "no-guess";
Description = "If <branch> is not found but there does exist a tracking branch in exactly one remote (call it <remote>) with a matching name, treat as equivalent to";
Condition = [ExclusiveParameterCondition]::new("guess")
},
[FlagParameter]@{
Keys = @("-l");
Expand Down Expand Up @@ -554,9 +578,16 @@ $stashes = [DynamicSource]@{
Description = "Using --recurse-submodules will update the content of all active submodules according to the commit recorded in the superproject. If local modifications in a submodule would be overwritten the checkout will fail unless -f is used. If nothing (or --no-recurse-submodules) is used, submodules working trees will not be updated. Just like git-submodule1 , this will detach HEAD of the submodule.";
},
[FlagParameter]@{
Keys = @("--overlay", "--no-overlay");
Keys = @("--overlay");
Name = "overlay";
Description = "In the default overlay mode, git checkout never removes files from the index or the working tree. When specifying --no-overlay, files that appear in the index and working tree, but not in <tree-ish> are removed, to make them match <tree-ish> exactly.";
Condition = [ExclusiveParameterCondition]::new("no-overlay")
},
[FlagParameter]@{
Keys = @("--no-overlay");
Name = "no-overlay";
Description = "In the default overlay mode, git checkout never removes files from the index or the working tree. When specifying --no-overlay, files that appear in the index and working tree, but not in <tree-ish> are removed, to make them match <tree-ish> exactly.";
Condition = [ExclusiveParameterCondition]::new("overlay")
},
[ValueParameter]@{
Keys = @("--pathspec-from-file");
Expand Down Expand Up @@ -601,9 +632,16 @@ $stashes = [DynamicSource]@{
Name = "show";
Parameters = @(
[FlagParameter]@{
Keys = @("--include-untracked", "--no-include-untracked", "-u");
Name = "no-include-untracked";
Keys = @("--include-untracked", "-u");
Name = "include-untracked";
Description = "All untracked files are also stashed and then cleaned up with git clean.";
Condition = [ExclusiveParameterCondition]::new("no-include-untracked")
},
[FlagParameter]@{
Keys = @("--no-include-untracked");
Name = "no-include-untracked";
Description = "No untracked files are stashed and then cleaned up with git clean.";
Condition = [ExclusiveParameterCondition]::new("include-untracked")
},
[ValueParameter]@{
Name = "stash";
Expand Down Expand Up @@ -665,17 +703,29 @@ $stashes = [DynamicSource]@{
[FlagParameter]@{
Keys = @("--patch", "-p");
Name = "patch";
Description = "This option is only valid for push and save commands.";
},
[FlagParameter]@{
Keys = @("--keep-index", "--no-keep-index", "-k");
Keys = @("--keep-index", "-k");
Name = "keep-index";
Description = "All changes already added to the index are left intact.";
Condition = [ExclusiveParameterCondition]::new("no-keep-index")
},
[FlagParameter]@{
Keys = @("--no-keep-index");
Name = "no-keep-index";
Description = "This option is only valid for push and save commands.";
Condition = [ExclusiveParameterCondition]::new("keep-index")
},
[FlagParameter]@{
Keys = @("--include-untracked", "--no-include-untracked", "-u");
Name = "no-include-untracked";
Keys = @("--include-untracked", "-u");
Name = "include-untracked";
Description = "All untracked files are also stashed and then cleaned up with git clean.";
Condition = [ExclusiveParameterCondition]::new("no-include-untracked")
},
[FlagParameter]@{
Keys = @("--no-include-untracked");
Name = "no-include-untracked";
Description = "No untracked files are stashed and then cleaned up with git clean.";
Condition = [ExclusiveParameterCondition]::new("include-untracked")
},
[FlagParameter]@{
Keys = @("--all", "-a");
Expand Down
1 change: 0 additions & 1 deletion PowerType/GetPowerTypeStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ public record PowerTypeStatus(bool ExecutionEngineIsRunning, Exception? Executio
[Cmdlet("Get", "PowerTypeStatus"), OutputType(typeof(bool))]
public class GetPowerTypeStatus : PowerTypeCmdlet
{

/// <inheritdoc/>
protected override void ProcessRecord()
{
Expand Down
41 changes: 20 additions & 21 deletions PowerType/Model/CommandParameter.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
using System.Collections.Generic;

namespace PowerType.Model
namespace PowerType.Model;

public class CommandParameter : Parameter
{
public class CommandParameter : Parameter
{
public List<Parameter> Parameters { get; set; } = new List<Parameter>();
public List<Parameter> Parameters { get; set; } = new List<Parameter>();

internal override void Initialize(ISystemTime systemTime)
{
base.Initialize(systemTime);
foreach(var parameter in Parameters)
{
parameter.Initialize(systemTime);
}
internal override void Initialize(ISystemTime systemTime)
{
base.Initialize(systemTime);
foreach (var parameter in Parameters)
{
parameter.Initialize(systemTime);
}
}

internal override void Validate()
internal override void Validate()
{
base.Validate();
if (Parameters == null)
{
throw new ArgumentNullException(nameof(Parameters));
}
foreach (var parameter in Parameters)
{
base.Validate();
if (Parameters == null)
{
throw new ArgumentNullException(nameof(Parameters));
}
foreach (var parameter in Parameters)
{
parameter.Validate();
}
parameter.Validate();
}
}
}
1 change: 0 additions & 1 deletion PowerType/Model/Conditions/Condition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,5 @@ public abstract class Condition

public virtual void Validate()
{

}
}
32 changes: 32 additions & 0 deletions PowerType/Model/Conditions/ExclusiveParameterCondition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PowerType.Parsing;

namespace PowerType.Model.Conditions;

public class ExclusiveParameterCondition : Condition
{
private readonly string[] parameterNames;

public ExclusiveParameterCondition(params string[] parameterNames)
{
if (parameterNames == null)
{
throw new ArgumentNullException(nameof(parameterNames));
}
else if (parameterNames.Length == 0)
{
throw new ArgumentOutOfRangeException(nameof(parameterNames), "Must have at least one name");
}
this.parameterNames = parameterNames;
}

public override bool Evaluate(Dictionary<string, object> parameters)
{
var dictionaryParsingContext = (DictionaryParsingContext)parameters[nameof(DictionaryParsingContext)];
return !dictionaryParsingContext.Parameters.Any(x => parameterNames.Contains(x.Parameter?.Name));
}
}
14 changes: 5 additions & 9 deletions PowerType/Model/Parameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

namespace PowerType.Model;


[DebuggerDisplay("{Name}")]
public abstract class Parameter
{
Expand All @@ -32,18 +31,15 @@ internal virtual void Validate()
{
throw new ArgumentNullException(nameof(Name));
}
if (Condition != null)
{
Condition.Validate();
}
Condition?.Validate();
}

internal bool IsAvailable(DictionaryParsingContext dictionaryParsingContext) =>
Condition == null || Condition.Evaluate(new Dictionary<string, object>
Condition?.Evaluate(new Dictionary<string, object>
{
{ "DictionaryParsingContext", dictionaryParsingContext },
{ "Parameter", this }
});
{ nameof(DictionaryParsingContext), dictionaryParsingContext },
{ nameof(Parameter), this }
}) != false;

internal bool HasKeys => Keys?.Count > 0;

Expand Down
Loading

0 comments on commit ec9ee93

Please sign in to comment.