Skip to content

Commit 0d803d2

Browse files
committed
Add UseOfUnboundBangNotationInspection
1 parent 8bd09db commit 0d803d2

12 files changed

+324
-1
lines changed

Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace Rubberduck.Inspections.Concrete
2626
/// <![CDATA[
2727
/// Public Function MyName(ByVal rst As ADODB.Recordset) As Variant
2828
/// With rst
29-
/// !Name.Value
29+
/// MyName = !Name.Value
3030
/// End With
3131
/// End Function
3232
/// ]]>
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using System.Collections.Generic;
2+
using Rubberduck.Inspections.Abstract;
3+
using Rubberduck.Resources.Inspections;
4+
using Rubberduck.Parsing.Symbols;
5+
using Rubberduck.Parsing.VBA;
6+
using Rubberduck.Inspections.Inspections.Extensions;
7+
using Rubberduck.Parsing.Grammar;
8+
using Rubberduck.Parsing.Inspections;
9+
using Rubberduck.VBEditor;
10+
11+
namespace Rubberduck.Inspections.Concrete
12+
{
13+
/// <summary>
14+
/// Identifies the use of bang notation, formally known as dictionary access expression, for which the default member is not known at compile time.
15+
/// </summary>
16+
/// <why>
17+
/// A dictionary access expression looks like a strongly typed call, but it actually is a stringly typed access to the parameterized default member of the object.
18+
/// This is especially misleading the default member cannot be determined at compile time.
19+
/// </why>
20+
/// <example hasResult="true">
21+
/// <![CDATA[
22+
/// Public Function MyName(ByVal rst As Object) As Variant
23+
/// MyName = rst!Name.Value
24+
/// End Function
25+
/// ]]>
26+
/// </example>
27+
/// <example hasResult="true">
28+
/// <![CDATA[
29+
/// Public Function MyName(ByVal rst As Variant) As Variant
30+
/// With rst
31+
/// MyName = !Name.Value
32+
/// End With
33+
/// End Function
34+
/// ]]>
35+
/// </example>
36+
/// <example hasResult="false">
37+
/// <![CDATA[
38+
/// Public Function MyName(ByVal rst As ADODB.Recordset) As Variant
39+
/// MyName = rst!Name.Value
40+
/// End Function
41+
/// ]]>
42+
/// </example>
43+
/// <example hasResult="false">
44+
/// <![CDATA[
45+
/// Public Function MyName(ByVal rst As Object) As Variant
46+
/// MyName = rst("Name").Value
47+
/// End Function
48+
/// ]]>
49+
/// </example>
50+
/// <example hasResult="false">
51+
/// <![CDATA[
52+
/// Public Function MyName(ByVal rst As Variant) As Variant
53+
/// With rst
54+
/// MyName = .Fields.Item("Name").Value
55+
/// End With
56+
/// End Function
57+
/// ]]>
58+
/// </example>
59+
public sealed class UseOfUnboundBangNotationInspection : IdentifierReferenceInspectionBase
60+
{
61+
public UseOfUnboundBangNotationInspection(RubberduckParserState state)
62+
: base(state)
63+
{
64+
Severity = CodeInspectionSeverity.Warning;
65+
}
66+
67+
protected override IEnumerable<IdentifierReference> ReferencesInModule(QualifiedModuleName module)
68+
{
69+
return DeclarationFinderProvider.DeclarationFinder.UnboundDefaultMemberAccesses(module);
70+
}
71+
72+
protected override bool IsResultReference(IdentifierReference reference)
73+
{
74+
return reference.IsIndexedDefaultMemberAccess
75+
&& reference.Context is VBAParser.DictionaryAccessContext
76+
&& !reference.IsIgnoringInspectionResultFor(AnnotationName);
77+
}
78+
79+
protected override string ResultDescription(IdentifierReference reference)
80+
{
81+
var expression = reference.IdentifierName;
82+
return string.Format(InspectionResults.UseOfRecursiveBangNotationInspection, expression);
83+
}
84+
}
85+
}

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
@@ -409,4 +409,7 @@ Falls der Parameter 'null' sein kann, bitte dieses Auftreten ignorieren. 'null'
409409
<data name="UseOfRecursiveBangNotationInspection" xml:space="preserve">
410410
<value>Die Ausrufezeichennotation erweckt den Eindruck, dass es sich um einen Zugriff handelt, der Typchecks unterliegt. Allerdings handelt es sich lediglich um einen Zugriff auf den Standardmember des Objekts, auf das sie angewendet wird, bei dem das Argument als Zeichenkette übergeben wird. Dies ist besonders verwirrend, wenn der Standardmember des Objekts selber keine Zeichenkette akzeptiert und deshalb ein rekursiver Zugriff auf den parameterlosen Standardmember erfolgen muss.</value>
411411
</data>
412+
<data name="UseOfUnboundBangNotationInspection" xml:space="preserve">
413+
<value>Die Ausrufezeichennotation erweckt den Eindruck, dass es sich um einen Zugriff handelt, der Typchecks unterliegt. Allerdings handelt es sich lediglich um einen Zugriff auf den Standardmember des Objekts, auf das sie angewendet wird, bei dem das Argument als Zeichenkette übergeben wird. Dies ist besonders verwirrend, wenn der Standardmember nicht zum Zeitpunkt des Kompilierens ermittelt werden kann.</value>
414+
</data>
412415
</root>

Rubberduck.Resources/Inspections/InspectionInfo.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,4 +409,7 @@ If the parameter can be null, ignore this inspection result; passing a null valu
409409
<data name="UseOfRecursiveBangNotationInspection" xml:space="preserve">
410410
<value>Bang notation, formally known as dictionary access expression, looks like it is strongly typed. However, it is actually a stringly typed access to the paramterized default member of the object it is used on. This is especially misleading if the parameterized default member is not on the object itself and can only be reached by calling the parameterless default member first. </value>
411411
</data>
412+
<data name="UseOfUnboundBangNotationInspection" xml:space="preserve">
413+
<value>Bang notation, formally known as dictionary access expression, looks like it is strongly typed. However, it is actually a stringly typed access to the paramterized default member of the object it is used on. This is especially misleading the default member cannot be determined at compile time.</value>
414+
</data>
412415
</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
@@ -393,4 +393,7 @@
393393
<data name="UseOfRecursiveBangNotationInspection" xml:space="preserve">
394394
<value>Verwendung rekursiver Ausrufezeichennotation</value>
395395
</data>
396+
<data name="UseOfUnboundBangNotationInspection" xml:space="preserve">
397+
<value>Verwendung nicht gebundener Ausrufezeichennotation</value>
398+
</data>
396399
</root>

Rubberduck.Resources/Inspections/InspectionNames.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,4 +413,7 @@
413413
<data name="UseOfRecursiveBangNotationInspection" xml:space="preserve">
414414
<value>Use of recursive bang notation</value>
415415
</data>
416+
<data name="UseOfUnboundBangNotationInspection" xml:space="preserve">
417+
<value>Use of unbound bang notation</value>
418+
</data>
416419
</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
@@ -434,4 +434,7 @@ In Memoriam, 1972-2018</value>
434434
<data name="UseOfRecursiveBangNotationInspection" xml:space="preserve">
435435
<value>Der Ausdruck '{0}' verwendet rekursive Ausrufezeichennotation.</value>
436436
</data>
437+
<data name="UseOfUnboundBangNotationInspection" xml:space="preserve">
438+
<value>Der Ausdruck '{0}' verwendet nicht gebundene Ausrufezeichennotation.</value>
439+
</data>
437440
</root>

0 commit comments

Comments
 (0)