Skip to content

Commit 3e5bc55

Browse files
committed
Fix Use Meaningful Name selection and Remove Identifier Not Used--Variable quick fix
1 parent 3e0a5bf commit 3e5bc55

File tree

2 files changed

+130
-15
lines changed

2 files changed

+130
-15
lines changed

RetailCoder.VBE/Inspections/IdentifierNotUsedInspectionResult.cs

Lines changed: 125 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
using System;
12
using System.Collections.Generic;
3+
using System.Linq;
24
using Antlr4.Runtime;
35
using Rubberduck.Common;
46
using Rubberduck.Parsing.Symbols;
7+
using Rubberduck.Parsing.VBA;
58
using Rubberduck.UI;
69
using Rubberduck.VBEditor;
10+
using Rubberduck.VBEditor.Extensions;
711

812
namespace Rubberduck.Inspections
913
{
@@ -17,7 +21,7 @@ public IdentifierNotUsedInspectionResult(IInspection inspection, Declaration tar
1721
{
1822
_quickFixes = new CodeInspectionQuickFix[]
1923
{
20-
new RemoveUnusedDeclarationQuickFix(context, QualifiedSelection),
24+
new RemoveUnusedDeclarationQuickFix(context, QualifiedSelection, Target),
2125
new IgnoreOnceQuickFix(context, QualifiedSelection, Inspection.AnnotationName),
2226
};
2327
}
@@ -42,32 +46,138 @@ public override NavigateCodeEventArgs GetNavigationArgs()
4246
/// </summary>
4347
public class RemoveUnusedDeclarationQuickFix : CodeInspectionQuickFix
4448
{
45-
public RemoveUnusedDeclarationQuickFix(ParserRuleContext context, QualifiedSelection selection)
49+
private readonly Declaration _target;
50+
51+
public RemoveUnusedDeclarationQuickFix(ParserRuleContext context, QualifiedSelection selection, Declaration target)
4652
: base(context, selection, InspectionsUI.RemoveUnusedDeclarationQuickFix)
4753
{
54+
_target = target;
4855
}
4956

5057
public override void Fix()
5158
{
52-
var module = Selection.QualifiedName.Component.CodeModule;
53-
var selection = Selection.Selection;
59+
if (_target.DeclarationType == DeclarationType.Variable)
60+
{
61+
RemoveVariable(_target);
62+
}
63+
else
64+
{
65+
var module = Selection.QualifiedName.Component.CodeModule;
66+
var selection = Selection.Selection;
67+
68+
var originalCodeLines = module.Lines[selection.StartLine, selection.LineCount]
69+
.Replace("\r\n", " ")
70+
.Replace("_", string.Empty);
71+
72+
var originalInstruction = Context.GetText();
73+
module.DeleteLines(selection.StartLine, selection.LineCount);
74+
75+
var newCodeLines = originalCodeLines.Replace(originalInstruction, string.Empty);
76+
if (!string.IsNullOrEmpty(newCodeLines))
77+
{
78+
module.InsertLines(selection.StartLine, newCodeLines);
79+
}
80+
}
81+
}
82+
83+
private void RemoveVariable(Declaration target)
84+
{
85+
Selection selection;
86+
var declarationText = target.Context.GetText().Replace(" _" + Environment.NewLine, string.Empty);
87+
var multipleDeclarations = target.HasMultipleDeclarationsInStatement();
88+
89+
var variableStmtContext = target.GetVariableStmtContext();
90+
91+
if (!multipleDeclarations)
92+
{
93+
declarationText = variableStmtContext.GetText().Replace(" _" + Environment.NewLine, string.Empty);
94+
selection = target.GetVariableStmtContextSelection();
95+
}
96+
else
97+
{
98+
selection = new Selection(target.Context.Start.Line, target.Context.Start.Column,
99+
target.Context.Stop.Line, target.Context.Stop.Column);
100+
}
54101

55-
var originalCodeLines = module.get_Lines(selection.StartLine, selection.LineCount)
56-
.Replace("\r\n", " ")
57-
.Replace("_", string.Empty);
102+
var codeModule = target.QualifiedName.QualifiedModuleName.Component.CodeModule;
103+
var oldLines = codeModule.GetLines(selection);
58104

59-
var originalInstruction = Context.GetText();
60-
module.DeleteLines(selection.StartLine, selection.LineCount);
105+
var newLines = oldLines.Replace(" _" + Environment.NewLine, string.Empty)
106+
.Remove(selection.StartColumn, declarationText.Length);
61107

62-
var newInstruction = string.Empty;
63-
var newCodeLines = string.IsNullOrEmpty(newInstruction)
64-
? string.Empty
65-
: originalCodeLines.Replace(originalInstruction, newInstruction);
108+
if (multipleDeclarations)
109+
{
110+
selection = target.GetVariableStmtContextSelection();
111+
newLines = RemoveExtraComma(codeModule.GetLines(selection).Replace(oldLines, newLines),
112+
target.CountOfDeclarationsInStatement(), target.IndexOfVariableDeclarationInStatement());
113+
}
66114

67-
if (!string.IsNullOrEmpty(newCodeLines))
115+
var newLinesWithoutExcessSpaces = newLines.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
116+
for (var i = 0; i < newLinesWithoutExcessSpaces.Length; i++)
68117
{
69-
module.InsertLines(selection.StartLine, newCodeLines);
118+
newLinesWithoutExcessSpaces[i] = newLinesWithoutExcessSpaces[i].RemoveExtraSpacesLeavingIndentation();
70119
}
120+
121+
for (var i = newLinesWithoutExcessSpaces.Length - 1; i >= 0; i--)
122+
{
123+
if (newLinesWithoutExcessSpaces[i].Trim() == string.Empty)
124+
{
125+
continue;
126+
}
127+
128+
if (newLinesWithoutExcessSpaces[i].EndsWith(" _"))
129+
{
130+
newLinesWithoutExcessSpaces[i] =
131+
newLinesWithoutExcessSpaces[i].Remove(newLinesWithoutExcessSpaces[i].Length - 2);
132+
}
133+
break;
134+
}
135+
136+
// remove all lines with only whitespace
137+
newLinesWithoutExcessSpaces = newLinesWithoutExcessSpaces.Where(str => str.Any(c => !char.IsWhiteSpace(c))).ToArray();
138+
139+
codeModule.DeleteLines(selection);
140+
if (newLinesWithoutExcessSpaces.Any())
141+
{
142+
codeModule.InsertLines(selection.StartLine,
143+
string.Join(Environment.NewLine, newLinesWithoutExcessSpaces));
144+
}
145+
}
146+
147+
private string RemoveExtraComma(string str, int numParams, int indexRemoved)
148+
{
149+
// Example use cases for this method (fields and variables):
150+
// Dim fizz as Boolean, dizz as Double
151+
// Private fizz as Boolean, dizz as Double
152+
// Public fizz as Boolean, _
153+
// dizz as Double
154+
// Private fizz as Boolean _
155+
// , dizz as Double _
156+
// , iizz as Integer
157+
158+
// Before this method is called, the parameter to be removed has
159+
// already been removed. This means 'str' will look like:
160+
// Dim fizz as Boolean,
161+
// Private , dizz as Double
162+
// Public fizz as Boolean, _
163+
//
164+
// Private _
165+
// , dizz as Double _
166+
// , iizz as Integer
167+
168+
// This method is responsible for removing the redundant comma
169+
// and returning a string similar to:
170+
// Dim fizz as Boolean
171+
// Private dizz as Double
172+
// Public fizz as Boolean _
173+
//
174+
// Private _
175+
// dizz as Double _
176+
// , iizz as Integer
177+
178+
var commaToRemove = numParams == indexRemoved ? indexRemoved - 1 : indexRemoved;
179+
180+
return str.Remove(str.NthIndexOf(',', commaToRemove), 1);
71181
}
72182
}
73183
}

RetailCoder.VBE/Inspections/UseMeaningfulNameInspectionResult.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ public override string Description
3030
{
3131
get { return string.Format(InspectionsUI.UseMeaningfulNameInspectionResultFormat, RubberduckUI.ResourceManager.GetString("DeclarationType_" + Target.DeclarationType), Target.IdentifierName); }
3232
}
33+
34+
public override NavigateCodeEventArgs GetNavigationArgs()
35+
{
36+
return new NavigateCodeEventArgs(Target);
37+
}
3338
}
3439

3540
/// <summary>

0 commit comments

Comments
 (0)