Skip to content

Commit c5ec039

Browse files
committed
Merge branch 'next' into FixNegLineNumberDetectedInGoToNegOne
2 parents 6cb105d + 136889f commit c5ec039

File tree

10 files changed

+387
-131
lines changed

10 files changed

+387
-131
lines changed

Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesWindow.xaml.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ private void ListView_SynchronizeCurrentSelection_OnGotFocus(object sender, Rout
2121
UpdateCurrentSelection((Selector)sender);
2222

2323
var cs = ViewModel.CurrentSelection;
24-
Description.Text = cs.Description;
25-
Version.Text = cs.Version;
26-
LocaleName.Text = cs.LocaleName;
27-
FullPath.Text = cs.FullPath;
24+
Description.Text = cs?.Description ?? string.Empty;
25+
Version.Text = cs?.Version ?? string.Empty;
26+
LocaleName.Text = cs?.LocaleName ?? string.Empty;
27+
FullPath.Text = cs?.FullPath ?? string.Empty;
2828
}
2929

3030
private void UpdateCurrentSelection(Selector sender)

Rubberduck.Main/ComClientLibrary/UnitTesting/PermissiveAssertClass.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,14 @@ public class PermissiveAssertClass : AssertClass
3131
/// </remarks>
3232
public override void AreEqual(object expected, object actual, string message = "")
3333
{
34-
// vbNullString is marshalled as null. assume value semantics:
35-
expected = expected ?? string.Empty;
36-
actual = actual ?? string.Empty;
37-
38-
if (!PermissiveComparer.Equals(expected, actual))
34+
if (PermissiveComparer.Equals(expected, actual))
35+
{
36+
AssertHandler.OnAssertSucceeded();
37+
}
38+
else
3939
{
4040
AssertHandler.OnAssertFailed(message);
4141
}
42-
AssertHandler.OnAssertSucceeded();
4342
}
4443

4544
public override void AreNotEqual(object expected, object actual, string message = "")

Rubberduck.Parsing/Preprocessing/VBAConditionalCompilationParser.g4

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@ ccBlock :
1010
(ccConst | ccIfBlock | physicalLine)*?
1111
;
1212

13-
ccConst : WS* hashConst WS+ ccVarLhs WS* EQ WS* ccExpression ccEol;
13+
ccConst : whiteSpace* hashConst whiteSpace+ ccVarLhs whiteSpace* EQ whiteSpace* ccExpression ccEol;
1414
ccVarLhs : name;
1515

1616
ccIfBlock : ccIf ccBlock ccElseIfBlock* ccElseBlock? ccEndIf;
17-
ccIf : WS* hashIf WS+ ccExpression WS+ THEN ccEol;
17+
ccIf : whiteSpace* hashIf whiteSpace+ ccExpression whiteSpace+ THEN ccEol;
1818
ccElseIfBlock : ccElseIf ccBlock;
19-
ccElseIf : WS* hashElseIf WS+ ccExpression WS+ THEN ccEol;
19+
ccElseIf : whiteSpace* hashElseIf whiteSpace+ ccExpression whiteSpace+ THEN ccEol;
2020
ccElseBlock : ccElse ccBlock;
21-
ccElse : WS* hashElse ccEol;
22-
ccEndIf : WS* hashEndIf ccEol;
23-
ccEol : WS* comment? (NEWLINE | EOF);
21+
ccElse : whiteSpace* hashElse ccEol;
22+
ccEndIf : whiteSpace* hashEndIf ccEol;
23+
ccEol : whiteSpace* comment? (NEWLINE | EOF);
2424
// We use parser rules instead of tokens (such as HASHCONST) because
2525
// marked file numbers have a similar format and cause conflicts.
2626
hashConst : HASH CONST;
@@ -32,26 +32,26 @@ hashEndIf : HASH END_IF;
3232
physicalLine : ~(NEWLINE | EOF)* (NEWLINE | EOF);
3333

3434
ccExpression :
35-
LPAREN WS* ccExpression WS* RPAREN
36-
| ccExpression WS* POW WS* ccExpression
37-
| MINUS WS* ccExpression
38-
| ccExpression WS* (MULT | DIV) WS* ccExpression
39-
| ccExpression WS* INTDIV WS* ccExpression
40-
| ccExpression WS* MOD WS* ccExpression
41-
| ccExpression WS* (PLUS | MINUS) WS* ccExpression
42-
| ccExpression WS* AMPERSAND WS* ccExpression
43-
| ccExpression WS* (EQ | NEQ | LT | GT | LEQ | GEQ | LIKE | IS) WS* ccExpression
44-
| NOT WS* ccExpression
45-
| ccExpression WS* AND WS* ccExpression
46-
| ccExpression WS* OR WS* ccExpression
47-
| ccExpression WS* XOR WS* ccExpression
48-
| ccExpression WS* EQV WS* ccExpression
49-
| ccExpression WS* IMP WS* ccExpression
35+
LPAREN whiteSpace* ccExpression whiteSpace* RPAREN
36+
| ccExpression whiteSpace* POW whiteSpace* ccExpression
37+
| MINUS whiteSpace* ccExpression
38+
| ccExpression whiteSpace* (MULT | DIV) whiteSpace* ccExpression
39+
| ccExpression whiteSpace* INTDIV whiteSpace* ccExpression
40+
| ccExpression whiteSpace* MOD whiteSpace* ccExpression
41+
| ccExpression whiteSpace* (PLUS | MINUS) whiteSpace* ccExpression
42+
| ccExpression whiteSpace* AMPERSAND whiteSpace* ccExpression
43+
| ccExpression whiteSpace* (EQ | NEQ | LT | GT | LEQ | GEQ | LIKE | IS) whiteSpace* ccExpression
44+
| NOT whiteSpace* ccExpression
45+
| ccExpression whiteSpace* AND whiteSpace* ccExpression
46+
| ccExpression whiteSpace* OR whiteSpace* ccExpression
47+
| ccExpression whiteSpace* XOR whiteSpace* ccExpression
48+
| ccExpression whiteSpace* EQV whiteSpace* ccExpression
49+
| ccExpression whiteSpace* IMP whiteSpace* ccExpression
5050
| intrinsicFunction
5151
| literal
5252
| name;
5353

54-
intrinsicFunction : intrinsicFunctionName LPAREN WS* ccExpression WS* RPAREN;
54+
intrinsicFunction : intrinsicFunctionName LPAREN whiteSpace* ccExpression whiteSpace* RPAREN;
5555

5656
intrinsicFunctionName :
5757
INT
@@ -270,4 +270,6 @@ statementKeyword :
270270
| WEND
271271
| WHILE
272272
| WITH
273-
;
273+
;
274+
275+
whiteSpace : (WS | LINE_CONTINUATION)+;

Rubberduck.UnitTesting/ComClientHelpers/PermissiveObjectComparer.cs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,7 @@ public class PermissiveObjectComparer : IEqualityComparer<object>
1414
/// <returns>VBA equity</returns>
1515
public new bool Equals(object x, object y)
1616
{
17-
if (x == null)
18-
{
19-
return y == null;
20-
}
21-
22-
if (y == null)
23-
{
24-
return false;
25-
}
26-
27-
var converted = VariantConverter.ChangeType(y, x.GetType());
28-
29-
return x.Equals(converted);
17+
return VariantComparer.Compare(x, y) == VariantComparisonResults.VARCMP_EQ;
3018
}
3119

3220
/// <summary>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Globalization;
2+
3+
namespace Rubberduck.VBEditor.Variants
4+
{
5+
public static class VariantComparer
6+
{
7+
public static VariantComparisonResults Compare(object x, object y)
8+
{
9+
return Compare(x, y, VariantComparisonFlags.NORM_IGNORECASE);
10+
}
11+
12+
public static VariantComparisonResults Compare(object x, object y, VariantComparisonFlags flags)
13+
{
14+
return Compare(x, y, CultureInfo.InvariantCulture.LCID, flags);
15+
}
16+
17+
public static VariantComparisonResults Compare(object x, object y, int lcid, VariantComparisonFlags flags)
18+
{
19+
object dy;
20+
try
21+
{
22+
dy = VariantConverter.ChangeType(y, x.GetType());
23+
}
24+
catch
25+
{
26+
dy = y;
27+
}
28+
return (VariantComparisonResults)VariantNativeMethods.VarCmp(ref x, ref dy, lcid, (uint)flags);
29+
}
30+
}
31+
}

Rubberduck.VBEEditor/Variants/VariantConverter.cs

Lines changed: 3 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -4,56 +4,6 @@
44

55
namespace Rubberduck.VBEditor.Variants
66
{
7-
public enum VARENUM
8-
{
9-
VT_EMPTY = 0x0000,
10-
VT_NULL = 0x0001,
11-
VT_I2 = 0x0002,
12-
VT_I4 = 0x0003,
13-
VT_R4 = 0x0004,
14-
VT_R8 = 0x0005,
15-
VT_CY = 0x0006,
16-
VT_DATE = 0x0007,
17-
VT_BSTR = 0x0008,
18-
VT_DISPATCH = 0x0009,
19-
VT_ERROR = 0x000A,
20-
VT_BOOL = 0x000B,
21-
VT_VARIANT = 0x000C,
22-
VT_UNKNOWN = 0x000D,
23-
VT_DECIMAL = 0x000E,
24-
VT_I1 = 0x0010,
25-
VT_UI1 = 0x0011,
26-
VT_UI2 = 0x0012,
27-
VT_UI4 = 0x0013,
28-
VT_I8 = 0x0014,
29-
VT_UI8 = 0x0015,
30-
VT_INT = 0x0016,
31-
VT_UINT = 0x0017,
32-
VT_VOID = 0x0018,
33-
VT_HRESULT = 0x0019,
34-
VT_PTR = 0x001A,
35-
VT_SAFEARRAY = 0x001B,
36-
VT_CARRAY = 0x001C,
37-
VT_USERDEFINED = 0x001D,
38-
VT_LPSTR = 0x001E,
39-
VT_LPWSTR = 0x001F,
40-
VT_RECORD = 0x0024,
41-
VT_INT_PTR = 0x0025,
42-
VT_UINT_PTR = 0x0026,
43-
VT_ARRAY = 0x2000,
44-
VT_BYREF = 0x4000
45-
}
46-
47-
[Flags]
48-
public enum VariantConversionFlags : ushort
49-
{
50-
NO_FLAGS = 0x00,
51-
VARIANT_NOVALUEPROP = 0x01, //Prevents the function from attempting to coerce an object to a fundamental type by getting the Value property. Applications should set this flag only if necessary, because it makes their behavior inconsistent with other applications.
52-
VARIANT_ALPHABOOL = 0x02, //Converts a VT_BOOL value to a string containing either "True" or "False".
53-
VARIANT_NOUSEROVERRIDE = 0x04, //For conversions to or from VT_BSTR, passes LOCALE_NOUSEROVERRIDE to the core coercion routines.
54-
VARIANT_LOCALBOOL = 0x08 //For conversions from VT_BOOL to VT_BSTR and back, uses the language specified by the locale in use on the local computer.
55-
}
56-
577
/// <summary>
588
/// Handles variant conversions, enabling us to have same implicit conversion behaviors within
599
/// .NET as we can observe it from VBA/VB6.
@@ -67,40 +17,18 @@ public enum VariantConversionFlags : ushort
6717
/// </remarks>
6818
public static class VariantConverter
6919
{
70-
private const string dllName = "oleaut32.dll";
71-
72-
// HRESULT VariantChangeType(
73-
// VARIANTARG *pvargDest,
74-
// const VARIANTARG *pvarSrc,
75-
// USHORT wFlags,
76-
// VARTYPE vt
77-
// );
78-
[DllImport(dllName, EntryPoint = "VariantChangeType", CharSet = CharSet.Auto, SetLastError = true, PreserveSig = true)]
79-
private static extern int VariantChangeType(ref object pvargDest, ref object pvarSrc, VariantConversionFlags wFlags, VARENUM vt);
80-
81-
// HRESULT VariantChangeTypeEx(
82-
// VARIANTARG *pvargDest,
83-
// const VARIANTARG *pvarSrc,
84-
// LCID lcid,
85-
// USHORT wFlags,
86-
// VARTYPE vt
87-
// );
88-
[DllImport(dllName, EntryPoint = "VariantChangeTypeEx", CharSet = CharSet.Auto, SetLastError = true, PreserveSig = true)]
89-
private static extern int VariantChangeTypeEx(ref object pvargDest, ref object pvarSrc, int lcid, VariantConversionFlags wFlags, VARENUM vt);
90-
9120
public static object ChangeType(object value, VARENUM vt)
9221
{
9322
return ChangeType(value, vt, null);
9423
}
9524

96-
private static bool HRESULT_FAILED(int hr) => hr < 0;
9725
public static object ChangeType(object value, VARENUM vt, CultureInfo cultureInfo)
9826
{
9927
object result = null;
10028
var hr = cultureInfo == null
101-
? VariantChangeType(ref result, ref value, VariantConversionFlags.NO_FLAGS, vt)
102-
: VariantChangeTypeEx(ref result, ref value, cultureInfo.LCID, VariantConversionFlags.NO_FLAGS, vt);
103-
if (HRESULT_FAILED(hr))
29+
? VariantNativeMethods.VariantChangeType(ref result, ref value, VariantConversionFlags.NO_FLAGS, vt)
30+
: VariantNativeMethods.VariantChangeTypeEx(ref result, ref value, cultureInfo.LCID, VariantConversionFlags.NO_FLAGS, vt);
31+
if (HResult.Failed(hr))
10432
{
10533
throw Marshal.GetExceptionForHR(hr);
10634
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace Rubberduck.VBEditor.Variants
5+
{
6+
public enum VARENUM
7+
{
8+
VT_EMPTY = 0x0000,
9+
VT_NULL = 0x0001,
10+
VT_I2 = 0x0002,
11+
VT_I4 = 0x0003,
12+
VT_R4 = 0x0004,
13+
VT_R8 = 0x0005,
14+
VT_CY = 0x0006,
15+
VT_DATE = 0x0007,
16+
VT_BSTR = 0x0008,
17+
VT_DISPATCH = 0x0009,
18+
VT_ERROR = 0x000A,
19+
VT_BOOL = 0x000B,
20+
VT_VARIANT = 0x000C,
21+
VT_UNKNOWN = 0x000D,
22+
VT_DECIMAL = 0x000E,
23+
VT_I1 = 0x0010,
24+
VT_UI1 = 0x0011,
25+
VT_UI2 = 0x0012,
26+
VT_UI4 = 0x0013,
27+
VT_I8 = 0x0014,
28+
VT_UI8 = 0x0015,
29+
VT_INT = 0x0016,
30+
VT_UINT = 0x0017,
31+
VT_VOID = 0x0018,
32+
VT_HRESULT = 0x0019,
33+
VT_PTR = 0x001A,
34+
VT_SAFEARRAY = 0x001B,
35+
VT_CARRAY = 0x001C,
36+
VT_USERDEFINED = 0x001D,
37+
VT_LPSTR = 0x001E,
38+
VT_LPWSTR = 0x001F,
39+
VT_RECORD = 0x0024,
40+
VT_INT_PTR = 0x0025,
41+
VT_UINT_PTR = 0x0026,
42+
VT_ARRAY = 0x2000,
43+
VT_BYREF = 0x4000
44+
}
45+
46+
[Flags]
47+
public enum VariantConversionFlags : ushort
48+
{
49+
NO_FLAGS = 0x00,
50+
VARIANT_NOVALUEPROP = 0x01, //Prevents the function from attempting to coerce an object to a fundamental type by getting the Value property. Applications should set this flag only if necessary, because it makes their behavior inconsistent with other applications.
51+
VARIANT_ALPHABOOL = 0x02, //Converts a VT_BOOL value to a string containing either "True" or "False".
52+
VARIANT_NOUSEROVERRIDE = 0x04, //For conversions to or from VT_BSTR, passes LOCALE_NOUSEROVERRIDE to the core coercion routines.
53+
VARIANT_LOCALBOOL = 0x08 //For conversions from VT_BOOL to VT_BSTR and back, uses the language specified by the locale in use on the local computer.
54+
}
55+
56+
[Flags]
57+
public enum VariantComparisonFlags : ulong
58+
{
59+
NO_FLAGS = 0x00,
60+
NORM_IGNORECASE = 0x00000001, //Ignore case.
61+
NORM_IGNORENONSPACE = 0x00000002, //Ignore nonspace characters.
62+
NORM_IGNORESYMBOLS = 0x00000004, //Ignore symbols.
63+
NORM_IGNOREWIDTH = 0x00000008, //Ignore string width.
64+
NORM_IGNOREKANATYPE = 0x00000040, //Ignore Kana type.
65+
NORM_IGNOREKASHIDA = 0x00040000 //Ignore Arabic kashida characters.
66+
}
67+
68+
public enum VariantComparisonResults : int
69+
{
70+
VARCMP_LT = 0, //pvarLeft is less than pvarRight.
71+
VARCMP_EQ = 1, //The parameters are equal.
72+
VARCMP_GT = 2, //pvarLeft is greater than pvarRight.
73+
VARCMP_NULL = 3 //Either expression is NULL.
74+
}
75+
76+
public static class HResult
77+
{
78+
internal static bool Succeeded(int hr) => hr >= 0;
79+
internal static bool Failed(int hr) => hr < 0;
80+
}
81+
82+
internal static class VariantNativeMethods
83+
{
84+
private const string dllName = "oleaut32.dll";
85+
86+
// HRESULT VariantChangeType(
87+
// VARIANTARG *pvargDest,
88+
// const VARIANTARG *pvarSrc,
89+
// USHORT wFlags,
90+
// VARTYPE vt
91+
// );
92+
[DllImport(dllName, EntryPoint = "VariantChangeType", CharSet = CharSet.Auto, SetLastError = true, PreserveSig = true)]
93+
internal static extern int VariantChangeType(ref object pvargDest, ref object pvarSrc, VariantConversionFlags wFlags, VARENUM vt);
94+
95+
// HRESULT VariantChangeTypeEx(
96+
// VARIANTARG *pvargDest,
97+
// const VARIANTARG *pvarSrc,
98+
// LCID lcid,
99+
// USHORT wFlags,
100+
// VARTYPE vt
101+
// );
102+
[DllImport(dllName, EntryPoint = "VariantChangeTypeEx", CharSet = CharSet.Auto, SetLastError = true, PreserveSig = true)]
103+
internal static extern int VariantChangeTypeEx(ref object pvargDest, ref object pvarSrc, int lcid, VariantConversionFlags wFlags, VARENUM vt);
104+
105+
// HRESULT VarCmp(
106+
// LPVARIANT pvarLeft,
107+
// LPVARIANT pvarRight,
108+
// LCID lcid,
109+
// ULONG dwFlags
110+
// );
111+
[DllImport(dllName, EntryPoint = "VarCmp", CharSet = CharSet.Auto, SetLastError = true, PreserveSig = true)]
112+
internal static extern int VarCmp(ref object pvarLeft, ref object pvarRight, int lcid, ulong dwFlags);
113+
}
114+
}

0 commit comments

Comments
 (0)