Skip to content

Commit 0a3d83d

Browse files
committed
Add DefaultMemberRequiredInspection
This inspection finds all failed indexed default member resolutions. The non-indexed ones are already covered by the ValueRequiredInspection and the ProcedureRequiredInspection.
1 parent 4373608 commit 0a3d83d

13 files changed

+546
-7
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Rubberduck.Inspections.Abstract;
4+
using Rubberduck.Inspections.Inspections.Extensions;
5+
using Rubberduck.Inspections.Results;
6+
using Rubberduck.Parsing.Inspections;
7+
using Rubberduck.Parsing.Inspections.Abstract;
8+
using Rubberduck.Parsing.Symbols;
9+
using Rubberduck.Parsing.VBA;
10+
using Rubberduck.Resources.Inspections;
11+
12+
namespace Rubberduck.CodeAnalysis.Inspections.Concrete
13+
{
14+
/// <summary>
15+
/// Locates indexed default member calls for which the corresponding object does not have a suitable suitable default member.
16+
/// </summary>
17+
/// <why>
18+
/// The VBA compiler does not check whether the necessary default member is present. Instead there is a runtime error whenever the runtime type fails to have the default member.
19+
/// </why>
20+
/// <example hasResult="true">
21+
/// <![CDATA[
22+
/// Class1:
23+
///
24+
/// Public Function Foo(index As Long) As Long
25+
/// 'No default member attribute
26+
/// End Function
27+
///
28+
/// ------------------------------
29+
/// Module1:
30+
///
31+
/// Public Sub DoIt()
32+
/// Dim cls As Class1
33+
/// Dim bar As Variant
34+
/// Set cls = New Class1
35+
/// bar = cls(0)
36+
/// End Sub
37+
/// ]]>
38+
/// </example>
39+
/// <example hasResult="false">
40+
/// <![CDATA[
41+
/// Class1:
42+
///
43+
/// Public Function Foo(index As Long) As Long
44+
/// Attribute Foo.UserMemId = 0
45+
/// End Function
46+
///
47+
/// ------------------------------
48+
/// Module1:
49+
///
50+
/// Public Sub DoIt()
51+
/// Dim cls As Class1
52+
/// Dim bar As Variant
53+
/// Set cls = New Class1
54+
/// bar = cls(0)
55+
/// End Sub
56+
/// ]]>
57+
/// </example>
58+
public class DefaultMemberRequiredInspection : InspectionBase
59+
{
60+
private readonly IDeclarationFinderProvider _declarationFinderProvider;
61+
62+
public DefaultMemberRequiredInspection(RubberduckParserState state)
63+
: base(state)
64+
{
65+
_declarationFinderProvider = state;
66+
67+
//This will most likely cause a runtime error. The exceptions are rare and should be refactored or made explicit with an @Ignore annotation.
68+
Severity = CodeInspectionSeverity.Error;
69+
}
70+
71+
protected override IEnumerable<IInspectionResult> DoGetInspectionResults()
72+
{
73+
var finder = _declarationFinderProvider.DeclarationFinder;
74+
75+
var failedIndexedDefaultMemberAccesses = finder.FailedIndexedDefaultMemberAccesses();
76+
return failedIndexedDefaultMemberAccesses
77+
.Where(failedIndexedDefaultMemberAccess => !IsIgnored(failedIndexedDefaultMemberAccess))
78+
.Select(failedIndexedDefaultMemberAccess => InspectionResult(failedIndexedDefaultMemberAccess, _declarationFinderProvider));
79+
}
80+
81+
private bool IsIgnored(IdentifierReference assignment)
82+
{
83+
return assignment.IsIgnoringInspectionResultFor(AnnotationName);
84+
}
85+
86+
private IInspectionResult InspectionResult(IdentifierReference failedCoercion, IDeclarationFinderProvider declarationFinderProvider)
87+
{
88+
return new IdentifierReferenceInspectionResult(this,
89+
ResultDescription(failedCoercion),
90+
declarationFinderProvider,
91+
failedCoercion);
92+
}
93+
94+
private string ResultDescription(IdentifierReference failedIndexedDefaultMemberAccess)
95+
{
96+
var expression = failedIndexedDefaultMemberAccess.IdentifierName;
97+
var typeName = failedIndexedDefaultMemberAccess.Declaration?.FullAsTypeName;
98+
return string.Format(InspectionResults.DefaultMemberRequiredInspection, expression, typeName);
99+
}
100+
}
101+
}

Rubberduck.Resources/Inspections/InspectionInfo.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/Inspections/InspectionInfo.de.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,4 +400,7 @@ Falls der Parameter 'null' sein kann, bitte dieses Auftreten ignorieren. 'null'
400400
<data name="ProcedureRequiredInspection" xml:space="preserve">
401401
<value>Der VBA-Compiler gibt keinen Fehler aus, wenn eine Objektvariable an einer Stelle verwendet wird, die eine Prozedur erfordert, und der deklarierte Type des Objekts keinen passenden Standardmember hat. In fast allen Fällen führt dies zu einem Laufzeitfehler, der schwerer zu entdecken ist und auf einen Programmierfehler hinweist.</value>
402402
</data>
403+
<data name="DefaultMemberRequiredInspection" xml:space="preserve">
404+
<value>Der VBA-Compiler gibt keinen Fehler aus, wenn ein Standardmemberzugriff nötig ist, aber der der deklarierte Type des Objekts keinen passenden Standardmember hat. In fast allen Fällen führt dies zu einem Laufzeitfehler, der schwerer zu entdecken ist und auf einen Programmierfehler hinweist.</value>
405+
</data>
403406
</root>

Rubberduck.Resources/Inspections/InspectionInfo.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,4 +400,7 @@ If the parameter can be null, ignore this inspection result; passing a null valu
400400
<data name="ProcedureRequiredInspection" xml:space="preserve">
401401
<value>The VBA compiler does not raise an error if an object variable is used in a place that requires a procedure and the object's declared type does not have a suitable default member. Under almost all circumstances, this leads to a run-time error, which is harder to detect and indicates a bug.</value>
402402
</data>
403+
<data name="DefaultMemberRequiredInspection" xml:space="preserve">
404+
<value>The VBA compiler does not raise an error if an indexed default member call is required but the object's declared type does not have a suitable default member. Under almost all circumstances, this leads to a run-time error, which is harder to detect and indicates a bug.</value>
405+
</data>
403406
</root>

Rubberduck.Resources/Inspections/InspectionNames.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/Inspections/InspectionNames.de.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,4 +384,7 @@
384384
<data name="ProcedureRequiredInspection" xml:space="preserve">
385385
<value>Objekt statt Prozedur verwendet</value>
386386
</data>
387+
<data name="DefaultMemberRequiredInspection" xml:space="preserve">
388+
<value>Standardmemberzugriff ohne Standardmember</value>
389+
</data>
387390
</root>

Rubberduck.Resources/Inspections/InspectionNames.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,4 +404,7 @@
404404
<data name="ProcedureRequiredInspection" xml:space="preserve">
405405
<value>Object used where a procedure is required</value>
406406
</data>
407+
<data name="DefaultMemberRequiredInspection" xml:space="preserve">
408+
<value>Indexed default member access without default member</value>
409+
</data>
407410
</root>

Rubberduck.Resources/Inspections/InspectionResults.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/Inspections/InspectionResults.de.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,4 +425,7 @@ In Memoriam, 1972-2018</value>
425425
<data name="ProcedureRequiredInspection" xml:space="preserve">
426426
<value>An einer Stelle, die eine Prozedur erfordert, wird der Ausdruck '{0}' vom Objekttyp '{1}' verwendet, der keinen passendes Standardmember hat.</value>
427427
</data>
428+
<data name="DefaultMemberRequiredInspection" xml:space="preserve">
429+
<value>Der Ausdruck '{0}' erfordert einen Standardmemberzugriff, aber der Typ '{1}' hat keinen passenden Standardmember.</value>
430+
</data>
428431
</root>

Rubberduck.Resources/Inspections/InspectionResults.resx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,4 +454,8 @@ In memoriam, 1972-2018</value>
454454
<value>In a context that requires a procedure, the expression '{0}' of object type '{1}' is used that does not have a suitable default member.</value>
455455
<comment>{0} expression; {1} type</comment>
456456
</data>
457+
<data name="DefaultMemberRequiredInspection" xml:space="preserve">
458+
<value>The expression '{0}' requires a default member access, but the type '{0}' does not have a suitable default member.</value>
459+
<comment>{0} expression; {1} type</comment>
460+
</data>
457461
</root>

0 commit comments

Comments
 (0)