Skip to content

Commit

Permalink
Pay attention to lambda expressions - fixes #930
Browse files Browse the repository at this point in the history
  • Loading branch information
GrahamTheCoder committed Jul 9, 2023
1 parent cd3ac4a commit 8d211e1
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 12 deletions.
2 changes: 2 additions & 0 deletions CodeConverter/CSharp/CommonConversions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace ICSharpCode.CodeConverter.CSharp;

internal class CommonConversions
{
public ITypeSymbol System_Linq_Expressions_Expression_T { get; }
private static readonly Type ExtensionAttributeType = typeof(ExtensionAttribute);
public Document Document { get; }
public SemanticModel SemanticModel { get; }
Expand Down Expand Up @@ -47,6 +48,7 @@ public CommonConversions(Document document, SemanticModel semanticModel,
_typeContext = typeContext;
VisualBasicEqualityComparison = visualBasicEqualityComparison;
WinformsConversions = new WinformsConversions(typeContext);
System_Linq_Expressions_Expression_T = semanticModel.Compilation.GetTypeByMetadataName("System.Linq.Expressions.Expression`1");
}

public record VariablePair(CSSyntax.VariableDeclaratorSyntax CsVar, VBSyntax.ModifiedIdentifierSyntax VbVar);
Expand Down
59 changes: 47 additions & 12 deletions CodeConverter/CSharp/ExpressionNodeVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1231,29 +1231,64 @@ private static bool NextStatementDefinitelyExecutedAfter(VBSyntax.InvocationExpr

public override async Task<CSharpSyntaxNode> VisitSingleLineLambdaExpression(VBasic.Syntax.SingleLineLambdaExpressionSyntax node)
{
IReadOnlyCollection<StatementSyntax> convertedStatements;
if (node.Body is VBasic.Syntax.StatementSyntax statement) {
convertedStatements = await ConvertMethodBodyStatementsAsync(statement, statement.Yield().ToArray());
} else {
var csNode = await node.Body.AcceptAsync<ExpressionSyntax>(TriviaConvertingExpressionVisitor);
convertedStatements = new[] { SyntaxFactory.ExpressionStatement(csNode)};
var originalIsWithinQuery = TriviaConvertingExpressionVisitor.IsWithinQuery;
TriviaConvertingExpressionVisitor.IsWithinQuery = IsLinqExpression(node);
try {
return await ConvertInnerAsync();
} finally {
TriviaConvertingExpressionVisitor.IsWithinQuery = originalIsWithinQuery;
}

async Task<CSharpSyntaxNode> ConvertInnerAsync()
{
IReadOnlyCollection<StatementSyntax> convertedStatements;
if (node.Body is VBasic.Syntax.StatementSyntax statement)
{
convertedStatements = await ConvertMethodBodyStatementsAsync(statement, statement.Yield().ToArray());
}
else
{
var csNode = await node.Body.AcceptAsync<ExpressionSyntax>(TriviaConvertingExpressionVisitor);
convertedStatements = new[] {SyntaxFactory.ExpressionStatement(csNode)};
}

var param = await node.SubOrFunctionHeader.ParameterList.AcceptAsync<ParameterListSyntax>(TriviaConvertingExpressionVisitor);
return await _lambdaConverter.ConvertAsync(node, param, convertedStatements);
}
var param = await node.SubOrFunctionHeader.ParameterList.AcceptAsync<ParameterListSyntax>(TriviaConvertingExpressionVisitor);
return await _lambdaConverter.ConvertAsync(node, param, convertedStatements);
}

public override async Task<CSharpSyntaxNode> VisitMultiLineLambdaExpression(VBasic.Syntax.MultiLineLambdaExpressionSyntax node)
{
var body = await ConvertMethodBodyStatementsAsync(node, node.Statements);
var param = await node.SubOrFunctionHeader.ParameterList.AcceptAsync<ParameterListSyntax>(TriviaConvertingExpressionVisitor);
return await _lambdaConverter.ConvertAsync(node, param, body.ToList());
var originalIsWithinQuery = TriviaConvertingExpressionVisitor.IsWithinQuery;
TriviaConvertingExpressionVisitor.IsWithinQuery = IsLinqExpression(node);
try {
return await ConvertInnerAsync();
} finally {
TriviaConvertingExpressionVisitor.IsWithinQuery = originalIsWithinQuery;
}

async Task<CSharpSyntaxNode> ConvertInnerAsync()
{
var body = await ConvertMethodBodyStatementsAsync(node, node.Statements);
var param = await node.SubOrFunctionHeader.ParameterList.AcceptAsync<ParameterListSyntax>(TriviaConvertingExpressionVisitor);
return await _lambdaConverter.ConvertAsync(node, param, body.ToList());
}
}

private bool IsLinqExpression(VisualBasicSyntaxNode node)
{
var convertedType = _semanticModel.GetTypeInfo(node).ConvertedType;
if (CommonConversions.System_Linq_Expressions_Expression_T.Equals(convertedType?.OriginalDefinition, SymbolEqualityComparer.Default)) {
return true;
}

return false;
}

public async Task<IReadOnlyCollection<StatementSyntax>> ConvertMethodBodyStatementsAsync(VBasic.VisualBasicSyntaxNode node, IReadOnlyCollection<VBSyntax.StatementSyntax> statements, bool isIterator = false, IdentifierNameSyntax csReturnVariable = null)
{

var innerMethodBodyVisitor = await MethodBodyExecutableStatementVisitor.CreateAsync(node, _semanticModel, TriviaConvertingExpressionVisitor, CommonConversions, _withBlockLhs, _extraUsingDirectives, _typeContext, isIterator, csReturnVariable);

return await GetWithConvertedGotosOrNull(statements) ?? await ConvertStatements(statements);

async Task<List<StatementSyntax>> ConvertStatements(IEnumerable<VBSyntax.StatementSyntax> readOnlyCollection)
Expand Down

0 comments on commit 8d211e1

Please sign in to comment.