Skip to content

Commit

Permalink
Fix Cpp2 evaluator for multichoice parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
JanKrivanek authored and vlada-shubina committed Jul 18, 2022
1 parent b6040cc commit ad5a6fc
Show file tree
Hide file tree
Showing 10 changed files with 277 additions and 30 deletions.
26 changes: 2 additions & 24 deletions src/Microsoft.TemplateEngine.Core/Expressions/Cpp/Scope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,34 +112,12 @@ private static bool LenientEquals(object x, object y)
return string.Equals(sx, sy, StringComparison.OrdinalIgnoreCase);
}

if (MultiValueParameter.TryPerformMultiValueEqual(x, y, out bool result))
{
if (x is MultiValueParameter mv && y is string sv)
{
return MultivalueEquals(mv, sv);
}
}

{
if (y is MultiValueParameter mv && x is string sv)
{
return MultivalueEquals(mv, sv);
}
return result;
}

return Equals(x, y);
}

private static bool MultivalueEquals(MultiValueParameter mv, string comparand)
{
foreach (string s in mv.Values)
{
if (string.Equals(s, comparand, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}

return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ public IEvaluable Build(ref int bufferLength, ref int bufferPosition, Action<IRe
//Is it a variable?
else if (_knownTokensCount <= token)
{
string value = (_symbolValues[token - _knownTokensCount] ?? "null").ToString();
object value = _symbolValues[token - _knownTokensCount] ?? null;
Token<TToken> t = new Token<TToken>(_literal, value);
TokenScope<TToken> scope = new TokenScope<TToken>(isolator.Active, t);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.TemplateEngine.Core.Contracts;
using Microsoft.TemplateEngine.Core.Util;
using Microsoft.TemplateEngine.Utils;

namespace Microsoft.TemplateEngine.Core.Expressions.Shared
{
Expand Down Expand Up @@ -79,6 +80,7 @@ protected static int Compare(object left, object right)
return AttemptNumericComparison(left, right)
?? AttemptBooleanComparison(left, right)
?? AttemptVersionComparison(left, right)
?? AttemptMultiValueComparison(left, right)
?? AttemptLexographicComparison(left, right)
?? AttemptComparableComparison(left, right)
?? 0;
Expand Down Expand Up @@ -114,7 +116,17 @@ protected static int Compare(object left, object right)
return ls.CompareTo(rs);
}

private static int? AttemptLexographicComparison(object left, object right)
private static int? AttemptMultiValueComparison(object left, object right)
{
if (MultiValueParameter.TryPerformMultiValueEqual(left, right, out bool result))
{
return result ? 0 : -1;
}

return null;
}

private static int? AttemptLexographicComparison(object left, object right)
{
string ls = left as string;
string rs = right as string;
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.TemplateEngine.Core/Expressions/Token.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ namespace Microsoft.TemplateEngine.Core.Expressions
{
public class Token<TToken>
{
public Token(TToken family, string value)
public Token(TToken family, object value)
{
Family = family;
Value = value;
}

public TToken Family { get; }

public string Value { get; }
public object Value { get; }
}
}
2 changes: 0 additions & 2 deletions src/Microsoft.TemplateEngine.Core/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,6 @@ override Microsoft.TemplateEngine.Core.TokenConfig.GetHashCode() -> int
~Microsoft.TemplateEngine.Core.Expressions.ScopeBuilder<TOperator, TToken>.Build(ref int bufferLength, ref int bufferPosition, System.Action<System.Collections.Generic.IReadOnlyList<byte>> onFault) -> Microsoft.TemplateEngine.Core.Expressions.IEvaluable
~Microsoft.TemplateEngine.Core.Expressions.ScopeBuilder<TOperator, TToken>.ScopeBuilder(Microsoft.TemplateEngine.Core.Contracts.IProcessorState processor, Microsoft.TemplateEngine.Core.Contracts.ITokenTrie tokens, Microsoft.TemplateEngine.Core.Expressions.IOperatorMap<TOperator, TToken> operatorMap, bool dereferenceInLiterals) -> void
~Microsoft.TemplateEngine.Core.Expressions.Shared.SharedEvaluatorDefinition<TSelf, TTokens>
~Microsoft.TemplateEngine.Core.Expressions.Token<TToken>.Token(TToken family, string value) -> void
~Microsoft.TemplateEngine.Core.Expressions.Token<TToken>.Value.get -> string
~Microsoft.TemplateEngine.Core.Expressions.TokenScope<TToken>.Evaluate() -> object
~Microsoft.TemplateEngine.Core.Expressions.TokenScope<TToken>.Parent.get -> Microsoft.TemplateEngine.Core.Expressions.IEvaluable
~Microsoft.TemplateEngine.Core.Expressions.TokenScope<TToken>.Parent.set -> void
Expand Down
2 changes: 2 additions & 0 deletions src/Microsoft.TemplateEngine.Core/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ static Microsoft.TemplateEngine.Core.Util.EngineConfig.DefaultWhitespaces.set ->
virtual Microsoft.TemplateEngine.Core.Util.Orchestrator.RunSpecLoader(System.IO.Stream! runSpec) -> Microsoft.TemplateEngine.Core.Contracts.IGlobalRunSpec!
virtual Microsoft.TemplateEngine.Core.Util.Orchestrator.TryGetBufferSize(Microsoft.TemplateEngine.Abstractions.Mount.IFile! sourceFile, out int bufferSize) -> bool
virtual Microsoft.TemplateEngine.Core.Util.Orchestrator.TryGetFlushThreshold(Microsoft.TemplateEngine.Abstractions.Mount.IFile! sourceFile, out int threshold) -> bool
~Microsoft.TemplateEngine.Core.Expressions.Token<TToken>.Token(TToken family, object value) -> void
~Microsoft.TemplateEngine.Core.Expressions.Token<TToken>.Value.get -> object
~static Microsoft.TemplateEngine.Core.Expressions.Shared.SharedEvaluatorDefinition<TSelf, TTokens>.EvaluateFromString(Microsoft.Extensions.Logging.ILogger logger, string text, Microsoft.TemplateEngine.Core.Contracts.IVariableCollection variables) -> bool
76 changes: 76 additions & 0 deletions src/Microsoft.TemplateEngine.Utils/MultiValueParameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Microsoft.TemplateEngine.Utils
Expand Down Expand Up @@ -38,7 +39,82 @@ public MultiValueParameter(IReadOnlyList<string> values)
/// </summary>
public IReadOnlyList<string> Values { get; private init; }

public static bool TryPerformMultiValueEqual(object x, object y, out bool result)
{
bool isxMv = x is MultiValueParameter;
bool isyMv = y is MultiValueParameter;

if (!isxMv && !isyMv)
{
result = false;
return false;
}

{
if (x is MultiValueParameter mv && y is string sv)
{
result = MultivalueEquals(mv, sv);
return true;
}
}

{
if (y is MultiValueParameter mv && x is string sv)
{
result = MultivalueEquals(mv, sv);
return true;
}
}

result = Equals(x, y);
return true;
}

/// <inheritdoc/>
public override string ToString() => string.Join(MultiValueSeparator.ToString(), Values);

/// <inheritdoc/>
public override bool Equals(object? obj)
{
if (obj is null)
{
return false;
}

if (ReferenceEquals(this, obj))
{
return true;
}

if (obj.GetType() != this.GetType())
{
return false;
}

return Equals((MultiValueParameter)obj);
}

/// <inheritdoc/>
public override int GetHashCode() => Values.OrderBy(v => v).ToCsvString().GetHashCode();

protected bool Equals(MultiValueParameter other)
{
var set1 = new HashSet<string>(Values);
var set2 = new HashSet<string>(other.Values);
return set1.SetEquals(set2);
}

private static bool MultivalueEquals(MultiValueParameter mv, string comparand)
{
foreach (string s in mv.Values)
{
if (string.Equals(s, comparand, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}

return false;
}
}
}
4 changes: 4 additions & 0 deletions src/Microsoft.TemplateEngine.Utils/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Microsoft.TemplateEngine.Utils.InMemoryFileSystem.PathRelativeTo(string! target,
Microsoft.TemplateEngine.Utils.DefaultTemplateEngineHost.Dispose() -> void
Microsoft.TemplateEngine.Utils.EnumerableExtensions
Microsoft.TemplateEngine.Utils.MultiValueParameter
Microsoft.TemplateEngine.Utils.MultiValueParameter.Equals(Microsoft.TemplateEngine.Utils.MultiValueParameter! other) -> bool
Microsoft.TemplateEngine.Utils.MultiValueParameter.MultiValueParameter(System.Collections.Generic.IReadOnlyList<string!>! values) -> void
Microsoft.TemplateEngine.Utils.MultiValueParameter.Values.get -> System.Collections.Generic.IReadOnlyList<string!>!
Microsoft.TemplateEngine.Utils.PhysicalFileSystem.PathRelativeTo(string! target, string! relativeTo) -> string!
Expand All @@ -43,6 +44,8 @@ Microsoft.TemplateEngine.Utils.TemplateParameter.AllowMultipleValues.get -> bool
Microsoft.TemplateEngine.Utils.TemplateParameter.TemplateParameter(string! name, string! type, string! datatype, Microsoft.TemplateEngine.Abstractions.TemplateParameterPriority priority = Microsoft.TemplateEngine.Abstractions.TemplateParameterPriority.Required, bool isName = false, string? defaultValue = null, string? defaultIfOptionWithoutValue = null, string? description = null, string? displayName = null, bool allowMultipleValues = false, System.Collections.Generic.IReadOnlyDictionary<string!, Microsoft.TemplateEngine.Abstractions.ParameterChoice!>? choices = null) -> void
Microsoft.TemplateEngine.Utils.Timing.Timing(Microsoft.Extensions.Logging.ILogger! logger, string! label) -> void
override Microsoft.TemplateEngine.Utils.ExactVersionSpecification.ToString() -> string!
override Microsoft.TemplateEngine.Utils.MultiValueParameter.Equals(object? obj) -> bool
override Microsoft.TemplateEngine.Utils.MultiValueParameter.GetHashCode() -> int
override Microsoft.TemplateEngine.Utils.MultiValueParameter.ToString() -> string!
static Microsoft.TemplateEngine.Utils.ArrayExtensions.CombineArrays<T>(params T[]![]! arrayList) -> T[]!
static Microsoft.TemplateEngine.Utils.DictionaryExtensions.CloneIfDifferentComparer<T>(this System.Collections.Generic.IReadOnlyDictionary<string!, T>! source, System.StringComparer! comparer) -> System.Collections.Generic.IReadOnlyDictionary<string!, T>!
Expand All @@ -63,6 +66,7 @@ static Microsoft.TemplateEngine.Utils.FileSystemInfoExtensions.PathRelativeTo(th
static Microsoft.TemplateEngine.Utils.Glob.Parse(string! pattern, bool canBeNameOnlyMatch = true) -> Microsoft.TemplateEngine.Utils.Glob!
static Microsoft.TemplateEngine.Utils.ListExtensions.GroupBy<TElement, TKey>(this System.Collections.Generic.IEnumerable<TElement>! elements, System.Func<TElement, TKey?>! grouper, System.Func<TElement, bool>! hasGroupKey, System.Collections.Generic.IEqualityComparer<TKey?>? comparer = null) -> System.Collections.Generic.IEnumerable<System.Linq.IGrouping<TKey?, TElement>!>!
static Microsoft.TemplateEngine.Utils.MultiValueParameter.MultiValueSeparators.get -> char[]!
static Microsoft.TemplateEngine.Utils.MultiValueParameter.TryPerformMultiValueEqual(object! x, object! y, out bool result) -> bool
static Microsoft.TemplateEngine.Utils.ParserExtensions.ConvertToDoubleCurrentOrInvariant(object! value) -> double
static Microsoft.TemplateEngine.Utils.ParserExtensions.DoubleTryParseСurrentOrInvariant(string? stringValue, out double doubleValue) -> bool
static Microsoft.TemplateEngine.Utils.RuntimeValueUtil.TryGetRuntimeValue(this Microsoft.TemplateEngine.Abstractions.IParameterSet! parameters, Microsoft.TemplateEngine.Abstractions.IEngineEnvironmentSettings! environmentSettings, string! name, out object? value, bool skipEnvironmentVariableSearch = false) -> bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.TemplateEngine.Orchestrator.RunnableProjects.Macros;
using Microsoft.TemplateEngine.Orchestrator.RunnableProjects.Macros.Config;
using Microsoft.TemplateEngine.TestHelper;
using Microsoft.TemplateEngine.Utils;
using Xunit;
using static Microsoft.TemplateEngine.Orchestrator.RunnableProjects.RunnableProjectGenerator;

Expand Down Expand Up @@ -38,5 +39,34 @@ public void TestEvaluateConfig(string predicate, bool expectedResult)
macro.EvaluateConfig(_engineEnvironmentSettings, variables, macroConfig);
Assert.Equal(variables[variableName], expectedResult);
}

[Theory(DisplayName = nameof(TestEvaluateConfig))]
[InlineData("(Param == A)", "C++", "A|B", true)]
[InlineData("(Param == C)", "C++", "A|B", false)]
[InlineData("((Param == A) || (Param == B))", "C++", "A|B", true)]
[InlineData("((Param == A) && (Param == B))", "C++", "A|B", true)]
[InlineData("((Param == A) && (Param != B))", "C++", "A|B", false)]
[InlineData("((Param == A) && (Param == C))", "C++", "A|B", false)]
[InlineData("(Param == A)", "C++2", "A|B", true)]
[InlineData("(Param == C)", "C++2", "A|B", false)]
[InlineData("((Param == A) || (Param == B))", "C++2", "A|B", true)]
[InlineData("((Param == A) && (Param == B))", "C++2", "A|B", true)]
[InlineData("((Param == A) && (Param != B))", "C++2", "A|B", false)]
[InlineData("((Param == A) && (Param == C))", "C++2", "A|B", false)]
public void TestEvaluateMultichoice(string condition, string evaluator, string multichoiceValues, bool expectedResult)
{
string variableName = "myPredicate";
EvaluateMacroConfig macroConfig = new EvaluateMacroConfig(variableName, null, condition, evaluator);

IVariableCollection variables = new VariableCollection();
variables["A"] = "A";
variables["B"] = "B";
variables["C"] = "C";
variables["Param"] = new MultiValueParameter(multichoiceValues.TokenizeMultiValueParameter());

EvaluateMacro macro = new EvaluateMacro();
macro.EvaluateConfig(_engineEnvironmentSettings, variables, macroConfig);
Assert.Equal(variables[variableName], expectedResult);
}
}
}
Loading

0 comments on commit ad5a6fc

Please sign in to comment.