Skip to content

Commit 5a733e9

Browse files
committed
Store failed procedure coercions for non-parameterized call statements
1 parent 7415d64 commit 5a733e9

File tree

2 files changed

+293
-5
lines changed

2 files changed

+293
-5
lines changed

Rubberduck.Parsing/Binding/Bindings/ProcedureCoercionDefaultBinding.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,9 @@ private static IBoundExpression Resolve(IBoundExpression wrappedExpression, Pars
6969
return ResolveViaDefaultMember(wrappedExpression, asTypeName, asTypeDeclaration, expression);
7070
}
7171

72-
private static IBoundExpression CreateFailedExpression(IBoundExpression lExpression, ParserRuleContext context)
72+
private static IBoundExpression CreateFailedExpression(IBoundExpression wrappedExpression, ParserRuleContext context)
7373
{
74-
var failedExpr = new ResolutionFailedExpression(context, true);
75-
failedExpr.AddSuccessfullyResolvedExpression(lExpression);
76-
return failedExpr;
74+
return new ProcedureCoercionExpression(wrappedExpression.ReferencedDeclaration, ExpressionClassification.ResolutionFailed, context, wrappedExpression);
7775
}
7876

7977
private static IBoundExpression ResolveViaDefaultMember(IBoundExpression wrappedExpression, string asTypeName, Declaration asTypeDeclaration, ParserRuleContext expression)
@@ -82,7 +80,7 @@ private static IBoundExpression ResolveViaDefaultMember(IBoundExpression wrapped
8280
|| Tokens.Object.Equals(asTypeName, StringComparison.InvariantCultureIgnoreCase))
8381
{
8482
// We cannot know the the default member in this case, so return an unbound member call.
85-
return new ProcedureCoercionExpression(null, ExpressionClassification.Unbound, expression, wrappedExpression);
83+
return new ProcedureCoercionExpression(wrappedExpression.ReferencedDeclaration, ExpressionClassification.Unbound, expression, wrappedExpression);
8684
}
8785

8886
var defaultMember = (asTypeDeclaration as ClassModuleDeclaration)?.DefaultMember;

RubberduckTests/Grammar/ResolverTests.cs

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5178,6 +5178,296 @@ End Sub
51785178
}
51795179
}
51805180

5181+
[Test]
5182+
[Category("Grammar")]
5183+
[Category("Resolver")]
5184+
[Ignore("Temporarily ignored until a way is found to save the failed procedure coercions for parameterized calls.")]
5185+
public void FailedParameterizedProcedureCoercionReferenceOnEntireContext()
5186+
{
5187+
var class1Code = @"
5188+
Public Sub Foo(arg As Long)
5189+
End Sub
5190+
";
5191+
5192+
var class2Code = @"
5193+
Public Function Baz() As Class1
5194+
Set Baz = New Class1
5195+
End Function
5196+
";
5197+
5198+
var moduleCode = $@"
5199+
Private Function Foo() As Variant
5200+
Dim cls As new Class2
5201+
cls.Baz 42
5202+
End Function
5203+
5204+
Private Sub Bar(arg As Long)
5205+
End Sub
5206+
5207+
Private Sub Baz(arg As Variant)
5208+
End Sub
5209+
";
5210+
5211+
var vbe = MockVbeBuilder.BuildFromModules(
5212+
("Class1", class1Code, ComponentType.ClassModule),
5213+
("Class2", class2Code, ComponentType.ClassModule),
5214+
("Module1", moduleCode, ComponentType.StandardModule));
5215+
5216+
using (var state = Resolve(vbe.Object))
5217+
{
5218+
var module = state.DeclarationFinder.AllModules.First(qmn => qmn.ComponentName == "Module1");
5219+
var failedProcedureCoercion = state.DeclarationFinder
5220+
.FailedProcedureCoercions(module)
5221+
.Single();
5222+
5223+
var expectedSelection = new Selection(4, 5, 4, 12);
5224+
var actualSelection = failedProcedureCoercion.Selection;
5225+
5226+
Assert.AreEqual(expectedSelection, actualSelection);
5227+
}
5228+
}
5229+
5230+
[Test]
5231+
[Category("Grammar")]
5232+
[Category("Resolver")]
5233+
public void FailedNonParameterizedProcedureCoercionReferenceOnEntireContext()
5234+
{
5235+
var class1Code = @"
5236+
Public Sub Foo()
5237+
End Sub
5238+
";
5239+
5240+
var class2Code = @"
5241+
Public Function Baz() As Class1
5242+
Set Baz = New Class1
5243+
End Function
5244+
";
5245+
5246+
var moduleCode = $@"
5247+
Private Function Foo() As Variant
5248+
Dim cls As new Class2
5249+
cls
5250+
End Function
5251+
5252+
Private Sub Bar(arg As Long)
5253+
End Sub
5254+
5255+
Private Sub Baz(arg As Variant)
5256+
End Sub
5257+
";
5258+
5259+
var vbe = MockVbeBuilder.BuildFromModules(
5260+
("Class1", class1Code, ComponentType.ClassModule),
5261+
("Class2", class2Code, ComponentType.ClassModule),
5262+
("Module1", moduleCode, ComponentType.StandardModule));
5263+
5264+
using (var state = Resolve(vbe.Object))
5265+
{
5266+
var module = state.DeclarationFinder.AllModules.First(qmn => qmn.ComponentName == "Module1");
5267+
var failedProcedureCoercion = state.DeclarationFinder
5268+
.FailedProcedureCoercions(module)
5269+
.Single();
5270+
5271+
var expectedSelection = new Selection(4, 5, 4, 8);
5272+
var actualSelection = failedProcedureCoercion.Selection;
5273+
5274+
Assert.AreEqual(expectedSelection, actualSelection);
5275+
}
5276+
}
5277+
5278+
[Test]
5279+
[Category("Grammar")]
5280+
[Category("Resolver")]
5281+
[Ignore("Temporarily ignored until a way is found to save the failed procedure coercions for parameterized calls.")]
5282+
public void FailedParameterizedProcedureCoercionReferenceOnEntireContext_ExplicitCall()
5283+
{
5284+
var class1Code = @"
5285+
Public Sub Foo(arg As Long)
5286+
End Sub
5287+
";
5288+
5289+
var class2Code = @"
5290+
Public Function Baz() As Class1
5291+
Set Baz = New Class1
5292+
End Function
5293+
";
5294+
5295+
var moduleCode = $@"
5296+
Private Function Foo() As Variant
5297+
Dim cls As new Class2
5298+
Call cls.Baz(42)
5299+
End Function
5300+
5301+
Private Sub Bar(arg As Long)
5302+
End Sub
5303+
5304+
Private Sub Baz(arg As Variant)
5305+
End Sub
5306+
";
5307+
5308+
var vbe = MockVbeBuilder.BuildFromModules(
5309+
("Class1", class1Code, ComponentType.ClassModule),
5310+
("Class2", class2Code, ComponentType.ClassModule),
5311+
("Module1", moduleCode, ComponentType.StandardModule));
5312+
5313+
using (var state = Resolve(vbe.Object))
5314+
{
5315+
var module = state.DeclarationFinder.AllModules.First(qmn => qmn.ComponentName == "Module1");
5316+
var failedProcedureCoercion = state.DeclarationFinder
5317+
.FailedProcedureCoercions(module)
5318+
.Single();
5319+
5320+
var expectedSelection = new Selection(4, 10, 4, 17);
5321+
var actualSelection = failedProcedureCoercion.Selection;
5322+
5323+
Assert.AreEqual(expectedSelection, actualSelection);
5324+
}
5325+
}
5326+
5327+
[Test]
5328+
[Category("Grammar")]
5329+
[Category("Resolver")]
5330+
public void FailedNonParameterizedProcedureCoercionReferenceOnEntireContext_ExplicitCall()
5331+
{
5332+
var class1Code = @"
5333+
Public Sub Foo()
5334+
End Sub
5335+
";
5336+
5337+
var class2Code = @"
5338+
Public Function Baz() As Class1
5339+
Set Baz = New Class1
5340+
End Function
5341+
";
5342+
5343+
var moduleCode = $@"
5344+
Private Function Foo() As Variant
5345+
Dim cls As new Class2
5346+
Call cls
5347+
End Function
5348+
5349+
Private Sub Bar(arg As Long)
5350+
End Sub
5351+
5352+
Private Sub Baz(arg As Variant)
5353+
End Sub
5354+
";
5355+
5356+
var vbe = MockVbeBuilder.BuildFromModules(
5357+
("Class1", class1Code, ComponentType.ClassModule),
5358+
("Class2", class2Code, ComponentType.ClassModule),
5359+
("Module1", moduleCode, ComponentType.StandardModule));
5360+
5361+
using (var state = Resolve(vbe.Object))
5362+
{
5363+
var module = state.DeclarationFinder.AllModules.First(qmn => qmn.ComponentName == "Module1");
5364+
var failedProcedureCoercion = state.DeclarationFinder
5365+
.FailedProcedureCoercions(module)
5366+
.Single();
5367+
5368+
var expectedSelection = new Selection(4, 10, 4, 13);
5369+
var actualSelection = failedProcedureCoercion.Selection;
5370+
5371+
Assert.AreEqual(expectedSelection, actualSelection);
5372+
}
5373+
}
5374+
5375+
[Test]
5376+
[Category("Grammar")]
5377+
[Category("Resolver")]
5378+
public void FailedNonParameterizedProcedureCoercionOnArrayAccessReferenceOnEntireContext()
5379+
{
5380+
var class1Code = @"
5381+
Public Sub Foo()
5382+
End Sub
5383+
";
5384+
5385+
var class2Code = @"
5386+
Public Function Baz() As Class1()
5387+
Set Baz = New Class1
5388+
End Function
5389+
";
5390+
5391+
var moduleCode = $@"
5392+
Private Function Foo() As Variant
5393+
Dim cls As new Class2
5394+
cls.Baz(42)
5395+
End Function
5396+
5397+
Private Sub Bar(arg As Long)
5398+
End Sub
5399+
5400+
Private Sub Baz(arg As Variant)
5401+
End Sub
5402+
";
5403+
5404+
var vbe = MockVbeBuilder.BuildFromModules(
5405+
("Class1", class1Code, ComponentType.ClassModule),
5406+
("Class2", class2Code, ComponentType.ClassModule),
5407+
("Module1", moduleCode, ComponentType.StandardModule));
5408+
5409+
using (var state = Resolve(vbe.Object))
5410+
{
5411+
var module = state.DeclarationFinder.AllModules.First(qmn => qmn.ComponentName == "Module1");
5412+
var failedProcedureCoercion = state.DeclarationFinder
5413+
.FailedProcedureCoercions(module)
5414+
.Single();
5415+
5416+
var expectedSelection = new Selection(4, 5, 4, 16);
5417+
var actualSelection = failedProcedureCoercion.Selection;
5418+
5419+
Assert.AreEqual(expectedSelection, actualSelection);
5420+
}
5421+
}
5422+
5423+
[Test]
5424+
[Category("Grammar")]
5425+
[Category("Resolver")]
5426+
public void FailedNonParameterizedProcedureCoercionOnArrayAccessReferenceOnEntireContext_ExplicitCall()
5427+
{
5428+
var class1Code = @"
5429+
Public Sub Foo()
5430+
End Sub
5431+
";
5432+
5433+
var class2Code = @"
5434+
Public Function Baz() As Class1()
5435+
Set Baz = New Class1
5436+
End Function
5437+
";
5438+
5439+
var moduleCode = $@"
5440+
Private Function Foo() As Variant
5441+
Dim cls As new Class2
5442+
Call cls.Baz(42)
5443+
End Function
5444+
5445+
Private Sub Bar(arg As Long)
5446+
End Sub
5447+
5448+
Private Sub Baz(arg As Variant)
5449+
End Sub
5450+
";
5451+
5452+
var vbe = MockVbeBuilder.BuildFromModules(
5453+
("Class1", class1Code, ComponentType.ClassModule),
5454+
("Class2", class2Code, ComponentType.ClassModule),
5455+
("Module1", moduleCode, ComponentType.StandardModule));
5456+
5457+
using (var state = Resolve(vbe.Object))
5458+
{
5459+
var module = state.DeclarationFinder.AllModules.First(qmn => qmn.ComponentName == "Module1");
5460+
var failedProcedureCoercion = state.DeclarationFinder
5461+
.FailedProcedureCoercions(module)
5462+
.Single();
5463+
5464+
var expectedSelection = new Selection(4, 10, 4, 21);
5465+
var actualSelection = failedProcedureCoercion.Selection;
5466+
5467+
Assert.AreEqual(expectedSelection, actualSelection);
5468+
}
5469+
}
5470+
51815471
[Test]
51825472
[Category("Grammar")]
51835473
[Category("Resolver")]

0 commit comments

Comments
 (0)