19
19
using VARDESC = System . Runtime . InteropServices . ComTypes . VARDESC ;
20
20
using Rubberduck . Parsing . Annotations ;
21
21
using Rubberduck . Parsing . Grammar ;
22
+ using IMPLTYPEFLAGS = System . Runtime . InteropServices . ComTypes . IMPLTYPEFLAGS ;
23
+ using System . Linq ;
22
24
23
25
namespace Rubberduck . Parsing . Symbols
24
26
{
25
27
public class ReferencedDeclarationsCollector
26
28
{
29
+ private readonly RubberduckParserState _state ;
30
+
27
31
/// <summary>
28
32
/// Controls how a type library is registered.
29
33
/// </summary>
@@ -43,9 +47,13 @@ private enum REGKIND
43
47
REGKIND_NONE = 2
44
48
}
45
49
46
-
47
50
[ 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
+ }
49
57
50
58
private static readonly IDictionary < VarEnum , string > TypeNames = new Dictionary < VarEnum , string >
51
59
{
@@ -77,6 +85,8 @@ private enum REGKIND
77
85
{ VarEnum . VT_R8 , "Double" } ,
78
86
} ;
79
87
88
+ private readonly Dictionary < Guid , ComInformation > _comInformation = new Dictionary < Guid , ComInformation > ( ) ;
89
+
80
90
private string GetTypeName ( TYPEDESC desc , ITypeInfo info )
81
91
{
82
92
var vt = ( VarEnum ) desc . vt ;
@@ -224,68 +234,93 @@ public List<Declaration> GetDeclarationsForReference(Reference reference)
224
234
moduleDeclaration = new Declaration (
225
235
typeQualifiedMemberName ,
226
236
pseudoParentModule ,
227
- pseudoParentModule ,
237
+ pseudoParentModule ,
228
238
typeName ,
229
239
null ,
230
- false ,
231
- false ,
240
+ false ,
241
+ false ,
232
242
Accessibility . Global ,
233
243
typeDeclarationType ,
234
- null ,
244
+ null ,
235
245
Selection . Home ,
236
246
false ,
237
247
null ,
238
- true ,
239
- null ,
248
+ true ,
249
+ null ,
240
250
attributes ) ;
241
251
break ;
242
252
}
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
+
243
267
info . ReleaseTypeAttr ( typeAttributesPointer ) ;
244
268
245
269
output . Add ( moduleDeclaration ) ;
270
+ }
246
271
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 ++ )
248
275
{
249
276
string [ ] memberNames ;
250
277
251
278
IntPtr memberDescriptorPointer ;
252
- info . GetFuncDesc ( memberIndex , out memberDescriptorPointer ) ;
279
+ member . TypeInfo . GetFuncDesc ( memberIndex , out memberDescriptorPointer ) ;
253
280
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 ) ;
255
284
if ( memberDeclaration == null )
256
285
{
257
- info . ReleaseFuncDesc ( memberDescriptorPointer ) ;
286
+ member . TypeInfo . ReleaseFuncDesc ( memberDescriptorPointer ) ;
258
287
continue ;
259
288
}
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 )
261
292
{
262
- ( ( ClassModuleDeclaration ) moduleDeclaration ) . DefaultMember = memberDeclaration ;
293
+ ( ( ClassModuleDeclaration ) member . ModuleDeclaration ) . DefaultMember = memberDeclaration ;
263
294
}
264
295
output . Add ( memberDeclaration ) ;
265
296
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 ) ;
267
299
for ( var paramIndex = 0 ; paramIndex < parameterCount ; paramIndex ++ )
268
300
{
269
- var parameter = CreateParameterDeclaration ( memberNames , paramIndex , memberDescriptor , typeQualifiedModuleName , memberDeclaration , info ) ;
301
+ var parameter = CreateParameterDeclaration ( memberNames , paramIndex , memberDescriptor ,
302
+ member . TypeQualifiedModuleName , memberDeclaration , member . TypeInfo ) ;
270
303
var declaration = memberDeclaration as IDeclarationWithParameter ;
271
304
if ( declaration != null )
272
305
{
273
306
declaration . AddParameter ( parameter ) ;
274
307
}
275
308
output . Add ( parameter ) ;
276
309
}
277
- info . ReleaseFuncDesc ( memberDescriptorPointer ) ;
310
+ member . TypeInfo . ReleaseFuncDesc ( memberDescriptorPointer ) ;
278
311
}
279
312
280
- for ( var fieldIndex = 0 ; fieldIndex < typeAttributes . cVars ; fieldIndex ++ )
313
+ for ( var fieldIndex = 0 ; fieldIndex < member . TypeAttributes . cVars ; fieldIndex ++ )
281
314
{
282
- output . Add ( CreateFieldDeclaration ( info , fieldIndex , typeDeclarationType , typeQualifiedModuleName , moduleDeclaration ) ) ;
315
+ output . Add ( CreateFieldDeclaration ( member . TypeInfo , fieldIndex , member . TypeDeclarationType , member . TypeQualifiedModuleName ,
316
+ member . ModuleDeclaration ) ) ;
283
317
}
284
318
}
319
+
285
320
return output ;
286
321
}
287
322
288
- private Declaration CreateMemberDeclaration ( FUNCDESC memberDescriptor , TYPEKIND typeKind , ITypeInfo info , int memberIndex ,
323
+ private Declaration CreateMemberDeclaration ( FUNCDESC memberDescriptor , TYPEKIND typeKind , ITypeInfo info , IMPLTYPEFLAGS parentImplFlags ,
289
324
QualifiedModuleName typeQualifiedModuleName , Declaration moduleDeclaration , out string [ ] memberNames )
290
325
{
291
326
if ( memberDescriptor . callconv != CALLCONV . CC_STDCALL )
@@ -300,7 +335,7 @@ private Declaration CreateMemberDeclaration(FUNCDESC memberDescriptor, TYPEKIND
300
335
301
336
var memberName = memberNames [ 0 ] ;
302
337
var funcValueType = ( VarEnum ) memberDescriptor . elemdescFunc . tdesc . vt ;
303
- var memberDeclarationType = GetDeclarationType ( memberDescriptor , funcValueType , typeKind ) ;
338
+ var memberDeclarationType = GetDeclarationType ( memberName , memberDescriptor , funcValueType , typeKind , parentImplFlags ) ;
304
339
305
340
var asTypeName = string . Empty ;
306
341
if ( memberDeclarationType != DeclarationType . Procedure )
@@ -470,13 +505,41 @@ private IEnumerable<string> GetImplementedInterfaceNames(TYPEATTR typeAttr, ITyp
470
505
ITypeInfo implTypeInfo ;
471
506
info . GetRefTypeInfo ( href , out implTypeInfo ) ;
472
507
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
+
473
520
var implTypeName = GetTypeName ( implTypeInfo ) ;
474
521
if ( implTypeName != "IDispatch" && implTypeName != "IUnknown" )
475
522
{
476
523
// skip IDispatch.. just about everything implements it and RD doesn't need to care about it; don't care about IUnknown either
477
524
output . Add ( implTypeName ) ;
478
525
}
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 ) ;
480
543
}
481
544
return output ;
482
545
}
@@ -507,7 +570,7 @@ private DeclarationType GetDeclarationType(ITypeLib typeLibrary, int i)
507
570
return typeDeclarationType ;
508
571
}
509
572
510
- private DeclarationType GetDeclarationType ( FUNCDESC funcDesc , VarEnum funcValueType , TYPEKIND typekind )
573
+ private DeclarationType GetDeclarationType ( string memberName , FUNCDESC funcDesc , VarEnum funcValueType , TYPEKIND typekind , IMPLTYPEFLAGS parentImplTypeFlags )
511
574
{
512
575
DeclarationType memberType ;
513
576
if ( funcDesc . invkind . HasFlag ( INVOKEKIND . INVOKE_PROPERTYGET ) )
@@ -522,13 +585,15 @@ private DeclarationType GetDeclarationType(FUNCDESC funcDesc, VarEnum funcValueT
522
585
{
523
586
memberType = DeclarationType . PropertySet ;
524
587
}
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
526
591
{
527
- memberType = DeclarationType . Procedure ;
592
+ memberType = DeclarationType . Event ;
528
593
}
529
- else if ( funcDesc . funckind == FUNCKIND . FUNC_PUREVIRTUAL && typekind == TYPEKIND . TKIND_COCLASS )
594
+ else if ( funcValueType == VarEnum . VT_VOID )
530
595
{
531
- memberType = DeclarationType . Event ;
596
+ memberType = DeclarationType . Procedure ;
532
597
}
533
598
else
534
599
{
0 commit comments