Skip to content

Commit 80652c0

Browse files
committed
resolved merge conflicts
2 parents a107d9f + b174d9c commit 80652c0

33 files changed

+1172
-825
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ Rubberduck is a COM Add-In for the VBA IDE that makes VBA development even more
66

77
If you're learning VBA, Rubberduck can help you avoid a few common beginner mistakes, and can probably show you a trick or two - even if you're only ever writing *macros*. If you're a more advanced programmer, you will appreciate the richness of Rubberduck's feature set.
88

9+
[**Follow us on Twitter!**](https://twitter.com/rubberduckvba)
10+
11+
912
---
1013

1114
#Features

RetailCoder.VBE/Extensions/Selection.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@ namespace Rubberduck.Extensions
55
{
66
public struct QualifiedSelection
77
{
8-
public QualifiedSelection(string projectName, string moduleName, Selection selection)
9-
: this(new QualifiedModuleName(projectName, moduleName), selection) { }
10-
118
public QualifiedSelection(QualifiedModuleName qualifiedName, Selection selection)
129
{
1310
_qualifiedName = qualifiedName;

RetailCoder.VBE/Extensions/VBComponentsExtensions.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,23 @@
44
using System.Text;
55
using System.Threading.Tasks;
66
using Microsoft.Vbe.Interop;
7+
using Rubberduck.Inspections;
78
using Rubberduck.VBA;
89

910
namespace Rubberduck.Extensions
1011
{
1112
public static class VBComponentsExtensions
1213
{
14+
public static QualifiedModuleName QualifiedName(this VBComponent component)
15+
{
16+
var moduleName = component.Name;
17+
var project = component.Collection.Parent;
18+
var hash = project.GetHashCode();
19+
var code = component.CodeModule.Lines().GetHashCode();
20+
21+
return new QualifiedModuleName(project.Name, moduleName, hash, code);
22+
}
23+
1324
/// <summary>
1425
/// Safely removes the specified VbComponent from the collection.
1526
/// </summary>

RetailCoder.VBE/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.

RetailCoder.VBE/Inspections/InspectionNames.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@
141141
<data name="OptionExplicit" xml:space="preserve">
142142
<value>Option Explicit is not specified</value>
143143
</data>
144+
<data name="VariableNotAssigned" xml:space="preserve">
145+
<value>Variable is never assigned</value>
146+
</data>
144147
<data name="VariableTypeNotDeclared" xml:space="preserve">
145148
<value>Variable type is implicitly Variant</value>
146149
</data>
Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,48 @@
1-
using System.Runtime.InteropServices;
21

32
namespace Rubberduck.Inspections
43
{
5-
[ComVisible(false)]
4+
public struct QualifiedMemberName
5+
{
6+
public QualifiedMemberName(QualifiedModuleName moduleScope, string member)
7+
{
8+
_moduleScope = moduleScope;
9+
_member = member;
10+
}
11+
12+
private readonly QualifiedModuleName _moduleScope;
13+
public QualifiedModuleName ModuleScope { get { return _moduleScope; } }
14+
15+
private readonly string _member;
16+
public string MemberName { get { return _member; } }
17+
18+
public override int GetHashCode()
19+
{
20+
return (_moduleScope.GetHashCode().ToString() + _member).GetHashCode();
21+
}
22+
23+
public override bool Equals(object obj)
24+
{
25+
return obj.GetHashCode() == GetHashCode();
26+
}
27+
}
28+
629
public struct QualifiedModuleName
730
{
8-
public QualifiedModuleName(string project, string module)
31+
public QualifiedModuleName(string project, string module, int projectHashCode, int contentHashCode)
932
{
33+
_projectHash = projectHashCode;
34+
_contentHashCode = contentHashCode;
1035
_project = project;
1136
_module = module;
1237
}
1338

14-
public static QualifiedModuleName Empty { get { return new QualifiedModuleName(string.Empty, string.Empty); } }
39+
public static QualifiedModuleName Empty { get { return new QualifiedModuleName(string.Empty, string.Empty, default(int), default(int)); } }
40+
41+
private readonly int _projectHash;
42+
public int ProjectHashCode { get { return _projectHash; } }
43+
44+
private readonly int _contentHashCode;
45+
public int ContentHashCode { get { return _contentHashCode; } }
1546

1647
private readonly string _project;
1748
public string ProjectName { get { return _project; } }
@@ -23,5 +54,15 @@ public override string ToString()
2354
{
2455
return _project + "." + _module;
2556
}
57+
58+
public override int GetHashCode()
59+
{
60+
return (_projectHash.ToString() + _contentHashCode.ToString() + ToString()).GetHashCode();
61+
}
62+
63+
public override bool Equals(object obj)
64+
{
65+
return obj.GetHashCode() == GetHashCode();
66+
}
2667
}
2768
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Antlr4.Runtime;
4+
using Microsoft.Vbe.Interop;
5+
using Rubberduck.Extensions;
6+
using Rubberduck.VBA;
7+
using Rubberduck.VBA.Grammar;
8+
using Rubberduck.VBA.Nodes;
9+
using Rubberduck.VBA.ParseTreeListeners;
10+
11+
namespace Rubberduck.Inspections
12+
{
13+
public class VariableNotAssignedInspection : IInspection
14+
{
15+
public VariableNotAssignedInspection()
16+
{
17+
Severity = CodeInspectionSeverity.Error;
18+
}
19+
20+
public string Name { get { return InspectionNames.VariableNotAssigned; } }
21+
public CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } }
22+
public CodeInspectionSeverity Severity { get; set; }
23+
24+
public IEnumerable<CodeInspectionResultBase> GetInspectionResults(IEnumerable<VBComponentParseResult> parseResult)
25+
{
26+
var parseResults = parseResult.ToList();
27+
28+
// publics & globals delared at module-scope in standard modules:
29+
var globals =
30+
parseResults.Select(result =>
31+
new
32+
{
33+
Name = result.QualifiedName,
34+
Globals = result.ParseTree.GetContexts<DeclarationSectionListener, ParserRuleContext>(new DeclarationSectionListener())
35+
.OfType<VisualBasic6Parser.VariableStmtContext>()
36+
.Where(context =>
37+
context.visibility() != null &&
38+
context.visibility().GetText() != Tokens.Private)
39+
.SelectMany(context => context.variableListStmt().variableSubStmt()
40+
.Select(variable => variable.ambiguousIdentifier()))
41+
})
42+
.SelectMany(module => module.Globals.Select(global =>
43+
new
44+
{
45+
Name = module.Name,
46+
Global = global
47+
})).ToList();
48+
49+
var assignedGlobals = new List<VisualBasic6Parser.AmbiguousIdentifierContext>();
50+
var unassignedDeclarations = new List<CodeInspectionResultBase>();
51+
52+
foreach (var result in parseResults)
53+
{
54+
// module-scoped in this module:
55+
var declarations = result.ParseTree.GetContexts<DeclarationSectionListener, ParserRuleContext>(new DeclarationSectionListener())
56+
.OfType<VisualBasic6Parser.VariableSubStmtContext>()
57+
.Where(variable => globals.All(global => global.Global.GetText() != variable.GetText()))
58+
.ToList();
59+
var procedures = result.ParseTree.GetContexts<ProcedureListener, ParserRuleContext>(new ProcedureListener()).ToList();
60+
61+
// fetch & scope all assignments:
62+
var assignments = procedures.SelectMany(
63+
procedure => procedure.GetContexts<VariableAssignmentListener, VisualBasic6Parser.AmbiguousIdentifierContext>(new VariableAssignmentListener())
64+
.Select(context => new
65+
{
66+
Scope = new QualifiedMemberName(result.QualifiedName, ((dynamic)procedure).ambiguousIdentifier().GetText()),
67+
Name = context.GetText()
68+
}));
69+
70+
// fetch & scope all procedure-scoped declarations:
71+
var locals = procedures.SelectMany(
72+
procedure => procedure.GetContexts<DeclarationListener, ParserRuleContext>(new DeclarationListener())
73+
.OfType<VisualBasic6Parser.VariableSubStmtContext>()
74+
.Select(context => new
75+
{
76+
Context = context,
77+
Scope = new QualifiedMemberName(result.QualifiedName, ((dynamic)procedure).ambiguousIdentifier().GetText()),
78+
Name = context.ambiguousIdentifier().GetText()
79+
}));
80+
81+
// identify unassigned module-scoped declarations:
82+
unassignedDeclarations.AddRange(
83+
declarations.Select(d => d.ambiguousIdentifier())
84+
.Where(d => globals.All(g => g.Global.GetText() != d.GetText())
85+
&& assignments.All(a => a.Name != d.GetText()))
86+
.Select(identifier => new VariableNotAssignedInspetionResult(Name, Severity, identifier, result.QualifiedName)));
87+
88+
// identify unassigned procedure-scoped declarations:
89+
unassignedDeclarations.AddRange(
90+
locals.Where(local => assignments.All(a => (a.Scope.MemberName + a.Name) != (local.Scope.MemberName + local.Name)))
91+
.Select(identifier => new VariableNotAssignedInspetionResult(Name, Severity, identifier.Context.ambiguousIdentifier(), result.QualifiedName)));
92+
93+
// identify globals assigned in this module:
94+
assignedGlobals.AddRange(globals.Where(global => assignments.Any(a => a.Name == global.Global.GetText()))
95+
.Select(global => global.Global));
96+
}
97+
98+
// identify unassigned globals:
99+
var assignedIdentifiers = assignedGlobals.Select(assigned => assigned.GetText());
100+
var unassignedGlobals = globals.Where(global => !assignedIdentifiers.Contains(global.Global.GetText()))
101+
.Select(identifier => new VariableNotAssignedInspetionResult(Name, Severity, identifier.Global, identifier.Name));
102+
unassignedDeclarations.AddRange(unassignedGlobals);
103+
104+
return unassignedDeclarations;
105+
}
106+
}
107+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Antlr4.Runtime;
5+
using Microsoft.Vbe.Interop;
6+
using Rubberduck.Extensions;
7+
8+
namespace Rubberduck.Inspections
9+
{
10+
public class VariableNotAssignedInspetionResult : CodeInspectionResultBase
11+
{
12+
public VariableNotAssignedInspetionResult(string inspection, CodeInspectionSeverity type,
13+
ParserRuleContext context, QualifiedModuleName qualifiedName)
14+
: base(inspection, type, qualifiedName, context)
15+
{
16+
}
17+
18+
public override IDictionary<string, Action<VBE>> GetQuickFixes()
19+
{
20+
return
21+
new Dictionary<string, Action<VBE>>
22+
{
23+
{"Remove unassigned variable (and usages)", RemoveVariableDeclaration}
24+
};
25+
}
26+
27+
private void RemoveVariableDeclaration(VBE vbe)
28+
{
29+
var module = vbe.FindCodeModules(QualifiedName).First();
30+
var selection = QualifiedSelection.Selection;
31+
32+
var originalCodeLines = module.get_Lines(selection.StartLine, selection.LineCount)
33+
.Replace("\r\n", " ")
34+
.Replace("_", string.Empty);
35+
36+
var originalInstruction = Context.GetText();
37+
module.DeleteLines(selection.StartLine, selection.LineCount);
38+
39+
var newInstruction = string.Empty;
40+
var newCodeLines = string.IsNullOrEmpty(newInstruction)
41+
? string.Empty
42+
: originalCodeLines.Replace(originalInstruction, newInstruction);
43+
44+
if (!string.IsNullOrEmpty(newCodeLines))
45+
{
46+
module.InsertLines(selection.StartLine, newCodeLines);
47+
}
48+
}
49+
50+
private void RemoveVariableUsages(VBE vbe)
51+
{
52+
53+
}
54+
}
55+
}

RetailCoder.VBE/Inspections/VariableTypeNotDeclaredInspection.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
namespace Rubberduck.Inspections
1313
{
14-
[ComVisible(false)]
1514
public class VariableTypeNotDeclaredInspection : IInspection
1615
{
1716
public VariableTypeNotDeclaredInspection()

RetailCoder.VBE/Inspections/VariableTypeNotDeclaredInspectionResult.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
namespace Rubberduck.Inspections
1111
{
12-
[ComVisible(false)]
1312
public class VariableTypeNotDeclaredInspectionResult : CodeInspectionResultBase
1413
{
1514
public VariableTypeNotDeclaredInspectionResult(string inspection, CodeInspectionSeverity type, ParserRuleContext context, QualifiedModuleName qualifiedName)

0 commit comments

Comments
 (0)