Skip to content

Commit a5b115e

Browse files
committed
Adjust com interface discovery for documents with separate interface
Hosts like Access insert an additional interface for document modules between the document and the built-in one. Since we do not have a declaration for the separate interface, we also add the interface two levels op to the supertypes of the document.
1 parent 9a7d34c commit a5b115e

File tree

1 file changed

+28
-11
lines changed

1 file changed

+28
-11
lines changed

Rubberduck.Parsing/VBA/ReferenceManagement/ReferenceResolveRunnerBase.cs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -200,23 +200,40 @@ private void AddSuperTypeNamesForDocumentModules(IReadOnlyCollection<QualifiedMo
200200
private static IEnumerable<string> SuperTypeNamesForDocumentFromComType(IComType comModule)
201201
{
202202
var inheritedInterfaces = comModule is ComCoClass documentCoClass
203-
? documentCoClass.ImplementedInterfaces
204-
: (comModule as ComInterface)?.InheritedInterfaces;
205-
206-
//todo: Find a way to deal with the VBE's document type assignment behaviour not relying on an assumption about an interface naming convention.
207-
var superTypeNames = (inheritedInterfaces?
208-
.Where(i => !i.IsRestricted && !IgnoredComInterfaces.Contains(i.Name))
209-
.Select(i => i.Name)
210-
?? Enumerable.Empty<string>())
203+
? documentCoClass.ImplementedInterfaces.ToList()
204+
: (comModule as ComInterface)?.InheritedInterfaces.ToList();
205+
206+
if (inheritedInterfaces == null)
207+
{
208+
return Enumerable.Empty<string>();
209+
}
210+
211+
var relevantInterfaces = inheritedInterfaces
212+
.Where(i => !i.IsRestricted && !IgnoredComInterfaces.Contains(i.Name))
213+
.ToList();
214+
215+
//todo: Find a way to deal with the VBE's document type assignment and interface behaviour not relying on an assumption about an interface naming conventions.
216+
217+
//Some hosts like Access chose to have a separate hidden interface for each document module and only let that inherit the built-in base interface.
218+
//Since we do not have a declaration for the hidden interface, we have to go one more step up the hierarchy.
219+
var additionalInterfaces = relevantInterfaces
220+
.Where(i => i.Name.Equals("_" + comModule.Name))
221+
.SelectMany(i => i.InheritedInterfaces);
222+
223+
relevantInterfaces.AddRange(additionalInterfaces);
224+
225+
var superTypeNames = relevantInterfaces
226+
.Select(i => i.Name)
211227
.ToList();
212228

213229
//This emulates the VBE's behaviour to allow assignment to the coclass type instead on the interface.
214-
var additionalSuperTypes = superTypeNames
230+
var additionalSuperTypeNames = superTypeNames
215231
.Where(name => name.StartsWith("_"))
216232
.Select(name => name.Substring(1))
233+
.Where(name => !name.Equals(comModule.Name))
217234
.ToList();
218235

219-
superTypeNames.AddRange(additionalSuperTypes);
236+
superTypeNames.AddRange(additionalSuperTypeNames);
220237
return superTypeNames;
221238
}
222239

@@ -240,7 +257,7 @@ protected void ResolveReferences(DeclarationFinder finder, QualifiedModuleName m
240257
Logger.Debug("Binding resolution done for component '{0}' in {1}ms (thread {2})", module.Name,
241258
watch.ElapsedMilliseconds, Thread.CurrentThread.ManagedThreadId);
242259

243-
//Evaluation of the overall status has to be defered to allow processing of undeclared variables before setting the ready state.
260+
//Evaluation of the overall status has to be deferred to allow processing of undeclared variables before setting the ready state.
244261
_parserStateManager.SetModuleState(module, ParserState.Ready, token, false);
245262
}
246263
catch (OperationCanceledException)

0 commit comments

Comments
 (0)