Skip to content

Commit 24667f4

Browse files
committed
Merge branch 'rubberduck-vba/next' into next
2 parents 283d596 + dc5d546 commit 24667f4

28 files changed

+8217
-20
lines changed

Rubberduck.Core/NLog.xsd

Lines changed: 3103 additions & 0 deletions
Large diffs are not rendered by default.

Rubberduck.Core/Rubberduck.Core.csproj

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,22 +232,18 @@
232232
</Reference>
233233
<Reference Include="Castle.Core, Version=4.1.1.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
234234
<HintPath>..\packages\Castle.Core.4.1.1\lib\net45\Castle.Core.dll</HintPath>
235-
<Private>True</Private>
236235
</Reference>
237236
<Reference Include="Castle.Windsor, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
238237
<HintPath>..\packages\Castle.Windsor.4.0.0\lib\net45\Castle.Windsor.dll</HintPath>
239-
<Private>True</Private>
240238
</Reference>
241239
<Reference Include="EasyHook, Version=2.7.6270.0, Culture=neutral, PublicKeyToken=4b580fca19d0b0c5, processorArchitecture=MSIL">
242240
<HintPath>..\packages\EasyHook.2.7.6270\lib\net40\EasyHook.dll</HintPath>
243-
<Private>True</Private>
244241
</Reference>
245242
<Reference Include="extensibility, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
246243
<EmbedInteropTypes>True</EmbedInteropTypes>
247244
</Reference>
248245
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
249246
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
250-
<Private>True</Private>
251247
</Reference>
252248
<Reference Include="ICSharpCode.AvalonEdit, Version=5.0.3.0, Culture=neutral, PublicKeyToken=9cc39be672370310, processorArchitecture=MSIL">
253249
<HintPath>..\packages\AvalonEdit.5.0.4\lib\Net40\ICSharpCode.AvalonEdit.dll</HintPath>
@@ -257,6 +253,7 @@
257253
</Reference>
258254
<Reference Include="Microsoft.Expression.Interactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
259255
<HintPath>..\packages\System.Windows.Interactivity.WPF.2.0.20525\lib\net40\Microsoft.Expression.Interactions.dll</HintPath>
256+
<Private>True</Private>
260257
</Reference>
261258
<Reference Include="Microsoft.VB6.Interop.VBIDE">
262259
<HintPath>..\libs\Microsoft.VB6.Interop.VBIDE.dll</HintPath>
@@ -292,6 +289,7 @@
292289
<Reference Include="System.Windows.Forms" />
293290
<Reference Include="System.Windows.Interactivity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
294291
<HintPath>..\packages\System.Windows.Interactivity.WPF.2.0.20525\lib\net40\System.Windows.Interactivity.dll</HintPath>
292+
<Private>True</Private>
295293
</Reference>
296294
<Reference Include="System.Xaml" />
297295
<Reference Include="Microsoft.CSharp" />
@@ -979,7 +977,6 @@
979977
<None Include="app.config">
980978
<SubType>Designer</SubType>
981979
</None>
982-
<None Include="packages.config" />
983980
<EmbeddedResource Include="UI\Controls\vba.xshd" />
984981
</ItemGroup>
985982
<ItemGroup>
@@ -1055,6 +1052,10 @@
10551052
<Resource Include="Resources\blue-folder-horizontal-open.png" />
10561053
<Resource Include="Resources\blue-folder-horizontal.png" />
10571054
<Resource Include="Resources\lock--exclamation.png" />
1055+
<None Include="NLog.xsd">
1056+
<SubType>Designer</SubType>
1057+
</None>
1058+
<None Include="packages.config" />
10581059
<None Include="Properties\Settings.settings">
10591060
<Generator>PublicSettingsSingleFileGenerator</Generator>
10601061
<LastGenOutput>Settings.Designer.cs</LastGenOutput>

Rubberduck.Core/UI/About/AboutControl.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ Ross McLean
124124
Ross Knudsen
125125
Simon Forsberg
126126
Stephen Bullen (Smart Indenter)
127+
Wayne Phillips (vbWatchdog)
127128
</TextBlock>
128129

129130
<TextBlock Text="{Resx ResxName=Rubberduck.UI.RubberduckUI, Key=AboutWindow_GeneralThanks}"
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Antlr4.Runtime;
2+
using Rubberduck.Parsing;
3+
4+
namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection
5+
{
6+
public abstract class ContextWrapperBase
7+
{
8+
protected readonly ParserRuleContext _context;
9+
protected IParseTreeVisitorResults _inspValues;
10+
private readonly IRangeClauseFilterFactory _rangeFilterFactory;
11+
private readonly IParseTreeValueFactory _valueFactory;
12+
13+
public ContextWrapperBase(ParserRuleContext context, IParseTreeVisitorResults inspValues, IUnreachableCaseInspectionFactoryProvider factoryFactory)
14+
{
15+
_context = context;
16+
_rangeFilterFactory = factoryFactory.CreateIRangeClauseFilterFactory();
17+
_valueFactory = factoryFactory.CreateIParseTreeValueFactory();
18+
_inspValues = inspValues;
19+
}
20+
21+
protected IParseTreeValueFactory ValueFactory => _valueFactory;
22+
23+
protected IRangeClauseFilterFactory FilterFactory => _rangeFilterFactory;
24+
25+
public ParserRuleContext Context => _context;
26+
27+
protected IParseTreeVisitorResults ParseTreeValueResults => _inspValues;
28+
}
29+
}
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
using Rubberduck.Parsing.Grammar;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Diagnostics;
5+
6+
namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection
7+
{
8+
public interface IParseTreeExpressionEvaluator
9+
{
10+
IParseTreeValue Evaluate(IParseTreeValue LHS, IParseTreeValue RHS, string opSymbol);
11+
IParseTreeValue Evaluate(IParseTreeValue LHS, string opSymbol, string requestedResultType);
12+
}
13+
14+
public class ParseTreeExpressionEvaluator : IParseTreeExpressionEvaluator
15+
{
16+
private readonly IParseTreeValueFactory _valueFactory;
17+
18+
private static Dictionary<string, Func<double, double, double>> MathOpsBinary = new Dictionary<string, Func<double, double, double>>()
19+
{
20+
[MathSymbols.MULTIPLY] = delegate (double LHS, double RHS) { return LHS * RHS; },
21+
[MathSymbols.DIVIDE] = delegate (double LHS, double RHS) { return LHS / RHS; },
22+
[MathSymbols.INTEGER_DIVIDE] = delegate (double LHS, double RHS) { return Math.Truncate(Convert.ToDouble(Convert.ToInt64(LHS) / Convert.ToInt64(RHS))); },
23+
[MathSymbols.PLUS] = delegate (double LHS, double RHS) { return LHS + RHS; },
24+
[MathSymbols.MINUS] = delegate (double LHS, double RHS) { return LHS - RHS; },
25+
[MathSymbols.EXPONENT] = Math.Pow,
26+
[MathSymbols.MODULO] = delegate (double LHS, double RHS) { return LHS % RHS; },
27+
};
28+
29+
private static Dictionary<string, Func<double, double, bool>> LogicOpsBinary = new Dictionary<string, Func<double, double, bool>>()
30+
{
31+
[LogicSymbols.EQ] = delegate (double LHS, double RHS) { return LHS == RHS; },
32+
[LogicSymbols.NEQ] = delegate (double LHS, double RHS) { return LHS != RHS; },
33+
[LogicSymbols.LT] = delegate (double LHS, double RHS) { return LHS < RHS; },
34+
[LogicSymbols.LTE] = delegate (double LHS, double RHS) { return LHS <= RHS; },
35+
[LogicSymbols.GT] = delegate (double LHS, double RHS) { return LHS > RHS; },
36+
[LogicSymbols.GTE] = delegate (double LHS, double RHS) { return LHS >= RHS; },
37+
[LogicSymbols.AND] = delegate (double LHS, double RHS) { return Convert.ToBoolean(LHS) && Convert.ToBoolean(RHS); },
38+
[LogicSymbols.OR] = delegate (double LHS, double RHS) { return Convert.ToBoolean(LHS) || Convert.ToBoolean(RHS); },
39+
[LogicSymbols.XOR] = delegate (double LHS, double RHS) { return Convert.ToBoolean(LHS) ^ Convert.ToBoolean(RHS); },
40+
[LogicSymbols.EQV] = delegate (double LHS, double RHS) { return Convert.ToBoolean(LHS).Equals(Convert.ToBoolean(RHS)); },
41+
[LogicSymbols.IMP] = delegate (double LHS, double RHS) { return Convert.ToBoolean(LHS).Equals(Convert.ToBoolean(RHS)) || Convert.ToBoolean(RHS); },
42+
};
43+
44+
private static Dictionary<string, Func<double, double>> MathOpsUnary = new Dictionary<string, Func<double, double>>()
45+
{
46+
[MathSymbols.ADDITIVE_INVERSE] = delegate (double value) { return value * -1.0; }
47+
};
48+
49+
private static Dictionary<string, Func<double, bool>> LogicOpsUnary = new Dictionary<string, Func<double, bool>>()
50+
{
51+
[LogicSymbols.NOT] = delegate (double value) { return !(Convert.ToBoolean(value)); }
52+
};
53+
54+
private static List<string> ResultTypeRanking = new List<string>()
55+
{
56+
Tokens.Currency,
57+
Tokens.Double,
58+
Tokens.Single,
59+
Tokens.Long,
60+
Tokens.Integer,
61+
Tokens.Byte,
62+
Tokens.Boolean,
63+
};
64+
65+
public ParseTreeExpressionEvaluator(IParseTreeValueFactory valueFactory)
66+
{
67+
_valueFactory = valueFactory;
68+
}
69+
70+
public IParseTreeValue Evaluate(IParseTreeValue LHS, IParseTreeValue RHS, string opSymbol)
71+
{
72+
var isMathOp = MathOpsBinary.ContainsKey(opSymbol);
73+
var isLogicOp = LogicOpsBinary.ContainsKey(opSymbol);
74+
Debug.Assert(isMathOp || isLogicOp);
75+
76+
var opResultTypeName = isMathOp ? DetermineMathResultType(LHS, RHS) : Tokens.Boolean;
77+
var operands = PrepareOperands(new string[] { LHS.ValueText, RHS.ValueText });
78+
79+
if (operands.Count == 2)
80+
{
81+
if (isMathOp)
82+
{
83+
var mathResult = MathOpsBinary[opSymbol](operands[0], operands[1]);
84+
return _valueFactory.Create(mathResult.ToString(), opResultTypeName);
85+
}
86+
var logicResult = LogicOpsBinary[opSymbol](operands[0], operands[1]);
87+
return _valueFactory.Create(logicResult.ToString(), opResultTypeName);
88+
}
89+
return _valueFactory.Create($"{LHS.ValueText} {opSymbol} {RHS.ValueText}", opResultTypeName);
90+
}
91+
92+
public IParseTreeValue Evaluate(IParseTreeValue value, string opSymbol, string requestedResultType)
93+
{
94+
var isMathOp = MathOpsUnary.ContainsKey(opSymbol);
95+
var isLogicOp = LogicOpsUnary.ContainsKey(opSymbol);
96+
Debug.Assert(isMathOp || isLogicOp);
97+
98+
var operands = PrepareOperands(new string[] { value.ValueText });
99+
if (operands.Count == 1)
100+
{
101+
if (isMathOp)
102+
{
103+
var mathResult = MathOpsUnary[opSymbol](operands[0]);
104+
return _valueFactory.Create(mathResult.ToString(), requestedResultType);
105+
}
106+
107+
//Unary Not (!) operator
108+
if (!value.TypeName.Equals(Tokens.Boolean) && ParseTreeValue.TryConvertValue(value, out long opValue))
109+
{
110+
var bitwiseComplement = ~opValue;
111+
return _valueFactory.Create(Convert.ToBoolean(bitwiseComplement).ToString(), requestedResultType);
112+
}
113+
else if (value.TypeName.Equals(Tokens.Boolean))
114+
{
115+
var logicResult = LogicOpsUnary[opSymbol](operands[0]);
116+
return _valueFactory.Create(logicResult.ToString(), requestedResultType);
117+
}
118+
}
119+
return _valueFactory.Create($"{opSymbol} {value.ValueText}", requestedResultType);
120+
}
121+
122+
private static string DetermineMathResultType(IParseTreeValue LHS, IParseTreeValue RHS)
123+
{
124+
var lhsTypeNameIndex = ResultTypeRanking.FindIndex(el => el.Equals(LHS.TypeName));
125+
var rhsTypeNameIndex = ResultTypeRanking.FindIndex(el => el.Equals(RHS.TypeName));
126+
return lhsTypeNameIndex <= rhsTypeNameIndex ? LHS.TypeName : RHS.TypeName;
127+
}
128+
129+
private static List<double> PrepareOperands(string[] args)
130+
{
131+
var results = new List<double>();
132+
foreach (var arg in args)
133+
{
134+
string parseArg = arg;
135+
if (arg.Equals(Tokens.True) || arg.Equals(Tokens.False))
136+
{
137+
parseArg = arg.Equals(Tokens.True) ? "-1" : "0";
138+
}
139+
140+
if (double.TryParse(parseArg, out double result))
141+
{
142+
results.Add(result);
143+
}
144+
}
145+
return results;
146+
}
147+
}
148+
149+
internal static class MathSymbols
150+
{
151+
private static string _multiply;
152+
private static string _divide;
153+
private static string _plus;
154+
private static string _minusSign;
155+
private static string _exponent;
156+
157+
public static string MULTIPLY => _multiply ?? LoadSymbols(VBAParser.MULT);
158+
public static string DIVIDE => _divide ?? LoadSymbols(VBAParser.DIV);
159+
public static string INTEGER_DIVIDE => @"\";
160+
public static string PLUS => _plus ?? LoadSymbols(VBAParser.PLUS);
161+
public static string MINUS => _minusSign ?? LoadSymbols(VBAParser.MINUS);
162+
public static string ADDITIVE_INVERSE => MINUS;
163+
public static string EXPONENT => _exponent ?? LoadSymbols(VBAParser.POW);
164+
public static string MODULO => Tokens.Mod;
165+
166+
private static string LoadSymbols(int target)
167+
{
168+
_multiply = VBAParser.DefaultVocabulary.GetLiteralName(VBAParser.MULT).Replace("'", "");
169+
_divide = VBAParser.DefaultVocabulary.GetLiteralName(VBAParser.DIV).Replace("'", "");
170+
_plus = VBAParser.DefaultVocabulary.GetLiteralName(VBAParser.PLUS).Replace("'", "");
171+
_minusSign = VBAParser.DefaultVocabulary.GetLiteralName(VBAParser.MINUS).Replace("'", "");
172+
_exponent = VBAParser.DefaultVocabulary.GetLiteralName(VBAParser.POW).Replace("'", "");
173+
return VBAParser.DefaultVocabulary.GetLiteralName(target).Replace("'", "");
174+
}
175+
}
176+
}

0 commit comments

Comments
 (0)