Skip to content

Commit 2b6ac70

Browse files
committed
addressed merge conflict in RubberduckIoCInstaller usings.
2 parents 2ca22eb + 48da45d commit 2b6ac70

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+4609
-145
lines changed

Rubberduck.Core/AddRemoveReferences/ReferenceModel.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Runtime.InteropServices;
66
using System.Runtime.InteropServices.ComTypes;
77
using Rubberduck.Parsing.ComReflection;
8+
using Rubberduck.Parsing.ComReflection.TypeLibReflection;
89
using Rubberduck.VBEditor;
910
using Rubberduck.VBEditor.SafeComWrappers;
1011
using Rubberduck.VBEditor.SafeComWrappers.Abstract;

Rubberduck.Core/AddRemoveReferences/RegisteredLibraryFinderService.cs

Lines changed: 0 additions & 100 deletions
This file was deleted.

Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesPresenterFactory.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Windows.Forms;
66
using NLog;
77
using Rubberduck.AddRemoveReferences;
8+
using Rubberduck.Parsing.ComReflection.TypeLibReflection;
89
using Rubberduck.Parsing.Symbols;
910
using Rubberduck.Parsing.VBA;
1011
using Rubberduck.Settings;
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
using Moq;
2+
using Rubberduck.Resources.Registration;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Reflection;
7+
using System.Runtime.InteropServices;
8+
9+
// ReSharper disable InconsistentNaming
10+
11+
namespace Rubberduck.ComClientLibrary.UnitTesting.Mocks
12+
{
13+
[
14+
ComVisible(true),
15+
Guid(RubberduckGuid.ComMockGuid),
16+
ProgId(RubberduckProgId.ComMockProgId),
17+
ClassInterface(ClassInterfaceType.None),
18+
ComDefaultInterface(typeof(IComMock))
19+
]
20+
public class ComMock : IComMock
21+
{
22+
private readonly ComMocked mocked;
23+
private readonly SetupArgumentResolver _resolver;
24+
private readonly SetupExpressionBuilder _setupBuilder;
25+
private readonly IMockProviderInternal _provider;
26+
27+
internal ComMock(IMockProviderInternal provider, string project, string progId, Mock mock, Type type, IEnumerable<Type> supportedInterfaces)
28+
{
29+
Project = project;
30+
ProgId = progId;
31+
Mock = mock;
32+
_provider = provider;
33+
_resolver = new SetupArgumentResolver();
34+
_setupBuilder = new SetupExpressionBuilder(type, supportedInterfaces, _resolver);
35+
MockedType = type;
36+
37+
Mock.As<IComMocked>().Setup(x => x.Mock).Returns(this);
38+
mocked = new ComMocked(this, supportedInterfaces);
39+
}
40+
41+
public string Project { get; }
42+
43+
public string ProgId { get; }
44+
45+
/// <remarks>
46+
/// Refer to remarks in <see cref="SetupArgumentResolver.ResolveArgs"/> for how the
47+
/// parameter <paramref name="Args"/> is handled.
48+
/// </remarks>
49+
public void SetupWithReturns(string Name, object Value, object Args = null)
50+
{
51+
var args = _resolver.ResolveArgs(Args);
52+
var setupDatas = _setupBuilder.CreateExpression(Name, args);
53+
54+
foreach (var setupData in setupDatas)
55+
{
56+
var builder = MockExpressionBuilder.Create(Mock);
57+
builder.As(setupData.DeclaringType)
58+
.Setup(setupData.SetupExpression, setupData.Args, setupData.ReturnType)
59+
.Returns(Value, setupData.ReturnType)
60+
.Execute();
61+
}
62+
}
63+
64+
/// <remarks>
65+
/// Refer to remarks in <see cref="SetupArgumentResolver.ResolveArgs"/> for how the
66+
/// parameter <paramref name="Args"/> is handled.
67+
/// </remarks>
68+
public void SetupWithCallback(string Name, Action Callback, object Args = null)
69+
{
70+
var args = _resolver.ResolveArgs(Args);
71+
var setupDatas = _setupBuilder.CreateExpression(Name, args);
72+
73+
foreach (var setupData in setupDatas)
74+
{
75+
var builder = MockExpressionBuilder.Create(Mock);
76+
builder.As(setupData.DeclaringType)
77+
.Setup(setupData.SetupExpression, setupData.Args)
78+
.Callback(Callback)
79+
.Execute();
80+
}
81+
}
82+
83+
public IComMock SetupChildMock(string Name, object Args)
84+
{
85+
Type type;
86+
var memberInfo = MockedType.GetMember(Name).FirstOrDefault();
87+
if (memberInfo == null)
88+
{
89+
memberInfo = MockedType.GetInterfaces().SelectMany(face => face.GetMember(Name)).First();
90+
}
91+
92+
switch (memberInfo)
93+
{
94+
case FieldInfo fieldInfo:
95+
type = fieldInfo.FieldType;
96+
break;
97+
case PropertyInfo propertyInfo:
98+
type = propertyInfo.PropertyType;
99+
break;
100+
case MethodInfo methodInfo:
101+
type = methodInfo.ReturnType;
102+
break;
103+
default:
104+
throw new InvalidOperationException($"Couldn't resolve member {Name} and acquire a type to mock.");
105+
}
106+
107+
var childMock = _provider.MockChildObject(this, type);
108+
var target = GetMockedObject(childMock, type);
109+
SetupWithReturns(Name, target, Args);
110+
111+
return childMock;
112+
}
113+
114+
private object GetMockedObject(IComMock mock, Type type)
115+
{
116+
var pUnkSource = IntPtr.Zero;
117+
var pUnkTarget = IntPtr.Zero;
118+
119+
try
120+
{
121+
pUnkSource = Marshal.GetIUnknownForObject(mock.Object);
122+
var iid = type.GUID;
123+
Marshal.QueryInterface(pUnkSource, ref iid, out pUnkTarget);
124+
return Marshal.GetTypedObjectForIUnknown(pUnkTarget, type);
125+
}
126+
finally
127+
{
128+
if (pUnkTarget != IntPtr.Zero) Marshal.Release(pUnkTarget);
129+
if (pUnkSource != IntPtr.Zero) Marshal.Release(pUnkSource);
130+
}
131+
}
132+
133+
public object Object => mocked;
134+
135+
internal Mock Mock { get; }
136+
137+
internal Type MockedType { get; }
138+
}
139+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Runtime.InteropServices;
5+
using Moq;
6+
using NLog;
7+
using Rubberduck.Resources.Registration;
8+
9+
namespace Rubberduck.ComClientLibrary.UnitTesting.Mocks
10+
{
11+
[
12+
ComVisible(true),
13+
Guid(RubberduckGuid.IComMockedGuid),
14+
InterfaceType(ComInterfaceType.InterfaceIsDual)
15+
]
16+
public interface IComMocked : IMocked
17+
{
18+
new ComMock Mock { get; }
19+
}
20+
21+
[
22+
ComVisible(true),
23+
Guid(RubberduckGuid.ComMockedGuid),
24+
ProgId(RubberduckProgId.ComMockedProgId),
25+
ClassInterface(ClassInterfaceType.None),
26+
ComDefaultInterface(typeof(IComMocked))
27+
]
28+
public class ComMocked : IComMocked, ICustomQueryInterface
29+
{
30+
private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();
31+
private readonly IEnumerable<Type> _supportedInterfaces;
32+
33+
// Not using auto-property as that leads to ambiguity. For COM compatibility,
34+
// this backs the public field `Mock`, which hides the `Moq.IMocked.Mock`
35+
// property that returns a non-COM-visible `Moq.Mock` object.
36+
private readonly ComMock _comMock;
37+
38+
internal ComMocked(ComMock mock, IEnumerable<Type> supportedInterfaces)
39+
{
40+
_comMock = mock;
41+
_supportedInterfaces = supportedInterfaces;
42+
}
43+
44+
public CustomQueryInterfaceResult GetInterface(ref Guid iid, out IntPtr ppv)
45+
{
46+
try
47+
{
48+
var result = IntPtr.Zero;
49+
var searchIid = iid; // Cannot use ref parameters directly in LINQ
50+
51+
if (iid == new Guid(RubberduckGuid.ComMockedGuid) || iid == new Guid(RubberduckGuid.IComMockedGuid))
52+
{
53+
result = Marshal.GetIUnknownForObject(this);
54+
}
55+
else if (iid == new Guid(RubberduckGuid.IID_IDispatch) && !string.IsNullOrWhiteSpace(Mock.Project))
56+
{
57+
// We cannot return IDispatch directly for VBA types but we can return the IUnknown in its place,
58+
// which is sufficient for COM's needs.
59+
60+
var pObject = Marshal.GetComInterfaceForObject(_comMock.Mock.Object, _comMock.MockedType);
61+
searchIid = new Guid(RubberduckGuid.IID_IUnknown);
62+
var hr = Marshal.QueryInterface(pObject, ref searchIid, out result);
63+
Marshal.Release(pObject);
64+
if (hr < 0)
65+
{
66+
ppv = IntPtr.Zero;
67+
return CustomQueryInterfaceResult.Failed;
68+
}
69+
}
70+
else
71+
{
72+
// Apparently some COM objects have multiple interface implementations using same GUID
73+
// so first result should suffice to avoid exception when using single.
74+
var type = _supportedInterfaces.FirstOrDefault(x => x.GUID == searchIid);
75+
if (type != null)
76+
{
77+
// Ensure that we return the actual Moq.Mock.Object, not the ComMocked object.
78+
result = Marshal.GetComInterfaceForObject(_comMock.Mock.Object, type);
79+
}
80+
}
81+
82+
ppv = result;
83+
return result == IntPtr.Zero
84+
? CustomQueryInterfaceResult.NotHandled
85+
: CustomQueryInterfaceResult.Handled;
86+
}
87+
catch (Exception ex)
88+
{
89+
Logger.Warn(ex, $"Failed to perform IQueryInterface call on {nameof(ComMocked)}. IID requested was {{{iid}}}.");
90+
ppv = IntPtr.Zero;
91+
return CustomQueryInterfaceResult.Failed;
92+
}
93+
}
94+
95+
// ReSharper disable once ConvertToAutoPropertyWhenPossible -- Leads to ambiguous naming; see comments above
96+
public ComMock Mock => _comMock;
97+
98+
Mock IMocked.Mock => _comMock.Mock;
99+
}
100+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using Rubberduck.Resources.Registration;
4+
5+
// ReSharper disable InconsistentNaming
6+
7+
namespace Rubberduck.ComClientLibrary.UnitTesting.Mocks
8+
{
9+
[
10+
ComVisible(true),
11+
Guid(RubberduckGuid.IComMockGuid),
12+
InterfaceType(ComInterfaceType.InterfaceIsDual)
13+
]
14+
public interface IComMock
15+
{
16+
[DispId(1)]
17+
object Object { [return: MarshalAs(UnmanagedType.IDispatch)] get; }
18+
19+
[DispId(2)]
20+
void SetupWithReturns(string Name, [MarshalAs(UnmanagedType.Struct)] object Value, [Optional, MarshalAs(UnmanagedType.Struct)] object Args);
21+
22+
[DispId(3)]
23+
void SetupWithCallback(string Name, [MarshalAs(UnmanagedType.FunctionPtr)] Action Callback, [Optional, MarshalAs(UnmanagedType.Struct)] object Args);
24+
25+
[DispId(4)]
26+
IComMock SetupChildMock(string Name, [Optional, MarshalAs(UnmanagedType.Struct)] object Args);
27+
28+
[DispId(5)]
29+
string Project { get; }
30+
31+
[DispId(6)]
32+
string ProgId { get; }
33+
}
34+
}

0 commit comments

Comments
 (0)