Skip to content

Commit 043cf59

Browse files
committed
fixed some false positives... still has issues with resolving member calls (can resolve to parameter name if there's a parameter with same name as invoked member method in procedure)
1 parent c58ad9f commit 043cf59

10 files changed

+423
-137
lines changed

RetailCoder.VBE/Inspections/ParameterCanBeByValInspection.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,23 @@ public IEnumerable<CodeInspectionResultBase> GetInspectionResults(VBProjectParse
3939
.Concat(parseResult.Declarations.FindInterfaceImplementationMembers())
4040
.ToList();
4141

42+
var formEventHandlerScopes = parseResult.Declarations.FindFormEventHandlers()
43+
.Select(handler => handler.Scope);
44+
45+
var eventScopes = parseResult.Declarations.Items.Where(item =>
46+
!item.IsBuiltIn && item.DeclarationType == DeclarationType.Event)
47+
.Select(e => e.Scope);
48+
49+
var declareScopes = parseResult.Declarations.Items.Where(item =>
50+
item.DeclarationType == DeclarationType.LibraryFunction
51+
|| item.DeclarationType == DeclarationType.LibraryProcedure)
52+
.Select(e => e.Scope);
53+
54+
var ignoredScopes = formEventHandlerScopes.Concat(eventScopes).Concat(declareScopes);
55+
4256
var issues = parseResult.Declarations.Items.Where(declaration =>
43-
!declaration.IsBuiltIn && declaration.DeclarationType == DeclarationType.Parameter
57+
!ignoredScopes.Contains(declaration.ParentScope)
58+
&& declaration.DeclarationType == DeclarationType.Parameter
4459
&& !interfaceMembers.Select(m => m.Scope).Contains(declaration.ParentScope)
4560
&& PrimitiveTypes.Contains(declaration.AsTypeName)
4661
&& ((VBAParser.ArgContext) declaration.Context).BYVAL() == null
@@ -49,5 +64,7 @@ public IEnumerable<CodeInspectionResultBase> GetInspectionResults(VBProjectParse
4964

5065
return issues;
5166
}
67+
68+
5269
}
5370
}

RetailCoder.VBE/Inspections/ParameterNotUsedInspection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public IEnumerable<CodeInspectionResultBase> GetInspectionResults(VBProjectParse
3131

3232
var issues = from issue in unused.Where(parameter => !IsInterfaceMemberParameter(parameter, interfaceMemberScopes))
3333
let isInterfaceImplementationMember = IsInterfaceMemberImplementationParameter(issue, interfaceImplementationMemberScopes)
34-
select new ParameterNotUsedInspectionResult(string.Format(Name, issue.IdentifierName), Severity, issue.Context, issue.QualifiedName, isInterfaceImplementationMember);
34+
select new ParameterNotUsedInspectionResult(string.Format(Name, issue.IdentifierName), Severity, ((dynamic)issue.Context).ambiguousIdentifier(), issue.QualifiedName, isInterfaceImplementationMember);
3535

3636
return issues.ToList();
3737
}

RetailCoder.VBE/Inspections/ProcedureNotUsedInspection.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Collections.Generic;
22
using System.Linq;
3+
using Microsoft.Vbe.Interop;
34
using Rubberduck.Parsing;
45
using Rubberduck.Parsing.Grammar;
56
using Rubberduck.Parsing.Symbols;
@@ -25,6 +26,19 @@ public IEnumerable<CodeInspectionResultBase> GetInspectionResults(VBProjectParse
2526
var handlers = parseResult.Declarations.Items.Where(item => !item.IsBuiltIn && item.DeclarationType == DeclarationType.Control)
2627
.SelectMany(control => parseResult.Declarations.FindEventHandlers(control)).ToList();
2728

29+
var withEventFields = parseResult.Declarations.Items.Where(item => !item.IsBuiltIn && item.DeclarationType == DeclarationType.Variable && item.IsWithEvents);
30+
handlers.AddRange(withEventFields.SelectMany(field => parseResult.Declarations.FindEventProcedures(field)));
31+
32+
var forms = parseResult.Declarations.Items.Where(
33+
item => !item.IsBuiltIn && item.DeclarationType == DeclarationType.Class
34+
&& item.QualifiedName.QualifiedModuleName.Component.Type == vbext_ComponentType.vbext_ct_MSForm)
35+
.ToList();
36+
37+
if (forms.Any())
38+
{
39+
handlers.AddRange(forms.SelectMany(form => parseResult.Declarations.FindFormEventHandlers(form)));
40+
}
41+
2842
var issues = parseResult.Declarations.Items
2943
.Where(item => !item.IsBuiltIn && !IsIgnoredDeclaration(parseResult.Declarations, item, handlers, classes, modules))
3044
.Select(issue => new IdentifierNotUsedInspectionResult(string.Format(Name, issue.IdentifierName), Severity, issue.Context, issue.QualifiedName.QualifiedModuleName))
@@ -98,23 +112,24 @@ private bool IsClassLifeCycleHandler(IEnumerable<Declaration> classes, Declarati
98112
private bool IsInterfaceMember(Declarations declarations, IEnumerable<Declaration> classes, Declaration procedure)
99113
{
100114
// get the procedure's parent module
101-
var parent = classes.Where(item => item.Project == procedure.Project)
115+
var enumerable = classes as IList<Declaration> ?? classes.ToList();
116+
var parent = enumerable.Where(item => item.Project == procedure.Project)
102117
.SingleOrDefault(item => item.IdentifierName == procedure.ComponentName);
103118

104119
if (parent == null)
105120
{
106121
return false;
107122
}
108123

109-
var interfaces = classes.Where(item => item.References.Any(reference =>
124+
var interfaces = enumerable.Where(item => item.References.Any(reference =>
110125
reference.Context.Parent is VBAParser.ImplementsStmtContext));
111126

112127
if (interfaces.Select(i => i.ComponentName).Contains(procedure.ComponentName))
113128
{
114129
return true;
115130
}
116131

117-
var result = GetImplementedInterfaceMembers(declarations, classes, procedure.ComponentName)
132+
var result = GetImplementedInterfaceMembers(declarations, enumerable, procedure.ComponentName)
118133
.Contains(procedure.IdentifierName);
119134

120135
return result;

RetailCoder.VBE/UI/CodeExplorer/CodeExplorerDockablePresenter.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,6 @@ private async void RefreshExplorerTreeView()
185185
Control.SolutionTree.Nodes.Clear();
186186
Control.ShowDesignerButton.Enabled = false;
187187
});
188-
189188

190189
var projects = VBE.VBProjects.Cast<VBProject>();
191190
foreach (var vbProject in projects)

Rubberduck.Parsing/Rubberduck.Parsing.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
</Compile>
8585
<Compile Include="Symbols\IdentifierReference.cs" />
8686
<Compile Include="Symbols\IdentifierReferenceListener.cs" />
87+
<Compile Include="Symbols\MsFormsLib.cs" />
8788
<Compile Include="Symbols\VbaStandardLib.cs" />
8889
<Compile Include="VBComponentParseResult.cs" />
8990
<Compile Include="VBProjectParseResult.cs" />

Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ public override void EnterArgList(VBAParser.ArgListContext context)
258258
: asTypeClause.type().GetText();
259259

260260
var identifier = argContext.ambiguousIdentifier();
261-
_declarations.Add(CreateDeclaration(identifier.GetText(), asTypeName, Accessibility.Implicit, DeclarationType.Parameter, argContext, argContext.GetSelection()));
261+
_declarations.Add(CreateDeclaration(identifier.GetText(), asTypeName, Accessibility.Implicit, DeclarationType.Parameter, argContext, argContext.ambiguousIdentifier().GetSelection()));
262262
}
263263
}
264264

Rubberduck.Parsing/Symbols/Declarations.cs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
using System.Collections.Concurrent;
1+
using System.CodeDom;
2+
using System.Collections.Concurrent;
23
using System.Collections.Generic;
34
using System.Linq;
5+
using Antlr4.Runtime.Tree;
6+
using Microsoft.Vbe.Interop;
47
using Rubberduck.Parsing.Grammar;
58

69
namespace Rubberduck.Parsing.Symbols
@@ -81,6 +84,68 @@ public IEnumerable<Declaration> FindInterfaceMembers()
8184
return _interfaceMembers;
8285
}
8386

87+
public IEnumerable<Declaration> FindFormEventHandlers()
88+
{
89+
var forms = _declarations.Where(item => item.DeclarationType == DeclarationType.Class
90+
&& item.QualifiedName.QualifiedModuleName.Component != null
91+
&& item.QualifiedName.QualifiedModuleName.Component.Type == vbext_ComponentType.vbext_ct_MSForm)
92+
.ToList();
93+
94+
var result = new List<Declaration>();
95+
foreach (var declaration in forms)
96+
{
97+
result.AddRange(FindFormEventHandlers(declaration));
98+
}
99+
100+
return result;
101+
}
102+
103+
public IEnumerable<Declaration> FindFormEventHandlers(Declaration userForm)
104+
{
105+
var events = _declarations.Where(item => item.IsBuiltIn
106+
&& item.ParentScope == "MSForms.UserForm"
107+
&& item.DeclarationType == DeclarationType.Event).ToList();
108+
var handlerNames = events.Select(item => "UserForm_" + item.IdentifierName);
109+
var handlers = _declarations.Where(item => item.ParentScope == userForm.Scope
110+
&& item.DeclarationType == DeclarationType.Procedure
111+
&& handlerNames.Contains(item.IdentifierName));
112+
113+
return handlers.ToList();
114+
}
115+
116+
public IEnumerable<Declaration> FindEventProcedures(Declaration withEventsDeclaration)
117+
{
118+
if (!withEventsDeclaration.IsWithEvents)
119+
{
120+
return new Declaration[]{};
121+
}
122+
123+
var type = _declarations.SingleOrDefault(item => item.DeclarationType == DeclarationType.Class
124+
&& item.Project != null
125+
&& item.IdentifierName == withEventsDeclaration.AsTypeName.Split('.').Last());
126+
127+
if (type == null)
128+
{
129+
return new Declaration[]{};
130+
}
131+
132+
var members = GetTypeMembers(type).ToList();
133+
var events = members.Where(member => member.DeclarationType == DeclarationType.Event);
134+
var handlerNames = events.Select(e => withEventsDeclaration.IdentifierName + '_' + e.IdentifierName);
135+
136+
return _declarations.Where(item => item.Project != null
137+
&& item.Project.Equals(withEventsDeclaration.Project)
138+
&& item.ParentScope == withEventsDeclaration.ParentScope
139+
&& item.DeclarationType == DeclarationType.Procedure
140+
&& handlerNames.Any(name => item.IdentifierName == name))
141+
.ToList();
142+
}
143+
144+
private IEnumerable<Declaration> GetTypeMembers(Declaration type)
145+
{
146+
return _declarations.Where(item => item.Project != null && item.Project.Equals(type.Project) && item.ParentScope == type.Scope);
147+
}
148+
84149
private IEnumerable<Declaration> _interfaceImplementationMembers;
85150

86151
/// <summary>

0 commit comments

Comments
 (0)