Skip to content

Commit

Permalink
Merge pull request #1068 from icsharpcode/issue/786
Browse files Browse the repository at this point in the history
Cast to dynamic when the accessed member can't be found but the surro…
  • Loading branch information
GrahamTheCoder authored Dec 21, 2023
2 parents 14c7d34 + 60bee52 commit f5e8b38
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 5 deletions.
6 changes: 6 additions & 0 deletions CodeConverter/CSharp/ExpressionNodeVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,12 @@ public override async Task<CSharpSyntaxNode> VisitMemberAccessExpression(VBasic.
}
if (left == null) {
left = await node.Expression.AcceptAsync<ExpressionSyntax>(TriviaConvertingExpressionVisitor);
if (left != null && _semanticModel.GetSymbolInfo(node) is {CandidateReason: CandidateReason.LateBound, CandidateSymbols.Length: 0}
&& _semanticModel.GetSymbolInfo(node.Expression).Symbol is {Kind: var expressionSymbolKind}
&& expressionSymbolKind != SymbolKind.ErrorType
&& _semanticModel.GetOperation(node) is IDynamicMemberReferenceOperation) {
left = SyntaxFactory.ParenthesizedExpression(SyntaxFactory.CastExpression(SyntaxFactory.ParseTypeName("dynamic"), left));
}
}
if (left == null) {
if (IsSubPartOfConditionalAccess(node)) {
Expand Down
37 changes: 37 additions & 0 deletions Tests/CSharp/ExpressionTests/ExpressionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,43 @@ private void TestMethod(string a)
}");
}

[Fact]
public async Task DynamicTestAsync()
{
await TestConversionVisualBasicToCSharpAsync(@"
Public Class C
Public Function IsPointWithinBoundaryBox(ByVal dblLat As Double, dblLon As Double, ByVal boundbox As Object) As Boolean
If boundbox IsNot Nothing Then
Dim boolInLatBounds As Boolean = (dblLat <= boundbox.north) And (dblLat >= boundbox.south) 'Less then highest (northmost) lat, AND more than lowest (southmost) lat
Dim boolInLonBounds As Boolean = (dblLon >= boundbox.west) And (dblLon <= boundbox.east) 'More than lowest (westmost) lat, AND less than highest (eastmost) lon
Return boolInLatBounds And boolInLonBounds
Else
'Throw New Exception(""boundbox is null."")
End If
Return False
End Function
End Class
", @"using Microsoft.VisualBasic.CompilerServices; // Install-Package Microsoft.VisualBasic
public partial class C
{
public bool IsPointWithinBoundaryBox(double dblLat, double dblLon, object boundbox)
{
if (boundbox is not null)
{
bool boolInLatBounds = Conversions.ToBoolean(Operators.AndObject(Operators.ConditionalCompareObjectLessEqual(dblLat, ((dynamic)boundbox).north, false), Operators.ConditionalCompareObjectGreaterEqual(dblLat, ((dynamic)boundbox).south, false))); // Less then highest (northmost) lat, AND more than lowest (southmost) lat
bool boolInLonBounds = Conversions.ToBoolean(Operators.AndObject(Operators.ConditionalCompareObjectGreaterEqual(dblLon, ((dynamic)boundbox).west, false), Operators.ConditionalCompareObjectLessEqual(dblLon, ((dynamic)boundbox).east, false))); // More than lowest (westmost) lat, AND less than highest (eastmost) lon
return boolInLatBounds & boolInLonBounds;
}
else
{
// Throw New Exception(""boundbox is null."")
}
return false;
}
}");
}

[Fact]
public async Task ConversionOfNotUsesParensIfNeededAsync()
{
Expand Down
9 changes: 4 additions & 5 deletions Tests/CSharp/StandaloneStatementTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,12 @@ End If
var cmccIds = new List<int>();
foreach (var scr in _sponsorPayment.SponsorClaimRevisions)
{
foreach (var claim in (IEnumerable)scr.Claims)
foreach (var claim in (IEnumerable)((dynamic)scr).Claims)
{
if (claim.ClaimSummary is ClaimSummary)
if (((dynamic)claim).ClaimSummary is ClaimSummary)
{
{
var withBlock = (ClaimSummary)claim.ClaimSummary;
var withBlock = (ClaimSummary)((dynamic)claim).ClaimSummary;
cmccIds.AddRange(withBlock.UnpaidClaimMealCountCalculationsIds);
}
}
Expand All @@ -151,9 +151,8 @@ End If
2 source compilation errors:
BC30451: '_sponsorPayment' is not declared. It may be inaccessible due to its protection level.
BC30002: Type 'ClaimSummary' is not defined.
3 target compilation errors:
2 target compilation errors:
CS0103: The name '_sponsorPayment' does not exist in the current context
CS1061: 'object' does not contain a definition for 'ClaimSummary' and no accessible extension method 'ClaimSummary' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
CS0246: The type or namespace name 'ClaimSummary' could not be found (are you missing a using directive or an assembly reference?)");
}
}

0 comments on commit f5e8b38

Please sign in to comment.