Skip to content

Commit 9e4076e

Browse files
Hosch250retailcoder
authored andcommitted
Make COM declaration collector discover events (#1687)
* Get parser off UI thread. * Close #1630
1 parent 4d62c33 commit 9e4076e

File tree

4 files changed

+128
-28
lines changed

4 files changed

+128
-28
lines changed

Rubberduck.Parsing/Rubberduck.Parsing.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
<Reference Include="Antlr4.Runtime.net45">
4646
<HintPath>..\packages\Antlr4.Runtime.4.3.0\lib\net45\Antlr4.Runtime.net45.dll</HintPath>
4747
</Reference>
48+
<Reference Include="Microsoft.Build.Tasks.v4.0" />
4849
<Reference Include="Microsoft.Vbe.Interop, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c">
4950
<SpecificVersion>False</SpecificVersion>
5051
<EmbedInteropTypes>False</EmbedInteropTypes>
@@ -126,6 +127,7 @@
126127
<Compile Include="Preprocessing\VBAConditionalCompilationParserBaseVisitor.cs" />
127128
<Compile Include="Preprocessing\VBAConditionalCompilationParserListener.cs" />
128129
<Compile Include="Preprocessing\VBAConditionalCompilationParserVisitor.cs" />
130+
<Compile Include="Symbols\ComInformation.cs" />
129131
<Compile Include="Symbols\Identifier.cs" />
130132
<Compile Include="Binding\IBindingContext.cs" />
131133
<Compile Include="Binding\IBoundExpression.cs" />
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System.Runtime.InteropServices.ComTypes;
2+
using Rubberduck.VBEditor;
3+
4+
namespace Rubberduck.Parsing.Symbols
5+
{
6+
public class ComInformation
7+
{
8+
public ComInformation(TYPEATTR typeAttributes, IMPLTYPEFLAGS implTypeFlags, ITypeInfo typeInfo, string typeName, QualifiedModuleName typeModuleName, Declaration moduleDeclaration, DeclarationType typeDeclarationType)
9+
{
10+
TypeAttributes = typeAttributes;
11+
ImplTypeFlags = implTypeFlags;
12+
TypeInfo = typeInfo;
13+
TypeName = typeName;
14+
TypeQualifiedModuleName = typeModuleName;
15+
ModuleDeclaration = moduleDeclaration;
16+
TypeDeclarationType = typeDeclarationType;
17+
}
18+
19+
public TYPEATTR TypeAttributes { get; internal set; }
20+
public IMPLTYPEFLAGS ImplTypeFlags { get; internal set; }
21+
public ITypeInfo TypeInfo { get; internal set; }
22+
23+
public string TypeName { get; internal set; }
24+
public QualifiedModuleName TypeQualifiedModuleName { get; internal set; }
25+
public Declaration ModuleDeclaration { get; internal set; }
26+
public DeclarationType TypeDeclarationType { get; internal set; }
27+
28+
public override string ToString()
29+
{
30+
return ModuleDeclaration.IdentifierName;
31+
}
32+
}
33+
}

Rubberduck.Parsing/Symbols/ReferencedDeclarationsCollector.cs

Lines changed: 92 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@
1919
using VARDESC = System.Runtime.InteropServices.ComTypes.VARDESC;
2020
using Rubberduck.Parsing.Annotations;
2121
using Rubberduck.Parsing.Grammar;
22+
using IMPLTYPEFLAGS = System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS;
23+
using System.Linq;
2224

2325
namespace Rubberduck.Parsing.Symbols
2426
{
2527
public class ReferencedDeclarationsCollector
2628
{
29+
private readonly RubberduckParserState _state;
30+
2731
/// <summary>
2832
/// Controls how a type library is registered.
2933
/// </summary>
@@ -43,9 +47,13 @@ private enum REGKIND
4347
REGKIND_NONE = 2
4448
}
4549

46-
4750
[DllImport("oleaut32.dll", CharSet = CharSet.Unicode)]
48-
private static extern Int32 LoadTypeLibEx(string strTypeLibName, REGKIND regKind, out ITypeLib TypeLib);
51+
private static extern int LoadTypeLibEx(string strTypeLibName, REGKIND regKind, out ITypeLib TypeLib);
52+
53+
public ReferencedDeclarationsCollector(RubberduckParserState state)
54+
{
55+
_state = state;
56+
}
4957

5058
private static readonly IDictionary<VarEnum, string> TypeNames = new Dictionary<VarEnum, string>
5159
{
@@ -77,6 +85,8 @@ private enum REGKIND
7785
{VarEnum.VT_R8, "Double"},
7886
};
7987

88+
private readonly Dictionary<Guid, ComInformation> _comInformation = new Dictionary<Guid, ComInformation>();
89+
8090
private string GetTypeName(TYPEDESC desc, ITypeInfo info)
8191
{
8292
var vt = (VarEnum)desc.vt;
@@ -224,68 +234,93 @@ public List<Declaration> GetDeclarationsForReference(Reference reference)
224234
moduleDeclaration = new Declaration(
225235
typeQualifiedMemberName,
226236
pseudoParentModule,
227-
pseudoParentModule,
237+
pseudoParentModule,
228238
typeName,
229239
null,
230-
false,
231-
false,
240+
false,
241+
false,
232242
Accessibility.Global,
233243
typeDeclarationType,
234-
null,
244+
null,
235245
Selection.Home,
236246
false,
237247
null,
238-
true,
239-
null,
248+
true,
249+
null,
240250
attributes);
241251
break;
242252
}
253+
ComInformation comInfo;
254+
if (_comInformation.TryGetValue(typeAttributes.guid, out comInfo))
255+
{
256+
comInfo.TypeQualifiedModuleName = typeQualifiedModuleName;
257+
comInfo.ModuleDeclaration = moduleDeclaration;
258+
comInfo.TypeDeclarationType = typeDeclarationType;
259+
}
260+
else
261+
{
262+
_comInformation.Add(typeAttributes.guid,
263+
new ComInformation(typeAttributes, 0, info, typeName, typeQualifiedModuleName, moduleDeclaration,
264+
typeDeclarationType));
265+
}
266+
243267
info.ReleaseTypeAttr(typeAttributesPointer);
244268

245269
output.Add(moduleDeclaration);
270+
}
246271

247-
for (var memberIndex = 0; memberIndex < typeAttributes.cFuncs; memberIndex++)
272+
foreach (var member in _comInformation.Values)
273+
{
274+
for (var memberIndex = 0; memberIndex < member.TypeAttributes.cFuncs; memberIndex++)
248275
{
249276
string[] memberNames;
250277

251278
IntPtr memberDescriptorPointer;
252-
info.GetFuncDesc(memberIndex, out memberDescriptorPointer);
279+
member.TypeInfo.GetFuncDesc(memberIndex, out memberDescriptorPointer);
253280
var memberDescriptor = (FUNCDESC)Marshal.PtrToStructure(memberDescriptorPointer, typeof(FUNCDESC));
254-
var memberDeclaration = CreateMemberDeclaration(memberDescriptor, typeAttributes.typekind, info, memberIndex, typeQualifiedModuleName, moduleDeclaration, out memberNames);
281+
282+
var memberDeclaration = CreateMemberDeclaration(memberDescriptor, member.TypeAttributes.typekind, member.TypeInfo, member.ImplTypeFlags,
283+
member.TypeQualifiedModuleName, member.ModuleDeclaration, out memberNames);
255284
if (memberDeclaration == null)
256285
{
257-
info.ReleaseFuncDesc(memberDescriptorPointer);
286+
member.TypeInfo.ReleaseFuncDesc(memberDescriptorPointer);
258287
continue;
259288
}
260-
if (moduleDeclaration.DeclarationType == DeclarationType.ClassModule && memberDeclaration is ICanBeDefaultMember && ((ICanBeDefaultMember)memberDeclaration).IsDefaultMember)
289+
if (member.ModuleDeclaration.DeclarationType == DeclarationType.ClassModule &&
290+
memberDeclaration is ICanBeDefaultMember &&
291+
((ICanBeDefaultMember)memberDeclaration).IsDefaultMember)
261292
{
262-
((ClassModuleDeclaration)moduleDeclaration).DefaultMember = memberDeclaration;
293+
((ClassModuleDeclaration)member.ModuleDeclaration).DefaultMember = memberDeclaration;
263294
}
264295
output.Add(memberDeclaration);
265296

266-
var parameterCount = memberDescriptor.cParams - (memberDescriptor.invkind.HasFlag(INVOKEKIND.INVOKE_PROPERTYGET) ? 0 : 1);
297+
var parameterCount = memberDescriptor.cParams -
298+
(memberDescriptor.invkind.HasFlag(INVOKEKIND.INVOKE_PROPERTYGET) ? 0 : 1);
267299
for (var paramIndex = 0; paramIndex < parameterCount; paramIndex++)
268300
{
269-
var parameter = CreateParameterDeclaration(memberNames, paramIndex, memberDescriptor, typeQualifiedModuleName, memberDeclaration, info);
301+
var parameter = CreateParameterDeclaration(memberNames, paramIndex, memberDescriptor,
302+
member.TypeQualifiedModuleName, memberDeclaration, member.TypeInfo);
270303
var declaration = memberDeclaration as IDeclarationWithParameter;
271304
if (declaration != null)
272305
{
273306
declaration.AddParameter(parameter);
274307
}
275308
output.Add(parameter);
276309
}
277-
info.ReleaseFuncDesc(memberDescriptorPointer);
310+
member.TypeInfo.ReleaseFuncDesc(memberDescriptorPointer);
278311
}
279312

280-
for (var fieldIndex = 0; fieldIndex < typeAttributes.cVars; fieldIndex++)
313+
for (var fieldIndex = 0; fieldIndex < member.TypeAttributes.cVars; fieldIndex++)
281314
{
282-
output.Add(CreateFieldDeclaration(info, fieldIndex, typeDeclarationType, typeQualifiedModuleName, moduleDeclaration));
315+
output.Add(CreateFieldDeclaration(member.TypeInfo, fieldIndex, member.TypeDeclarationType, member.TypeQualifiedModuleName,
316+
member.ModuleDeclaration));
283317
}
284318
}
319+
285320
return output;
286321
}
287322

288-
private Declaration CreateMemberDeclaration(FUNCDESC memberDescriptor, TYPEKIND typeKind, ITypeInfo info, int memberIndex,
323+
private Declaration CreateMemberDeclaration(FUNCDESC memberDescriptor, TYPEKIND typeKind, ITypeInfo info, IMPLTYPEFLAGS parentImplFlags,
289324
QualifiedModuleName typeQualifiedModuleName, Declaration moduleDeclaration, out string[] memberNames)
290325
{
291326
if (memberDescriptor.callconv != CALLCONV.CC_STDCALL)
@@ -300,7 +335,7 @@ private Declaration CreateMemberDeclaration(FUNCDESC memberDescriptor, TYPEKIND
300335

301336
var memberName = memberNames[0];
302337
var funcValueType = (VarEnum)memberDescriptor.elemdescFunc.tdesc.vt;
303-
var memberDeclarationType = GetDeclarationType(memberDescriptor, funcValueType, typeKind);
338+
var memberDeclarationType = GetDeclarationType(memberName, memberDescriptor, funcValueType, typeKind, parentImplFlags);
304339

305340
var asTypeName = string.Empty;
306341
if (memberDeclarationType != DeclarationType.Procedure)
@@ -470,13 +505,41 @@ private IEnumerable<string> GetImplementedInterfaceNames(TYPEATTR typeAttr, ITyp
470505
ITypeInfo implTypeInfo;
471506
info.GetRefTypeInfo(href, out implTypeInfo);
472507

508+
IntPtr typeAttributesPointer;
509+
implTypeInfo.GetTypeAttr(out typeAttributesPointer);
510+
511+
var typeAttributes = (TYPEATTR)Marshal.PtrToStructure(typeAttributesPointer, typeof(TYPEATTR));
512+
513+
IMPLTYPEFLAGS flags = 0;
514+
try
515+
{
516+
info.GetImplTypeFlags(implIndex, out flags);
517+
}
518+
catch (COMException) { }
519+
473520
var implTypeName = GetTypeName(implTypeInfo);
474521
if (implTypeName != "IDispatch" && implTypeName != "IUnknown")
475522
{
476523
// skip IDispatch.. just about everything implements it and RD doesn't need to care about it; don't care about IUnknown either
477524
output.Add(implTypeName);
478525
}
479-
//Debug.WriteLine(string.Format("\tImplements {0}", implTypeName));
526+
527+
if (flags != 0)
528+
{
529+
ComInformation comInfo;
530+
if (_comInformation.TryGetValue(typeAttributes.guid, out comInfo))
531+
{
532+
_comInformation[typeAttributes.guid].ImplTypeFlags =
533+
_comInformation[typeAttributes.guid].ImplTypeFlags | flags;
534+
}
535+
else
536+
{
537+
_comInformation.Add(typeAttributes.guid,
538+
new ComInformation(typeAttributes, flags, implTypeInfo, implTypeName, new QualifiedModuleName(), null, 0));
539+
}
540+
}
541+
542+
info.ReleaseTypeAttr(typeAttributesPointer);
480543
}
481544
return output;
482545
}
@@ -507,7 +570,7 @@ private DeclarationType GetDeclarationType(ITypeLib typeLibrary, int i)
507570
return typeDeclarationType;
508571
}
509572

510-
private DeclarationType GetDeclarationType(FUNCDESC funcDesc, VarEnum funcValueType, TYPEKIND typekind)
573+
private DeclarationType GetDeclarationType(string memberName, FUNCDESC funcDesc, VarEnum funcValueType, TYPEKIND typekind, IMPLTYPEFLAGS parentImplTypeFlags)
511574
{
512575
DeclarationType memberType;
513576
if (funcDesc.invkind.HasFlag(INVOKEKIND.INVOKE_PROPERTYGET))
@@ -522,13 +585,15 @@ private DeclarationType GetDeclarationType(FUNCDESC funcDesc, VarEnum funcValueT
522585
{
523586
memberType = DeclarationType.PropertySet;
524587
}
525-
else if (funcValueType == VarEnum.VT_VOID)
588+
else if ((parentImplTypeFlags.HasFlag(IMPLTYPEFLAGS.IMPLTYPEFLAG_FSOURCE) ||
589+
((FUNCFLAGS)funcDesc.wFuncFlags).HasFlag(FUNCFLAGS.FUNCFLAG_FSOURCE)) &&
590+
!new[] {"QueryInterface", "AddRef", "Release", "GetTypeInfoCount", "GetTypeInfo", "GetIDsOfNames", "Invoke"}.Contains(memberName)) // quick-and-dirty for beta
526591
{
527-
memberType = DeclarationType.Procedure;
592+
memberType = DeclarationType.Event;
528593
}
529-
else if (funcDesc.funckind == FUNCKIND.FUNC_PUREVIRTUAL && typekind == TYPEKIND.TKIND_COCLASS)
594+
else if (funcValueType == VarEnum.VT_VOID)
530595
{
531-
memberType = DeclarationType.Event;
596+
memberType = DeclarationType.Procedure;
532597
}
533598
else
534599
{

Rubberduck.Parsing/VBA/RubberduckParser.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public RubberduckParser(
5353
_attributeParser = attributeParser;
5454
_preprocessorFactory = preprocessorFactory;
5555

56-
_comReflector = new ReferencedDeclarationsCollector();
56+
_comReflector = new ReferencedDeclarationsCollector(_state);
5757

5858
state.ParseRequest += ReparseRequested;
5959
state.StateChanged += StateOnStateChanged;

0 commit comments

Comments
 (0)