Skip to content

Commit 10d0680

Browse files
Improve heuristic for unknown indexer vs method, fix missing params
Relates to #595
1 parent 4b6b856 commit 10d0680

2 files changed

Lines changed: 46 additions & 11 deletions

File tree

CodeConverter/CSharp/ExpressionNodeVisitor.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@ private async Task<CSharpSyntaxNode> ConvertInvocationAsync(VBSyntax.InvocationE
838838
}
839839

840840
if (expressionSymbol != null && expressionSymbol.IsKind(SymbolKind.Property) &&
841-
invocationSymbol != null && invocationSymbol.GetParameters().Length == 0) {
841+
invocationSymbol != null && invocationSymbol.GetParameters().Length == 0 && node.ArgumentList.Arguments.Count == 0) {
842842
return convertedExpression; //Parameterless property access
843843
}
844844

@@ -1444,12 +1444,15 @@ private static CSharpSyntaxNode ReplaceRightmostIdentifierText(CSharpSyntaxNode
14441444
}
14451445

14461446
/// <summary>
1447-
/// Chances of having an unknown delegate stored as a field/local seem lower than having an unknown non-delegate type with an indexer stored.
1448-
/// So for a standalone identifier err on the side of assuming it's an indexer.
1447+
/// If there's a single numeric arg, let's assume it's an indexer (probably an array).
1448+
/// Otherwise, err on the side of a method call.
14491449
/// </summary>
1450-
private static bool ProbablyNotAMethodCall(VBasic.Syntax.InvocationExpressionSyntax node, ISymbol symbol, ITypeSymbol symbolReturnType)
1450+
private bool ProbablyNotAMethodCall(VBasic.Syntax.InvocationExpressionSyntax node, ISymbol symbol, ITypeSymbol symbolReturnType)
14511451
{
1452-
return !node.IsParentKind(VBasic.SyntaxKind.CallStatement) && !(symbol is IMethodSymbol) && symbolReturnType.IsErrorType() && node.Expression is VBasic.Syntax.IdentifierNameSyntax && node.ArgumentList?.Arguments.Count() == 1;
1452+
return !node.IsParentKind(VBasic.SyntaxKind.CallStatement) && !(symbol is IMethodSymbol) &&
1453+
symbolReturnType.IsErrorType() && node.Expression is VBasic.Syntax.IdentifierNameSyntax &&
1454+
node.ArgumentList?.Arguments.OnlyOrDefault()?.GetExpression() is {} arg &&
1455+
_semanticModel.GetTypeInfo(arg).Type.IsNumericType();
14531456
}
14541457

14551458
private async Task<ArgumentListSyntax> ConvertArgumentListOrEmptyAsync(SyntaxNode node, VBSyntax.ArgumentListSyntax argumentList)

Tests/CSharp/MissingSemanticModelInfo/ExpressionTests.cs

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ public async Task InvokeIndexerOnPropertyValueAsync()
1212
// Chances of having an unknown delegate stored as a field/property/local seem lower than having an unknown non-delegate
1313
// type with an indexer stored, so for a standalone identifier err on the side of assuming it's an indexer
1414
await TestConversionVisualBasicToCSharpAsync(@"Class TestClass
15-
Public Property SomeProperty As System.Some.UnknownType
15+
Public Property SomeProperty As System.Some.UnknownType
1616
Private Sub TestMethod()
17-
Dim value = SomeProperty(0)
17+
Dim num = 0
18+
Dim value = SomeProperty(num)
19+
value = SomeProperty(0)
1820
End Sub
1921
End Class", @"
2022
internal partial class TestClass
@@ -23,7 +25,9 @@ internal partial class TestClass
2325
2426
private void TestMethod()
2527
{
26-
var value = SomeProperty[0];
28+
int num = 0;
29+
var value = SomeProperty[num];
30+
value = SomeProperty[0];
2731
}
2832
}
2933
2 source compilation errors:
@@ -32,6 +36,33 @@ private void TestMethod()
3236
1 target compilation errors:
3337
CS0234: The type or namespace name 'Some' does not exist in the namespace 'System' (are you missing an assembly reference?)");
3438
}
39+
[Fact]
40+
public async Task InvokeMethodOnPropertyValueAsync()
41+
{
42+
// Chances of having an unknown delegate stored as a field/property/local seem lower than having an unknown non-delegate
43+
// type with an indexer stored, so for a standalone identifier err on the side of assuming it's an indexer
44+
await TestConversionVisualBasicToCSharpAsync(@"Class TestClass
45+
Public Property SomeProperty As System.Some.UnknownType
46+
Private Sub TestMethod()
47+
Dim value = SomeProperty(New Object())
48+
End Sub
49+
End Class", @"
50+
internal partial class TestClass
51+
{
52+
public System.Some.UnknownType SomeProperty { get; set; }
53+
54+
private void TestMethod()
55+
{
56+
var value = SomeProperty(new object());
57+
}
58+
}
59+
2 source compilation errors:
60+
BC30002: Type 'System.Some.UnknownType' is not defined.
61+
BC32016: 'Public Property SomeProperty As System.Some.UnknownType' has no parameters and its return type cannot be indexed.
62+
2 target compilation errors:
63+
CS0234: The type or namespace name 'Some' does not exist in the namespace 'System' (are you missing an assembly reference?)
64+
CS1955: Non-invocable member 'TestClass.SomeProperty' cannot be used like a method.");
65+
}
3566

3667
[Fact]
3768
public async Task InvokeMethodWithUnknownReturnTypeAsync()
@@ -310,14 +341,15 @@ internal partial class TestClass
310341
311342
private void TestMethod()
312343
{
313-
var a = DefaultDate.Blawer(1, 2, 3);
344+
var a = DefaultDate(1, 2, 3).Blawer(1, 2, 3);
314345
}
315346
}
316347
2 source compilation errors:
317348
BC30002: Type 'System.SomeUnknownType' is not defined.
318349
BC32016: 'Private Property DefaultDate As System.SomeUnknownType' has no parameters and its return type cannot be indexed.
319-
1 target compilation errors:
320-
CS0234: The type or namespace name 'SomeUnknownType' does not exist in the namespace 'System' (are you missing an assembly reference?)");
350+
2 target compilation errors:
351+
CS0234: The type or namespace name 'SomeUnknownType' does not exist in the namespace 'System' (are you missing an assembly reference?)
352+
CS1955: Non-invocable member 'TestClass.DefaultDate' cannot be used like a method.");
321353
}
322354

323355
[Fact]

0 commit comments

Comments
 (0)