5
5
using Rubberduck . Inspections . CodePathAnalysis ;
6
6
using Rubberduck . Inspections . CodePathAnalysis . Extensions ;
7
7
using Rubberduck . Inspections . CodePathAnalysis . Nodes ;
8
+ using Rubberduck . Parsing ;
8
9
using Rubberduck . Parsing . Grammar ;
9
10
using Rubberduck . Parsing . Symbols ;
10
11
using Rubberduck . Parsing . VBA ;
@@ -67,7 +68,7 @@ private IEnumerable<IdentifierReference> UnusedAssignments(Declaration localVari
67
68
return UnusedAssignmentReferences ( tree ) ;
68
69
}
69
70
70
- public static List < IdentifierReference > UnusedAssignmentReferences ( INode node )
71
+ private static List < IdentifierReference > UnusedAssignmentReferences ( INode node )
71
72
{
72
73
var nodes = new List < IdentifierReference > ( ) ;
73
74
@@ -98,7 +99,8 @@ public static List<IdentifierReference> UnusedAssignmentReferences(INode node)
98
99
99
100
protected override bool IsResultReference ( IdentifierReference reference , DeclarationFinder finder )
100
101
{
101
- return ! IsAssignmentOfNothing ( reference ) ;
102
+ return ! ( IsAssignmentOfNothing ( reference )
103
+ || DisqualifiedByResumeOrGoToStatements ( reference , finder ) ) ;
102
104
}
103
105
104
106
private static bool IsAssignmentOfNothing ( IdentifierReference reference )
@@ -108,6 +110,38 @@ private static bool IsAssignmentOfNothing(IdentifierReference reference)
108
110
&& setStmtContext . expression ( ) . GetText ( ) . Equals ( Tokens . Nothing ) ;
109
111
}
110
112
113
+ private static bool DisqualifiedByResumeOrGoToStatements ( IdentifierReference resultCandidate , DeclarationFinder finder )
114
+ {
115
+ var relevantLabels = finder . DeclarationsWithType ( DeclarationType . LineLabel )
116
+ . Where ( label => resultCandidate . ParentScoping . Equals ( label . ParentDeclaration ) ) ;
117
+
118
+ if ( ! relevantLabels . Any ( ) )
119
+ {
120
+ return false ;
121
+ }
122
+
123
+ var lineNumbersForNonAssignmentReferencesOfResultCandidateDeclaration =
124
+ resultCandidate . Declaration . References
125
+ . Where ( rf => ! rf . IsAssignment )
126
+ . Select ( rf => rf . Context . Stop . Line ) ;
127
+
128
+ if ( ! lineNumbersForNonAssignmentReferencesOfResultCandidateDeclaration . Any ( ) )
129
+ {
130
+ return false ;
131
+ }
132
+
133
+ var labelReferencesAffectingExecutionPath = relevantLabels . SelectMany ( d => d . References )
134
+ . Where ( labelReference => LabelReferencedByJumpStatementAfterResultCandidateAssignment ( labelReference , resultCandidate ) ) ;
135
+
136
+ return labelReferencesAffectingExecutionPath . Any ( labelReference => labelReference . Declaration . Context . Stop . Line < resultCandidate . Context . Start . Line
137
+ && labelReference . Declaration . Context . Start . Line < lineNumbersForNonAssignmentReferencesOfResultCandidateDeclaration . Max ( ) ) ;
138
+ }
139
+
140
+ private static bool LabelReferencedByJumpStatementAfterResultCandidateAssignment ( IdentifierReference labelReference , IdentifierReference resultCandidate )
141
+ => labelReference . Context . Start . Line > resultCandidate . Context . Stop . Line
142
+ && ( labelReference . Context . TryGetAncestor < VBAParser . ResumeStmtContext > ( out _ )
143
+ || labelReference . Context . TryGetAncestor < VBAParser . GoToStmtContext > ( out _ ) ) ;
144
+
111
145
protected override string ResultDescription ( IdentifierReference reference )
112
146
{
113
147
return Description ;
0 commit comments