Skip to content

Commit 0dc14a7

Browse files
committed
applying default member attributes to, well, default members. not always what one might expect though.
1 parent eff9da9 commit 0dc14a7

File tree

5 files changed

+175
-81
lines changed

5 files changed

+175
-81
lines changed

RetailCoder.VBE/UI/Controls/SearchResultPresenterInstanceManager.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,14 @@ private void viewModel_LastTabClosed(object sender, EventArgs e)
4242

4343
public void Dispose()
4444
{
45-
_view.ViewModel.LastTabClosed -= viewModel_LastTabClosed;
46-
_presenter.Dispose();
45+
if (_view.ViewModel != null)
46+
{
47+
_view.ViewModel.LastTabClosed -= viewModel_LastTabClosed;
48+
}
49+
if (_presenter != null)
50+
{
51+
_presenter.Dispose();
52+
}
4753
}
4854
}
4955
}

Rubberduck.Parsing/Rubberduck.Parsing.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@
179179
<Compile Include="Symbols\IdentifierReferenceListener.cs" />
180180
<Compile Include="Symbols\ValuedDeclaration.cs" />
181181
<Compile Include="VBA\AttributeParser.cs" />
182+
<Compile Include="VBA\Attributes.cs" />
182183
<Compile Include="VBA\AttributesBaseListener.cs" />
183184
<Compile Include="VBA\AttributesBaseVisitor.cs" />
184185
<Compile Include="VBA\AttributesLexer.cs" />

Rubberduck.Parsing/Symbols/ReferencedDeclarationsCollector.cs

Lines changed: 123 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Diagnostics;
34
using System.Runtime.InteropServices;
45
using System.Runtime.InteropServices.ComTypes;
56
using Microsoft.Vbe.Interop;
7+
using Rubberduck.Parsing.VBA;
68
using Rubberduck.VBEditor;
9+
using CALLCONV = System.Runtime.InteropServices.ComTypes.CALLCONV;
710
using FUNCFLAGS = System.Runtime.InteropServices.ComTypes.FUNCFLAGS;
811
using TYPEDESC = System.Runtime.InteropServices.ComTypes.TYPEDESC;
912
using 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
}

Rubberduck.Parsing/VBA/AttributeParser.cs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,6 @@
99

1010
namespace Rubberduck.Parsing.VBA
1111
{
12-
/// <summary>
13-
/// A dictionary storing values for a given attribute.
14-
/// </summary>
15-
/// <remarks>
16-
/// Dictionary key is the attribute name/identifier.
17-
/// </remarks>
18-
public class Attributes : Dictionary<string, IEnumerable<string>> { }
19-
2012
public class AttributeParser : IAttributeParser
2113
{
2214
private readonly IModuleExporter _exporter;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System.Collections.Generic;
2+
3+
namespace Rubberduck.Parsing.VBA
4+
{
5+
/// <summary>
6+
/// A dictionary storing values for a given attribute.
7+
/// </summary>
8+
/// <remarks>
9+
/// Dictionary key is the attribute name/identifier.
10+
/// </remarks>
11+
public class Attributes : Dictionary<string, IEnumerable<string>>
12+
{
13+
/// <summary>
14+
/// Specifies that a member is the type's default member.
15+
/// Only one member in the type is allowed to have this attribute.
16+
/// </summary>
17+
/// <param name="identifierName"></param>
18+
public void AddDefaultMemberAttribute(string identifierName)
19+
{
20+
Add(identifierName + ".VB_UserMemId", new[] {"0"});
21+
}
22+
23+
public void AddHiddenMemberAttribute(string identifierName)
24+
{
25+
Add(identifierName + ".VB_UserMemId", new[] {"40"});
26+
}
27+
28+
public void AddEnumeratorMemberAttribute(string identifierName)
29+
{
30+
Add(identifierName + ".VB_UserMemId", new[] {"-4"});
31+
}
32+
33+
public void AddMemberDescriptionAttribute(string identifierName, string description)
34+
{
35+
Add(identifierName + ".VB_Description", new[] {description});
36+
}
37+
38+
public void AddPredeclaredIdTypeAttribute()
39+
{
40+
Add("VB_PredeclaredId", new[] {"True"});
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)