Skip to content

Commit c2d3547

Browse files
committed
Fix DeclarationFinder.FindInterface
Previously, this completely ignored the selection passed to it. Now, it only returns interfaces such that the selection is inside an Implements statement for it or contains the Implements statement. If multiple Implements statements are contained, it takes the first it comes across.
1 parent afbdee1 commit c2d3547

File tree

2 files changed

+100
-2
lines changed

2 files changed

+100
-2
lines changed

Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,12 @@ public ClassModuleDeclaration FindInterface(QualifiedSelection selection)
420420
{
421421
return FindAllUserInterfaces()
422422
.FirstOrDefault(declaration => declaration.References
423-
.Any(reference => reference.Context.GetAncestor<VBAParser.ImplementsStmtContext>() != null
424-
&& ReferenceEquals(reference.Declaration, declaration)));
423+
.Where(reference => reference.QualifiedModuleName.Equals(selection.QualifiedName))
424+
.Select(reference => reference.Context.GetAncestor<VBAParser.ImplementsStmtContext>())
425+
.Where(context => context != null)
426+
.Select(context => context.GetSelection())
427+
.Any(contextSelection => contextSelection.Contains(selection.Selection)
428+
|| selection.Selection.Contains(contextSelection)));
425429
}
426430

427431
/// <summary>

RubberduckTests/Refactoring/ImplementInterfaceTests.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,49 @@ End Sub
6060
}
6161
}
6262

63+
[Test]
64+
[Category("Refactorings")]
65+
[Category("Implement Interface")]
66+
public void DoesNotImplementInterface_SelectionNotOnImplementsStatement()
67+
{
68+
//Input
69+
const string inputCode1 =
70+
@"Public Sub Foo()
71+
End Sub";
72+
73+
const string inputCode2 =
74+
@"Implements Class1
75+
76+
";
77+
78+
//Expectation
79+
const string expectedCode =
80+
@"Implements Class1
81+
82+
";
83+
84+
var builder = new MockVbeBuilder();
85+
var project = builder.ProjectBuilder("TestProject1", ProjectProtection.Unprotected)
86+
.AddComponent("Class1", ComponentType.ClassModule, inputCode1)
87+
.AddComponent("Class2", ComponentType.ClassModule, inputCode2)
88+
.Build();
89+
var vbe = builder.AddProject(project).Build();
90+
var component = project.Object.VBComponents[1];
91+
92+
var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe.Object);
93+
using (state)
94+
{
95+
96+
var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), new Selection(2,2));
97+
98+
var refactoring = TestRefactoring(vbe.Object, rewritingManager, state);
99+
refactoring.Refactor(qualifiedSelection);
100+
101+
var actualCode = component.CodeModule.Content();
102+
Assert.AreEqual(expectedCode, actualCode);
103+
}
104+
}
105+
63106
[Test]
64107
[Category("Refactorings")]
65108
[Category("Implement Interface")]
@@ -1018,6 +1061,57 @@ End Property
10181061
}
10191062
}
10201063

1064+
[Test]
1065+
[Category("Refactorings")]
1066+
[Category("Implement Interface")]
1067+
public void ImplementsCorrectInterface_MultipleInterfaces()
1068+
{
1069+
//Input
1070+
const string inputCode1 =
1071+
@"Public Sub Foo()
1072+
End Sub";
1073+
1074+
const string inputCode2 =
1075+
@"Implements Class1
1076+
Implements Class3";
1077+
1078+
const string inputCode3 =
1079+
@"Public Sub Foo()
1080+
End Sub";
1081+
1082+
//Expectation
1083+
const string expectedCode =
1084+
@"Implements Class1
1085+
Implements Class3
1086+
1087+
Private Sub Class1_Foo()
1088+
Err.Raise 5 'TODO implement interface member
1089+
End Sub
1090+
";
1091+
1092+
var builder = new MockVbeBuilder();
1093+
var project = builder.ProjectBuilder("TestProject1", ProjectProtection.Unprotected)
1094+
.AddComponent("Class1", ComponentType.ClassModule, inputCode1)
1095+
.AddComponent("Class2", ComponentType.ClassModule, inputCode2)
1096+
.AddComponent("Class3", ComponentType.ClassModule, inputCode3)
1097+
.Build();
1098+
var vbe = builder.AddProject(project).Build();
1099+
var component = project.Object.VBComponents[1];
1100+
1101+
var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe.Object);
1102+
using (state)
1103+
{
1104+
1105+
var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), new Selection(1,1));
1106+
1107+
var refactoring = TestRefactoring(vbe.Object, rewritingManager, state);
1108+
refactoring.Refactor(qualifiedSelection);
1109+
1110+
var actualCode = component.CodeModule.Content();
1111+
Assert.AreEqual(expectedCode, actualCode);
1112+
}
1113+
}
1114+
10211115
private static IRefactoring TestRefactoring(IVBE vbe, IRewritingManager rewritingManager, RubberduckParserState state, IMessageBox msgBox = null)
10221116
{
10231117
var selectionService = MockedSelectionService(vbe.GetActiveSelection());

0 commit comments

Comments
 (0)