11using System ;
22using System . Collections . Generic ;
3+ using System . Diagnostics ;
34using System . Runtime . InteropServices ;
45using System . Runtime . InteropServices . ComTypes ;
56using Microsoft . Vbe . Interop ;
7+ using Rubberduck . Parsing . VBA ;
68using Rubberduck . VBEditor ;
9+ using CALLCONV = System . Runtime . InteropServices . ComTypes . CALLCONV ;
710using FUNCFLAGS = System . Runtime . InteropServices . ComTypes . FUNCFLAGS ;
811using TYPEDESC = System . Runtime . InteropServices . ComTypes . TYPEDESC ;
912using TYPEKIND = System . Runtime . InteropServices . ComTypes . TYPEKIND ;
@@ -111,8 +114,7 @@ public IEnumerable<Declaration> GetDeclarationsForReference(Reference reference)
111114
112115 QualifiedModuleName typeQualifiedModuleName ;
113116 QualifiedMemberName typeQualifiedMemberName ;
114- if ( typeDeclarationType == DeclarationType . Enumeration ||
115- typeDeclarationType == DeclarationType . UserDefinedType )
117+ if ( typeDeclarationType == DeclarationType . Enumeration || typeDeclarationType == DeclarationType . UserDefinedType )
116118 {
117119 typeQualifiedModuleName = projectQualifiedModuleName ;
118120 typeQualifiedMemberName = new QualifiedMemberName ( projectQualifiedModuleName , typeName ) ;
@@ -131,94 +133,144 @@ public IEnumerable<Declaration> GetDeclarationsForReference(Reference reference)
131133
132134 var typeAttributes = ( TYPEATTR ) Marshal . PtrToStructure ( typeAttributesPointer , typeof ( TYPEATTR ) ) ;
133135 //var implements = GetImplementedInterfaceNames(typeAttributes, info);
134-
136+
135137 for ( var memberIndex = 0 ; memberIndex < typeAttributes . cFuncs ; memberIndex ++ )
136138 {
137- IntPtr memberDescriptorPointer ;
138- info . GetFuncDesc ( memberIndex , out memberDescriptorPointer ) ;
139- var memberDescriptor = ( FUNCDESC ) Marshal . PtrToStructure ( memberDescriptorPointer , typeof ( FUNCDESC ) ) ;
140-
141- var memberNames = new string [ 255 ] ; // member name at index 0; array contains parameter names too
142- int namesArrayLength ;
143- info . GetNames ( memberDescriptor . memid , memberNames , 255 , out namesArrayLength ) ;
144-
145- var memberName = memberNames [ 0 ] ;
146-
147- var funcValueType = ( VarEnum ) memberDescriptor . elemdescFunc . tdesc . vt ;
148- var memberDeclarationType = GetDeclarationType ( memberDescriptor , funcValueType ) ;
149-
150- var asTypeName = string . Empty ;
151- if ( memberDeclarationType != DeclarationType . Procedure && ! TypeNames . TryGetValue ( funcValueType , out asTypeName ) )
139+ FUNCDESC memberDescriptor ;
140+ string [ ] memberNames ;
141+ var memberDeclaration = CreateMemberDeclaration ( out memberDescriptor , typeAttributes . typekind , info , memberIndex , typeQualifiedModuleName , moduleDeclaration , out memberNames ) ;
142+ if ( memberDeclaration == null )
152143 {
153- asTypeName = funcValueType . ToString ( ) ; //TypeNames[VarEnum.VT_VARIANT] ;
144+ continue ;
154145 }
155146
156- var memberDeclaration = new Declaration ( new QualifiedMemberName ( typeQualifiedModuleName , memberName ) , moduleDeclaration , moduleDeclaration , asTypeName , false , false , Accessibility . Global , memberDeclarationType , null , Selection . Home ) ;
157147 yield return memberDeclaration ;
158148
159149 var parameterCount = memberDescriptor . cParams - 1 ;
160150 for ( var paramIndex = 0 ; paramIndex < parameterCount ; paramIndex ++ )
161151 {
162- var paramName = memberNames [ paramIndex + 1 ] ;
163-
164- var paramPointer = new IntPtr ( memberDescriptor . lprgelemdescParam . ToInt64 ( ) + Marshal . SizeOf ( typeof ( ELEMDESC ) ) * paramIndex ) ;
165- var elementDesc = ( ELEMDESC ) Marshal . PtrToStructure ( paramPointer , typeof ( ELEMDESC ) ) ;
166- var isOptional = elementDesc . desc . paramdesc . wParamFlags . HasFlag ( PARAMFLAG . PARAMFLAG_FOPT ) ;
167- var asParamTypeName = string . Empty ;
168-
169- var isByRef = false ;
170- var isArray = false ;
171- var paramDesc = elementDesc . tdesc ;
172- var valueType = ( VarEnum ) paramDesc . vt ;
173- if ( valueType == VarEnum . VT_PTR || valueType == VarEnum . VT_BYREF )
174- {
175- //var paramTypeDesc = (TYPEDESC) Marshal.PtrToStructure(paramDesc.lpValue, typeof (TYPEDESC));
176- isByRef = true ;
177- var paramValueType = ( VarEnum ) paramDesc . vt ;
178- if ( ! TypeNames . TryGetValue ( paramValueType , out asParamTypeName ) )
179- {
180- asParamTypeName = TypeNames [ VarEnum . VT_VARIANT ] ;
181- }
182- //var href = paramDesc.lpValue.ToInt32();
183- //ITypeInfo refTypeInfo;
184- //info.GetRefTypeInfo(href, out refTypeInfo);
185-
186- // todo: get type info?
187- }
188- if ( valueType == VarEnum . VT_CARRAY || valueType == VarEnum . VT_ARRAY || valueType == VarEnum . VT_SAFEARRAY )
189- {
190- // todo: tell ParamArray arrays from normal arrays
191- isArray = true ;
192- }
193-
194- yield return new ParameterDeclaration ( new QualifiedMemberName ( typeQualifiedModuleName , paramName ) , memberDeclaration , asParamTypeName , isOptional , isByRef , isArray ) ;
152+ yield return CreateParameterDeclaration ( memberNames , paramIndex , memberDescriptor , typeQualifiedModuleName , memberDeclaration ) ;
195153 }
196154 }
197155
198156 for ( var fieldIndex = 0 ; fieldIndex < typeAttributes . cVars ; fieldIndex ++ )
199157 {
200- IntPtr ppVarDesc ;
201- info . GetVarDesc ( fieldIndex , out ppVarDesc ) ;
158+ yield return CreateFieldDeclaration ( info , fieldIndex , typeDeclarationType , typeQualifiedModuleName , moduleDeclaration ) ;
159+ }
160+ }
161+ }
202162
203- var varDesc = ( VARDESC ) Marshal . PtrToStructure ( ppVarDesc , typeof ( VARDESC ) ) ;
163+ private Declaration CreateMemberDeclaration ( out FUNCDESC memberDescriptor , TYPEKIND typeKind , ITypeInfo info , int memberIndex ,
164+ QualifiedModuleName typeQualifiedModuleName , Declaration moduleDeclaration , out string [ ] memberNames )
165+ {
166+ IntPtr memberDescriptorPointer ;
167+ info . GetFuncDesc ( memberIndex , out memberDescriptorPointer ) ;
168+ memberDescriptor = ( FUNCDESC ) Marshal . PtrToStructure ( memberDescriptorPointer , typeof ( FUNCDESC ) ) ;
204169
205- var names = new string [ 255 ] ;
206- int namesArrayLength ;
207- info . GetNames ( varDesc . memid , names , 255 , out namesArrayLength ) ;
170+ if ( memberDescriptor . callconv != CALLCONV . CC_STDCALL )
171+ {
172+ memberDescriptor = new FUNCDESC ( ) ;
173+ memberNames = new string [ ] { } ;
174+ return null ;
175+ }
208176
209- var fieldName = names [ 0 ] ;
210- var fieldValueType = ( VarEnum ) varDesc . elemdescVar . tdesc . vt ;
211- var memberType = GetDeclarationType ( varDesc , typeDeclarationType ) ;
177+ memberNames = new string [ 255 ] ;
178+ int namesArrayLength ;
179+ info . GetNames ( memberDescriptor . memid , memberNames , 255 , out namesArrayLength ) ;
180+
181+ var memberName = memberNames [ 0 ] ;
182+ var funcValueType = ( VarEnum ) memberDescriptor . elemdescFunc . tdesc . vt ;
183+ var memberDeclarationType = GetDeclarationType ( memberDescriptor , funcValueType , typeKind ) ;
212184
213- string asTypeName ;
214- if ( ! TypeNames . TryGetValue ( fieldValueType , out asTypeName ) )
215- {
216- asTypeName = TypeNames [ VarEnum . VT_VARIANT ] ;
217- }
185+ var asTypeName = string . Empty ;
186+ if ( memberDeclarationType != DeclarationType . Procedure && ! TypeNames . TryGetValue ( funcValueType , out asTypeName ) )
187+ {
188+ asTypeName = funcValueType . ToString ( ) ; //TypeNames[VarEnum.VT_VARIANT];
189+ }
190+
191+ var attributes = new Attributes ( ) ;
192+ if ( memberName == "_NewEnum" && ( ( FUNCFLAGS ) memberDescriptor . wFuncFlags ) . HasFlag ( FUNCFLAGS . FUNCFLAG_FNONBROWSABLE ) )
193+ {
194+ attributes . AddEnumeratorMemberAttribute ( memberName ) ;
195+ }
196+ else if ( memberDescriptor . memid == 0 )
197+ {
198+ attributes . AddDefaultMemberAttribute ( memberName ) ;
199+ Debug . WriteLine ( "Default member found: {0}.{1} ({2} / {3})" , moduleDeclaration . IdentifierName , memberName , memberDeclarationType , ( VarEnum ) memberDescriptor . elemdescFunc . tdesc . vt ) ;
200+ }
201+ else if ( ( ( FUNCFLAGS ) memberDescriptor . wFuncFlags ) . HasFlag ( FUNCFLAGS . FUNCFLAG_FHIDDEN ) )
202+ {
203+ attributes . AddHiddenMemberAttribute ( memberName ) ;
204+ }
218205
219- yield return new Declaration ( new QualifiedMemberName ( typeQualifiedModuleName , fieldName ) , moduleDeclaration , moduleDeclaration , asTypeName , false , false , Accessibility . Global , memberType , null , Selection . Home ) ;
206+ return new Declaration ( new QualifiedMemberName ( typeQualifiedModuleName , memberName ) ,
207+ moduleDeclaration , moduleDeclaration , asTypeName , false , false , Accessibility . Global , memberDeclarationType ,
208+ null , Selection . Home , true , null , attributes ) ;
209+ }
210+
211+ private Declaration CreateFieldDeclaration ( ITypeInfo info , int fieldIndex , DeclarationType typeDeclarationType ,
212+ QualifiedModuleName typeQualifiedModuleName , Declaration moduleDeclaration )
213+ {
214+ IntPtr ppVarDesc ;
215+ info . GetVarDesc ( fieldIndex , out ppVarDesc ) ;
216+
217+ var varDesc = ( VARDESC ) Marshal . PtrToStructure ( ppVarDesc , typeof ( VARDESC ) ) ;
218+
219+ var names = new string [ 255 ] ;
220+ int namesArrayLength ;
221+ info . GetNames ( varDesc . memid , names , 255 , out namesArrayLength ) ;
222+
223+ var fieldName = names [ 0 ] ;
224+ var fieldValueType = ( VarEnum ) varDesc . elemdescVar . tdesc . vt ;
225+ var memberType = GetDeclarationType ( varDesc , typeDeclarationType ) ;
226+
227+ string asTypeName ;
228+ if ( ! TypeNames . TryGetValue ( fieldValueType , out asTypeName ) )
229+ {
230+ asTypeName = TypeNames [ VarEnum . VT_VARIANT ] ;
231+ }
232+
233+ return new Declaration ( new QualifiedMemberName ( typeQualifiedModuleName , fieldName ) ,
234+ moduleDeclaration , moduleDeclaration , asTypeName , false , false , Accessibility . Global , memberType , null ,
235+ Selection . Home ) ;
236+ }
237+
238+ private static ParameterDeclaration CreateParameterDeclaration ( IReadOnlyList < string > memberNames , int paramIndex ,
239+ FUNCDESC memberDescriptor , QualifiedModuleName typeQualifiedModuleName , Declaration memberDeclaration )
240+ {
241+ var paramName = memberNames [ paramIndex + 1 ] ;
242+
243+ var paramPointer = new IntPtr ( memberDescriptor . lprgelemdescParam . ToInt64 ( ) + Marshal . SizeOf ( typeof ( ELEMDESC ) ) * paramIndex ) ;
244+ var elementDesc = ( ELEMDESC ) Marshal . PtrToStructure ( paramPointer , typeof ( ELEMDESC ) ) ;
245+ var isOptional = elementDesc . desc . paramdesc . wParamFlags . HasFlag ( PARAMFLAG . PARAMFLAG_FOPT ) ;
246+ var asParamTypeName = string . Empty ;
247+
248+ var isByRef = false ;
249+ var isArray = false ;
250+ var paramDesc = elementDesc . tdesc ;
251+ var valueType = ( VarEnum ) paramDesc . vt ;
252+ if ( valueType == VarEnum . VT_PTR || valueType == VarEnum . VT_BYREF )
253+ {
254+ //var paramTypeDesc = (TYPEDESC) Marshal.PtrToStructure(paramDesc.lpValue, typeof (TYPEDESC));
255+ isByRef = true ;
256+ var paramValueType = ( VarEnum ) paramDesc . vt ;
257+ if ( ! TypeNames . TryGetValue ( paramValueType , out asParamTypeName ) )
258+ {
259+ asParamTypeName = TypeNames [ VarEnum . VT_VARIANT ] ;
220260 }
221- }
261+ //var href = paramDesc.lpValue.ToInt32();
262+ //ITypeInfo refTypeInfo;
263+ //info.GetRefTypeInfo(href, out refTypeInfo);
264+
265+ // todo: get type info?
266+ }
267+ if ( valueType == VarEnum . VT_CARRAY || valueType == VarEnum . VT_ARRAY || valueType == VarEnum . VT_SAFEARRAY )
268+ {
269+ // todo: tell ParamArray arrays from normal arrays
270+ isArray = true ;
271+ }
272+
273+ return new ParameterDeclaration ( new QualifiedMemberName ( typeQualifiedModuleName , paramName ) , memberDeclaration , asParamTypeName , isOptional , isByRef , isArray ) ;
222274 }
223275
224276 //private IEnumerable<string> GetImplementedInterfaceNames(TYPEATTR typeAttr, ITypeInfo info)
@@ -264,7 +316,7 @@ private DeclarationType GetDeclarationType(ITypeLib typeLibrary, int i)
264316 return typeDeclarationType ;
265317 }
266318
267- private DeclarationType GetDeclarationType ( FUNCDESC funcDesc , VarEnum funcValueType )
319+ private DeclarationType GetDeclarationType ( FUNCDESC funcDesc , VarEnum funcValueType , TYPEKIND typekind )
268320 {
269321 DeclarationType memberType ;
270322 if ( funcDesc . invkind . HasFlag ( INVOKEKIND . INVOKE_PROPERTYGET ) )
@@ -283,7 +335,7 @@ private DeclarationType GetDeclarationType(FUNCDESC funcDesc, VarEnum funcValueT
283335 {
284336 memberType = DeclarationType . Procedure ;
285337 }
286- else if ( funcDesc . funckind == FUNCKIND . FUNC_PUREVIRTUAL )
338+ else if ( funcDesc . funckind == FUNCKIND . FUNC_PUREVIRTUAL && typekind == TYPEKIND . TKIND_COCLASS )
287339 {
288340 memberType = DeclarationType . Event ;
289341 }
0 commit comments