Skip to content

Commit cd52c73

Browse files
authored
Merge pull request #5721 from retailcoder/resolve-supertypes
Fixes the resolution of default instance variables
2 parents bcd843e + c5ad714 commit cd52c73

File tree

10 files changed

+60
-33
lines changed

10 files changed

+60
-33
lines changed

Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitSheetReferenceInspectionBase.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ protected override IEnumerable<Declaration> ObjectionableDeclarations(Declaratio
2626
.Select(className => finder.FindClassModule(className, excel, true))
2727
.OfType<ModuleDeclaration>();
2828

29+
2930
return globalModules
3031
.SelectMany(moduleClass => moduleClass.Members)
3132
.Where(declaration => TargetMemberNames.Contains(declaration.IdentifierName)
@@ -35,7 +36,8 @@ protected override IEnumerable<Declaration> ObjectionableDeclarations(Declaratio
3536

3637
private static readonly string[] GlobalObjectClassNames =
3738
{
38-
"Global", "_Global"
39+
"Global", "_Global",
40+
"Worksheet", "_Worksheet"
3941
};
4042

4143
private static readonly string[] TargetMemberNames =

Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitWorkbookReferenceInspectionBase.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ internal ImplicitWorkbookReferenceInspectionBase(IDeclarationFinderProvider decl
2424

2525
protected override IEnumerable<Declaration> ObjectionableDeclarations(DeclarationFinder finder)
2626
{
27-
var excel = finder.Projects
28-
.SingleOrDefault(project => project.IdentifierName == "Excel" && !project.IsUserDefined);
29-
if (excel == null)
27+
if (!finder.TryFindProjectDeclaration("Excel", out var excel))
3028
{
3129
return Enumerable.Empty<Declaration>();
3230
}

Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,20 +131,19 @@ private static IEnumerable<AssignmentNode> FindUnusedAssignmentNodes(INode node,
131131
.Contains(refNode));
132132

133133
var assignmentsPrecedingReference = assignmentExprNodesWithReference.Any()
134-
? assignmentExprNodes.TakeWhile(n => n != assignmentExprNodesWithReference.Last())
135-
.Last()
136-
.Nodes(new[] { typeof(AssignmentNode) })
134+
? assignmentExprNodes.TakeWhile(n => n != assignmentExprNodesWithReference.LastOrDefault())
135+
?.LastOrDefault()
136+
?.Nodes(new[] { typeof(AssignmentNode) })
137137
: allAssignmentsAndReferences.TakeWhile(n => n != refNode)
138138
.OfType<AssignmentNode>();
139139

140-
if (assignmentsPrecedingReference.Any())
140+
if (assignmentsPrecedingReference?.Any() ?? false)
141141
{
142-
usedAssignments.Add(assignmentsPrecedingReference.Last() as AssignmentNode);
142+
usedAssignments.Add(assignmentsPrecedingReference.LastOrDefault() as AssignmentNode);
143143
}
144144
}
145145

146-
return allAssignmentsAndReferences.OfType<AssignmentNode>()
147-
.Except(usedAssignments);
146+
return allAssignmentsAndReferences.OfType<AssignmentNode>().Except(usedAssignments);
148147
}
149148

150149
private static bool IsDescendentOfNeverFlagNode(AssignmentNode assignment)

Rubberduck.CodeAnalysis/Inspections/Concrete/SheetAccessedUsingStringInspection.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,19 @@ public SheetAccessedUsingStringInspection(IDeclarationFinderProvider declaration
6161

6262
private static readonly string[] InterestingMembers =
6363
{
64-
"Worksheets", "Sheets"
64+
"Worksheets", // gets a Sheets object containing Worksheet objects.
65+
"Sheets", // gets a Sheets object containing all sheets (not just Worksheet sheets) in the qualifying workbook.
6566
};
6667

6768
private static readonly string[] InterestingClasses =
6869
{
69-
"Workbook"
70+
"Workbook", // unqualified member call
71+
"_Workbook", // qualified member call
7072
};
7173

7274
protected override IEnumerable<Declaration> ObjectionableDeclarations(DeclarationFinder finder)
7375
{
74-
var excel = finder.Projects
75-
.SingleOrDefault(project => project.IdentifierName == "Excel" && !project.IsUserDefined);
76-
if (excel == null)
76+
if (!finder.TryFindProjectDeclaration("Excel", out var excel))
7777
{
7878
return Enumerable.Empty<Declaration>();
7979
}

Rubberduck.Parsing/Binding/Bindings/SimpleNameDefaultBinding.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ procedural module contained in the enclosing project.
187187
var defaultInstanceVariableClass = _declarationFinder.FindDefaultInstanceVariableClassEnclosingProject(_project, _module, _name);
188188
if (defaultInstanceVariableClass != null)
189189
{
190-
return new SimpleNameExpression(defaultInstanceVariableClass, ExpressionClassification.Type, _context);
190+
return new SimpleNameExpression(defaultInstanceVariableClass, ExpressionClassification.Variable, _context);
191191
}
192192
return null;
193193
}

Rubberduck.Parsing/Symbols/VariableDeclaration.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ public VariableDeclaration(
2323
bool isArray,
2424
VBAParser.AsTypeClauseContext asTypeContext,
2525
IEnumerable<IParseTreeAnnotation> annotations = null,
26-
Attributes attributes = null)
26+
Attributes attributes = null,
27+
bool isUserDefined = true)
2728
: base(
2829
qualifiedName,
2930
parentDeclaration,
@@ -39,7 +40,7 @@ public VariableDeclaration(
3940
selection,
4041
isArray,
4142
asTypeContext,
42-
true,
43+
isUserDefined,
4344
annotations,
4445
attributes)
4546
{

Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ public IEnumerable<ModuleBodyElementDeclaration> FindEventHandlers(Declaration e
333333
{
334334
var withEventsDeclarations = FindWithEventFields(eventDeclaration);
335335
return withEventsDeclarations
336-
.Select(withEventsField => FindHandlersForWithEventsField(withEventsField).Single(handler =>
336+
.Select(withEventsField => FindHandlersForWithEventsField(withEventsField).SingleOrDefault(handler =>
337337
handler.IdentifierName.Equals($"{withEventsField.IdentifierName}_{eventDeclaration.IdentifierName}", StringComparison.InvariantCultureIgnoreCase)));
338338
}
339339

@@ -357,6 +357,18 @@ public ICollection<Declaration> FindFormEventHandlers()
357357
public IEnumerable<Declaration> Classes => _classes.Value;
358358
public IEnumerable<Declaration> Projects => _projects.Value;
359359

360+
/// <summary>
361+
/// Gets the <see cref="ProjectDeclaration"/> object for specified referenced project/library.
362+
/// </summary>
363+
/// <param name="name">The identifier name of the project declaration to find.</param>
364+
/// <param name="result">The <see cref="ProjectDeclaration"/> result, if found; null otherwise.</param>
365+
/// <param name="includeUserDefined">True to include user-defined projects in the search; false by default.</param>
366+
public bool TryFindProjectDeclaration(string name, out Declaration result, bool includeUserDefined = false)
367+
{
368+
result = _projects.Value.FirstOrDefault(project => project.IdentifierName.Equals(name, StringComparison.InvariantCultureIgnoreCase) && project.IsUserDefined == includeUserDefined);
369+
return result != null;
370+
}
371+
360372
public IEnumerable<Declaration> UserDeclarations(DeclarationType type)
361373
{
362374
return _userDeclarationsByType.TryGetValue(type, out var result)
@@ -898,9 +910,10 @@ public Declaration FindMemberWithParent(Declaration callingProject, Declaration
898910
string memberName, DeclarationType memberType)
899911
{
900912
var allMatches = MatchName(memberName);
913+
var parentClass = parent as ClassModuleDeclaration;
901914
var memberMatches = allMatches
902915
.Where(m => m.DeclarationType.HasFlag(memberType)
903-
&& parent.Equals(m.ParentDeclaration))
916+
&& (parent.Equals(m.ParentDeclaration) || (parentClass?.Supertypes.Any(t => t.Equals(m.ParentDeclaration)) ?? false)))
904917
.ToList();
905918
var accessibleMembers = memberMatches.Where(m => AccessibilityCheck.IsMemberAccessible(callingProject, callingModule, callingParent, m));
906919
var match = accessibleMembers.FirstOrDefault();
@@ -934,21 +947,23 @@ public Declaration FindMemberEnclosingModule(Declaration callingModule, Declarat
934947
}
935948
// Classes such as Worksheet have properties such as Range that can be access in a user defined class such as Sheet1,
936949
// that's why we have to walk the type hierarchy and find these implementations.
937-
foreach (var supertype in ClassModuleDeclaration.GetSupertypes(callingModule))
950+
if (callingModule is ClassModuleDeclaration callingClass)
938951
{
939-
// Only built-in classes such as Worksheet can be considered "real base classes".
940-
// User created interfaces work differently and don't allow accessing accessing implementations.
941-
if (supertype.IsUserDefined)
952+
foreach (var supertype in callingClass.Supertypes)
942953
{
943-
continue;
944-
}
945-
var supertypeMatch = FindMemberEnclosingModule(supertype, callingParent, memberName, memberType);
946-
if (supertypeMatch != null)
947-
{
948-
return supertypeMatch;
954+
// Only built-in classes such as Worksheet can be considered "real base classes".
955+
// User created interfaces work differently and don't allow accessing accessing implementations.
956+
if (supertype.IsUserDefined)
957+
{
958+
continue;
959+
}
960+
var supertypeMatch = FindMemberEnclosingModule(supertype, callingParent, memberName, memberType);
961+
if (supertypeMatch != null)
962+
{
963+
return supertypeMatch;
964+
}
949965
}
950966
}
951-
952967
return null;
953968
}
954969

Rubberduck.Resources/RubberduckUI.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Rubberduck.Resources/RubberduckUI.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1892,4 +1892,7 @@ Do you want to proceed?</value>
18921892
<data name="IndenterSettings_GroupRelatedProperties" xml:space="preserve">
18931893
<value>Remove vertical space between related property members</value>
18941894
</data>
1895+
<data name="DeclarationType_Document" xml:space="preserve">
1896+
<value>document</value>
1897+
</data>
18951898
</root>

RubberduckTests/Symbols/SelectedDeclarationProviderTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ Dim sht As WorkSheet
527527
.AddProjectToVbeBuilder()
528528
.Build();
529529

530-
var (expected, actual) = DeclarationsFromParse(vbe.Object, DeclarationType.Parameter, "Link", "EXCEL.EXE;Excel.Worksheet.Paste");
530+
var (expected, actual) = DeclarationsFromParse(vbe.Object, DeclarationType.Parameter, "Link", "EXCEL.EXE;Excel._Worksheet.Paste");
531531

532532
Assert.AreEqual(expected, actual);
533533
}

0 commit comments

Comments
 (0)