Skip to content

Commit 8818fbe

Browse files
committed
Make ExpandDefaultMember able to fix suspicious Let assignments
This is generally deactivated if one of the sides is unbound.
1 parent 8a368f3 commit 8818fbe

File tree

3 files changed

+73
-19
lines changed

3 files changed

+73
-19
lines changed

Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Rubberduck.Inspections.Concrete;
55
using Rubberduck.Parsing.Inspections.Abstract;
66
using Rubberduck.Parsing.Rewriter;
7+
using Rubberduck.Parsing.Symbols;
78
using Rubberduck.Parsing.VBA;
89
using Rubberduck.Parsing.VBA.DeclarationCaching;
910
using Rubberduck.VBEditor;
@@ -20,7 +21,8 @@ public ExpandDefaultMemberQuickFix(IDeclarationFinderProvider declarationFinderP
2021
typeof(IndexedDefaultMemberAccessInspection),
2122
typeof(IndexedRecursiveDefaultMemberAccessInspection),
2223
typeof(ImplicitDefaultMemberAccessInspection),
23-
typeof(ImplicitRecursiveDefaultMemberAccessInspection))
24+
typeof(ImplicitRecursiveDefaultMemberAccessInspection),
25+
typeof(SuspiciousLetAssignmentInspection))
2426
{
2527
_declarationFinderProvider = declarationFinderProvider;
2628
}
@@ -33,6 +35,14 @@ public override void Fix(IInspectionResult result, IRewriteSession rewriteSessio
3335
var lExpressionContext = result.Context;
3436
var selection = result.QualifiedSelection;
3537
InsertDefaultMember(lExpressionContext, selection, finder, rewriter);
38+
39+
if (result.Inspection is SuspiciousLetAssignmentInspection)
40+
{
41+
IdentifierReference rhsReference = result.Properties.RhSReference;
42+
var rhsLExpressionContext = rhsReference.Context;
43+
var rhsSelection = rhsReference.QualifiedSelection;
44+
InsertDefaultMember(rhsLExpressionContext, rhsSelection, finder, rewriter);
45+
}
3646
}
3747

3848
private void InsertDefaultMember(ParserRuleContext lExpressionContext, QualifiedSelection selection, DeclarationFinder finder, IModuleRewriter rewriter)

Rubberduck.Parsing/Symbols/IdentifierReference.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,8 @@ public IdentifierReference(
3333
{
3434
ParentScoping = parentScopingDeclaration;
3535
ParentNonScoping = parentNonScopingDeclaration;
36-
QualifiedModuleName = qualifiedName;
36+
QualifiedSelection = new QualifiedSelection(qualifiedName, selection);
3737
IdentifierName = identifierName;
38-
Selection = selection;
3938
Context = context;
4039
Declaration = declaration;
4140
HasExplicitLetStatement = hasExplicitLetStatement;
@@ -50,12 +49,12 @@ public IdentifierReference(
5049
IsInnerRecursiveDefaultMemberAccess = isInnerRecursiveDefaultMemberAccess;
5150
}
5251

53-
public QualifiedModuleName QualifiedModuleName { get; }
52+
public QualifiedSelection QualifiedSelection { get; }
53+
public QualifiedModuleName QualifiedModuleName => QualifiedSelection.QualifiedName;
54+
public Selection Selection => QualifiedSelection.Selection;
5455

5556
public string IdentifierName { get; }
5657

57-
public Selection Selection { get; }
58-
5958
/// <summary>
6059
/// Gets the scoping <see cref="Declaration"/> that contains this identifier reference,
6160
/// e.g. a module, procedure, function or property.

RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ End Function
8888
("Class2", class2Code, ComponentType.ClassModule),
8989
("Module1", moduleCode, ComponentType.StandardModule));
9090

91-
var actualModuleCode = ApplyQuickFixToFirstInspectionResult(vbe.Object, "Module1", state => new ObjectWhereProcedureIsRequiredInspection(state), CodeKind.AttributesCode);
91+
var actualModuleCode = ApplyQuickFixToFirstInspectionResult(vbe.Object, "Module1", state => new ObjectWhereProcedureIsRequiredInspection(state));
9292
Assert.AreEqual(expectedModuleCode, actualModuleCode);
9393
}
9494

@@ -128,7 +128,7 @@ End Function
128128
("Class2", class2Code, ComponentType.ClassModule),
129129
("Module1", moduleCode, ComponentType.StandardModule));
130130

131-
var actualModuleCode = ApplyQuickFixToFirstInspectionResult(vbe.Object, "Module1", state => new ObjectWhereProcedureIsRequiredInspection(state), CodeKind.AttributesCode);
131+
var actualModuleCode = ApplyQuickFixToFirstInspectionResult(vbe.Object, "Module1", state => new ObjectWhereProcedureIsRequiredInspection(state));
132132
Assert.AreEqual(expectedModuleCode, actualModuleCode);
133133
}
134134

@@ -168,7 +168,7 @@ End Function
168168
("Class2", class2Code, ComponentType.ClassModule),
169169
("Module1", moduleCode, ComponentType.StandardModule));
170170

171-
var actualModuleCode = ApplyQuickFixToFirstInspectionResult(vbe.Object, "Module1", state => new ObjectWhereProcedureIsRequiredInspection(state), CodeKind.AttributesCode);
171+
var actualModuleCode = ApplyQuickFixToFirstInspectionResult(vbe.Object, "Module1", state => new ObjectWhereProcedureIsRequiredInspection(state));
172172
Assert.AreEqual(expectedModuleCode, actualModuleCode);
173173
}
174174

@@ -207,7 +207,7 @@ End Function
207207
("Class2", class2Code, ComponentType.ClassModule),
208208
("Module1", moduleCode, ComponentType.StandardModule));
209209

210-
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new IndexedDefaultMemberAccessInspection(state), CodeKind.AttributesCode);
210+
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new IndexedDefaultMemberAccessInspection(state));
211211
Assert.AreEqual(expectedModuleCode, actualModuleCode);
212212
}
213213

@@ -246,7 +246,7 @@ End Function
246246
("Class2", class2Code, ComponentType.ClassModule),
247247
("Module1", moduleCode, ComponentType.StandardModule));
248248

249-
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new IndexedRecursiveDefaultMemberAccessInspection(state), CodeKind.AttributesCode);
249+
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new IndexedRecursiveDefaultMemberAccessInspection(state));
250250
Assert.AreEqual(expectedModuleCode, actualModuleCode);
251251
}
252252

@@ -285,7 +285,7 @@ End Function
285285
("Class2", class2Code, ComponentType.ClassModule),
286286
("Module1", moduleCode, ComponentType.StandardModule));
287287

288-
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new IndexedDefaultMemberAccessInspection(state), CodeKind.AttributesCode);
288+
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new IndexedDefaultMemberAccessInspection(state));
289289
Assert.AreEqual(expectedModuleCode, actualModuleCode);
290290
}
291291

@@ -324,7 +324,7 @@ End Function
324324
("Class2", class2Code, ComponentType.ClassModule),
325325
("Module1", moduleCode, ComponentType.StandardModule));
326326

327-
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new IndexedRecursiveDefaultMemberAccessInspection(state), CodeKind.AttributesCode);
327+
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new IndexedRecursiveDefaultMemberAccessInspection(state));
328328
Assert.AreEqual(expectedModuleCode, actualModuleCode);
329329
}
330330

@@ -370,7 +370,7 @@ End Function
370370
("Class3", class3Code, ComponentType.ClassModule),
371371
("Module1", moduleCode, ComponentType.StandardModule));
372372

373-
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new IndexedDefaultMemberAccessInspection(state), CodeKind.AttributesCode);
373+
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new IndexedDefaultMemberAccessInspection(state));
374374
Assert.AreEqual(expectedModuleCode, actualModuleCode);
375375
}
376376

@@ -416,7 +416,7 @@ End Function
416416
("Class3", class3Code, ComponentType.ClassModule),
417417
("Module1", moduleCode, ComponentType.StandardModule));
418418

419-
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new IndexedRecursiveDefaultMemberAccessInspection(state), CodeKind.AttributesCode);
419+
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new IndexedRecursiveDefaultMemberAccessInspection(state));
420420
Assert.AreEqual(expectedModuleCode, actualModuleCode);
421421
}
422422

@@ -452,7 +452,7 @@ End Function
452452
("Class1", class1Code, ComponentType.ClassModule),
453453
("Module1", moduleCode, ComponentType.StandardModule));
454454

455-
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new ImplicitDefaultMemberAccessInspection(state), CodeKind.AttributesCode);
455+
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new ImplicitDefaultMemberAccessInspection(state));
456456
Assert.AreEqual(expectedModuleCode, actualModuleCode);
457457
}
458458

@@ -495,7 +495,7 @@ End Function
495495
("Class2", class2Code, ComponentType.ClassModule),
496496
("Module1", moduleCode, ComponentType.StandardModule));
497497

498-
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new ImplicitRecursiveDefaultMemberAccessInspection(state), CodeKind.AttributesCode);
498+
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new ImplicitRecursiveDefaultMemberAccessInspection(state));
499499
Assert.AreEqual(expectedModuleCode, actualModuleCode);
500500
}
501501

@@ -538,7 +538,7 @@ End Function
538538
("Class2", class2Code, ComponentType.ClassModule),
539539
("Module1", moduleCode, ComponentType.StandardModule));
540540

541-
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new ImplicitDefaultMemberAccessInspection(state), CodeKind.AttributesCode);
541+
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new ImplicitDefaultMemberAccessInspection(state));
542542
Assert.AreEqual(expectedModuleCode, actualModuleCode);
543543
}
544544

@@ -595,7 +595,52 @@ End Function
595595
("Class4", class4Code, ComponentType.ClassModule),
596596
("Module1", moduleCode, ComponentType.StandardModule));
597597

598-
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new ImplicitRecursiveDefaultMemberAccessInspection(state), CodeKind.AttributesCode);
598+
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new ImplicitRecursiveDefaultMemberAccessInspection(state));
599+
Assert.AreEqual(expectedModuleCode, actualModuleCode);
600+
}
601+
602+
[Test]
603+
[Category("Inspections")]
604+
public void BothSidesOfAssignmentHaveDefaultMemberAccess_NoExplicitLet_QuickFixWorks()
605+
{
606+
var class1Code = @"
607+
Public Function Foo() As Long
608+
Attribute Foo.VB_UserMemId = 0
609+
End Function
610+
";
611+
612+
var class2Code = @"
613+
Public Property Let Baz(RHS As Long)
614+
Attribute Baz.VB_UserMemId = 0
615+
End Property
616+
";
617+
618+
var moduleCode = $@"
619+
Private Sub Bar()
620+
Dim cls1 As Class1
621+
Dim cls2 As Class2
622+
Set cls1 = New Class1
623+
Set cls2 = New Class2
624+
cls2 = cls1
625+
End Sub
626+
";
627+
628+
var expectedModuleCode = $@"
629+
Private Sub Bar()
630+
Dim cls1 As Class1
631+
Dim cls2 As Class2
632+
Set cls1 = New Class1
633+
Set cls2 = New Class2
634+
cls2.Baz = cls1.Foo
635+
End Sub
636+
";
637+
638+
var vbe = MockVbeBuilder.BuildFromModules(
639+
("Class1", class1Code, ComponentType.ClassModule),
640+
("Class2", class2Code, ComponentType.ClassModule),
641+
("Module1", moduleCode, ComponentType.StandardModule));
642+
643+
var actualModuleCode = ApplyQuickFixToAllInspectionResults(vbe.Object, "Module1", state => new SuspiciousLetAssignmentInspection(state));
599644
Assert.AreEqual(expectedModuleCode, actualModuleCode);
600645
}
601646

0 commit comments

Comments
 (0)