Skip to content

Commit

Permalink
Merge pull request #3968 from MDoerner/MakeUnreachableSelectCultureIn…
Browse files Browse the repository at this point in the history
…variant

Make unreachable select culture invariant
  • Loading branch information
retailcoder committed Apr 26, 2018
2 parents 1b4312b + 4576a8c commit 1b1fe5c
Show file tree
Hide file tree
Showing 11 changed files with 936 additions and 527 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;

namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection
{
Expand All @@ -15,7 +16,7 @@ public class ParseTreeExpressionEvaluator : IParseTreeExpressionEvaluator
{
private readonly IParseTreeValueFactory _valueFactory;

private static Dictionary<string, Func<double, double, double>> MathOpsBinary = new Dictionary<string, Func<double, double, double>>()
private static readonly Dictionary<string, Func<double, double, double>> MathOpsBinary = new Dictionary<string, Func<double, double, double>>()
{
[MathSymbols.MULTIPLY] = delegate (double LHS, double RHS) { return LHS * RHS; },
[MathSymbols.DIVIDE] = delegate (double LHS, double RHS) { return LHS / RHS; },
Expand All @@ -26,7 +27,7 @@ public class ParseTreeExpressionEvaluator : IParseTreeExpressionEvaluator
[MathSymbols.MODULO] = delegate (double LHS, double RHS) { return LHS % RHS; },
};

private static Dictionary<string, Func<double, double, bool>> LogicOpsBinary = new Dictionary<string, Func<double, double, bool>>()
private static readonly Dictionary<string, Func<double, double, bool>> LogicOpsBinary = new Dictionary<string, Func<double, double, bool>>()
{
[LogicSymbols.EQ] = delegate (double LHS, double RHS) { return LHS == RHS; },
[LogicSymbols.NEQ] = delegate (double LHS, double RHS) { return LHS != RHS; },
Expand All @@ -41,17 +42,17 @@ public class ParseTreeExpressionEvaluator : IParseTreeExpressionEvaluator
[LogicSymbols.IMP] = delegate (double LHS, double RHS) { return Convert.ToBoolean(LHS).Equals(Convert.ToBoolean(RHS)) || Convert.ToBoolean(RHS); },
};

private static Dictionary<string, Func<double, double>> MathOpsUnary = new Dictionary<string, Func<double, double>>()
private static readonly Dictionary<string, Func<double, double>> MathOpsUnary = new Dictionary<string, Func<double, double>>()
{
[MathSymbols.ADDITIVE_INVERSE] = delegate (double value) { return value * -1.0; }
};

private static Dictionary<string, Func<double, bool>> LogicOpsUnary = new Dictionary<string, Func<double, bool>>()
private static readonly Dictionary<string, Func<double, bool>> LogicOpsUnary = new Dictionary<string, Func<double, bool>>()
{
[LogicSymbols.NOT] = delegate (double value) { return !(Convert.ToBoolean(value)); }
};

private static List<string> ResultTypeRanking = new List<string>()
private static readonly List<string> ResultTypeRanking = new List<string>()
{
Tokens.Currency,
Tokens.Double,
Expand All @@ -74,14 +75,14 @@ public IParseTreeValue Evaluate(IParseTreeValue LHS, IParseTreeValue RHS, string
Debug.Assert(isMathOp || isLogicOp);

var opResultTypeName = isMathOp ? DetermineMathResultType(LHS, RHS) : Tokens.Boolean;
var operands = PrepareOperands(new string[] { LHS.ValueText, RHS.ValueText });
var operands = PrepareOperands(new IParseTreeValue[] { LHS, RHS });

if (operands.Count == 2)
{
if (isMathOp)
{
var mathResult = MathOpsBinary[opSymbol](operands[0], operands[1]);
return _valueFactory.Create(mathResult.ToString(), opResultTypeName);
return _valueFactory.Create(mathResult.ToString(CultureInfo.InvariantCulture), opResultTypeName);
}
var logicResult = LogicOpsBinary[opSymbol](operands[0], operands[1]);
return _valueFactory.Create(logicResult.ToString(), opResultTypeName);
Expand All @@ -95,22 +96,23 @@ public IParseTreeValue Evaluate(IParseTreeValue value, string opSymbol, string r
var isLogicOp = LogicOpsUnary.ContainsKey(opSymbol);
Debug.Assert(isMathOp || isLogicOp);

var operands = PrepareOperands(new string[] { value.ValueText });
var operands = PrepareOperands(new IParseTreeValue[] { value });
if (operands.Count == 1)
{
if (isMathOp)
{
var mathResult = MathOpsUnary[opSymbol](operands[0]);
return _valueFactory.Create(mathResult.ToString(), requestedResultType);
return _valueFactory.Create(mathResult.ToString(CultureInfo.InvariantCulture), requestedResultType);
}

//Unary Not (!) operator
if (!value.TypeName.Equals(Tokens.Boolean) && ParseTreeValue.TryConvertValue(value, out long opValue))
if (!value.TypeName.Equals(Tokens.Boolean) && value.TryConvertValue(out long opValue))
{
var bitwiseComplement = ~opValue;
return _valueFactory.Create(Convert.ToBoolean(bitwiseComplement).ToString(), requestedResultType);
}
else if (value.TypeName.Equals(Tokens.Boolean))

if (value.TypeName.Equals(Tokens.Boolean))
{
var logicResult = LogicOpsUnary[opSymbol](operands[0]);
return _valueFactory.Create(logicResult.ToString(), requestedResultType);
Expand All @@ -137,13 +139,26 @@ private static List<double> PrepareOperands(string[] args)
parseArg = arg.Equals(Tokens.True) ? "-1" : "0";
}

if (double.TryParse(parseArg, out double result))
if (double.TryParse(parseArg, NumberStyles.Any, CultureInfo.InvariantCulture, out double result))
{
results.Add(result);
}
}
return results;
}

private static List<double> PrepareOperands(IParseTreeValue[] args)
{
var results = new List<double>();
foreach (var arg in args)
{
if (arg.TryConvertValue(out double value))
{
results.Add(value);
}
}
return results;
}
}

internal static class MathSymbols
Expand Down

0 comments on commit 1b1fe5c

Please sign in to comment.