public async Task <SyntaxList <StatementSyntax> > CreateLocalsAsync(VBasic.VisualBasicSyntaxNode vbNode, IEnumerable <StatementSyntax> csNodes, HashSet <string> generatedNames, SemanticModel semanticModel) { var preDeclarations = new List <StatementSyntax>(); var postAssignments = new List <StatementSyntax>(); var additionalDeclarationInfo = GetDeclarations(); var newNames = additionalDeclarationInfo.ToDictionary(l => l.Id, l => NameGenerator.GetUniqueVariableNameInScope(semanticModel, generatedNames, vbNode, l.Prefix) ); foreach (var additionalLocal in additionalDeclarationInfo) { var decl = CommonConversions.CreateVariableDeclarationAndAssignment(newNames[additionalLocal.Id], additionalLocal.Initializer, additionalLocal.Type); preDeclarations.Add(CS.SyntaxFactory.LocalDeclarationStatement(decl)); } foreach (var additionalAssignment in GetPostAssignments()) { var assign = CS.SyntaxFactory.AssignmentExpression(CS.SyntaxKind.SimpleAssignmentExpression, additionalAssignment.LeftHandSide, additionalAssignment.RightHandSide); postAssignments.Add(CS.SyntaxFactory.ExpressionStatement(assign)); } var statementsWithUpdatedIds = ReplaceNames(preDeclarations.Concat(csNodes).Concat(postAssignments), newNames); return(CS.SyntaxFactory.List(statementsWithUpdatedIds)); }
/// <summary> /// Array copy for multiple array dimensions represented by <paramref name="convertedBounds"/> /// </summary> /// <remarks> /// Exception cases will sometimes silently succeed in the converted code, /// but existing VB code relying on the exception thrown from a multidimensional redim preserve on /// different rank arrays is hopefully rare enough that it's worth saving a few lines of code /// </remarks> private StatementSyntax CreateArrayCopy(VBasic.VisualBasicSyntaxNode originalVbNode, IdentifierNameSyntax sourceArrayExpression, MemberAccessExpressionSyntax sourceLength, ExpressionSyntax targetArrayExpression, ICollection convertedBounds) { var lastSourceLengthArgs = ExpressionSyntaxExtensions.CreateArgList(CommonConversions.Literal(convertedBounds.Count - 1)); var sourceLastRankLength = SyntaxFactory.InvocationExpression( SyntaxFactory.ParseExpression($"{sourceArrayExpression.Identifier}.GetLength"), lastSourceLengthArgs); var targetLastRankLength = SyntaxFactory.InvocationExpression(SyntaxFactory.ParseExpression($"{targetArrayExpression}.GetLength"), lastSourceLengthArgs); var length = SyntaxFactory.InvocationExpression(SyntaxFactory.ParseExpression("Math.Min"), ExpressionSyntaxExtensions.CreateArgList(sourceLastRankLength, targetLastRankLength)); var loopVariableName = GetUniqueVariableNameInScope(originalVbNode, "i"); var loopVariableIdentifier = SyntaxFactory.IdentifierName(loopVariableName); var sourceStartForThisIteration = SyntaxFactory.BinaryExpression(SyntaxKind.MultiplyExpression, loopVariableIdentifier, sourceLastRankLength); var targetStartForThisIteration = SyntaxFactory.BinaryExpression(SyntaxKind.MultiplyExpression, loopVariableIdentifier, targetLastRankLength); var arrayCopy = CreateArrayCopyWithStartingPoints(sourceArrayExpression, sourceStartForThisIteration, targetArrayExpression, targetStartForThisIteration, length); var sourceArrayCount = SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression, SyntaxFactory.BinaryExpression(SyntaxKind.DivideExpression, sourceLength, sourceLastRankLength), CommonConversions.Literal(1)); return(CreateForZeroToValueLoop(loopVariableIdentifier, arrayCopy, sourceArrayCount)); }
private SyntaxList <StatementSyntax> AddLocalVariables(VBasic.VisualBasicSyntaxNode node) { _additionalLocals.PushScope(); IEnumerable <SyntaxNode> csNodes = _wrappedVisitor.Visit(node); var additionalDeclarations = new List <StatementSyntax>(); if (_additionalLocals.Count() > 0) { var newNames = new Dictionary <string, string>(); csNodes = csNodes.Select(csNode => csNode.ReplaceNodes(csNode.GetAnnotatedNodes(AdditionalLocals.Annotation), (an, _) => { var id = (an as IdentifierNameSyntax).Identifier.ValueText; newNames[id] = NameGenerator.GetUniqueVariableNameInScope(_semanticModel, _generatedNames, node, _additionalLocals[id].Prefix); return(SyntaxFactory.IdentifierName(newNames[id])); })).ToList(); foreach (var additionalLocal in _additionalLocals) { var decl = CommonConversions.CreateVariableDeclarationAndAssignment(newNames[additionalLocal.Key], additionalLocal.Value.Initializer); additionalDeclarations.Add(SyntaxFactory.LocalDeclarationStatement(decl)); } } _additionalLocals.PopScope(); return(SyntaxFactory.List(additionalDeclarations.Concat(csNodes))); }
public static bool PrecedenceCouldChange(this VBasic.VisualBasicSyntaxNode node) { bool parentIsBinaryExpression = node is VBSyntax.BinaryExpressionSyntax; bool parentIsLambda = node.Parent is VBSyntax.LambdaExpressionSyntax; bool parentIsNonArgumentExpression = node.Parent is VBSyntax.ExpressionSyntax && !(node.Parent is VBSyntax.ArgumentSyntax); bool parentIsParenthesis = node.Parent is VBSyntax.ParenthesizedExpressionSyntax; bool parentIsMemberAccessExpression = node.Parent is VBSyntax.MemberAccessExpressionSyntax; return(parentIsMemberAccessExpression || parentIsNonArgumentExpression && !parentIsBinaryExpression && !parentIsLambda && !parentIsParenthesis); }
public MethodBodyVisitor(VBasic.VisualBasicSyntaxNode methodNode, SemanticModel semanticModel, VBasic.VisualBasicSyntaxVisitor <CSharpSyntaxNode> nodesVisitor, Stack <string> withBlockTempVariableNames, TriviaConverter triviaConverter) { _methodNode = methodNode; this._semanticModel = semanticModel; this._nodesVisitor = nodesVisitor; this._withBlockTempVariableNames = withBlockTempVariableNames; CommentConvertingVisitor = new CommentConvertingMethodBodyVisitor(this, triviaConverter); CommonConversions = new CommonConversions(semanticModel, _nodesVisitor); }
public override void VisitAssignment(VB.VisualBasicSyntaxNode node, ExecutionState state, MethodBehavior behavior, ISymbol symbol, VariableState variableRightState) { if (node is VBSyntax.AssignmentStatementSyntax || node is VBSyntax.NamedFieldInitializerSyntax) { Analyzer.TagVariables(symbol, variableRightState); } }
public SyntaxList <StatementSyntax> CreateStatements(VBasic.VisualBasicSyntaxNode vbNode, IEnumerable <StatementSyntax> statements, HashSet <string> generatedNames, SemanticModel semanticModel) { var localFunctions = GetParameterlessFunctions(); var newNames = localFunctions.ToDictionary(f => f.Id, f => NameGenerator.GetUniqueVariableNameInScope(semanticModel, generatedNames, vbNode, f.Prefix) ); statements = ReplaceNames(statements, newNames); var functions = localFunctions.Select(f => f.AsLocalFunction(newNames[f.Id])); return(SyntaxFactory.List(functions.Concat(statements))); }
static SyntaxList<VB.VisualBasicSyntaxNode> ConvertSyntaxNodes(this IEnumerable<CS.CSharpSyntaxNode> cs) { SyntaxList<VB.VisualBasicSyntaxNode> retval = new SyntaxList<VB.VisualBasicSyntaxNode>(); foreach (var c in cs) { VB.VisualBasicSyntaxNode b = (VB.VisualBasicSyntaxNode)c.Convert(); if (b != null) { retval = retval.Add(b); } } return retval; }
private async Task <SyntaxList <StatementSyntax> > AddLocalVariablesAsync(VBasic.VisualBasicSyntaxNode node) { _additionalLocals.PushScope(); try { var csNodes = await _wrappedVisitor.Visit(node); var statements = await _additionalLocals.CreateLocalsAsync(node, csNodes, _generatedNames, _semanticModel); return(_additionalLocals.CreateStatements(node, statements, _generatedNames, _semanticModel)); } finally { _additionalLocals.PopScope(); } }
private string GetUniqueVariableNameInScope(VBasic.VisualBasicSyntaxNode node, string variableNameBase) { // Need to check not just the symbols this node has access to, but whether there are any nested blocks which have access to this node and contain a conflicting name var scopeStarts = node.GetAncestorOrThis <VBSyntax.StatementSyntax>().DescendantNodesAndSelf() .OfType <VBSyntax.StatementSyntax>().Select(n => n.SpanStart).ToList(); string uniqueName = NameGenerator.GenerateUniqueName(variableNameBase, string.Empty, n => { var matchingSymbols = scopeStarts.SelectMany(scopeStart => _semanticModel.LookupSymbols(scopeStart, name: n)); return(!_generatedNames.Contains(n) && !matchingSymbols.Any()); }); _generatedNames.Add(uniqueName); return(uniqueName); }
private async Task <SyntaxList <StatementSyntax> > AddLocalVariables(VBasic.VisualBasicSyntaxNode node) { _additionalLocals.PushScope(); IEnumerable <SyntaxNode> csNodes; List <StatementSyntax> additionalDeclarations; try { (csNodes, additionalDeclarations) = await CreateLocals(node); } finally { _additionalLocals.PopScope(); } return(SyntaxFactory.List(additionalDeclarations.Concat(csNodes))); }
/// <summary> /// Cut down version of Microsoft.VisualBasic.CompilerServices.Utils.CopyArray /// </summary> private IfStatementSyntax CreateConditionalArrayCopy(VBasic.VisualBasicSyntaxNode originalVbNode, IdentifierNameSyntax sourceArrayExpression, ExpressionSyntax targetArrayExpression, List <ExpressionSyntax> convertedBounds) { var sourceLength = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, sourceArrayExpression, SyntaxFactory.IdentifierName("Length")); var arrayCopyStatement = convertedBounds.Count == 1 ? CreateArrayCopyWithMinOfLengths(sourceArrayExpression, sourceLength, targetArrayExpression, convertedBounds.Single()) : CreateArrayCopy(originalVbNode, sourceArrayExpression, sourceLength, targetArrayExpression, convertedBounds); var oldTargetNotEqualToNull = SyntaxFactory.BinaryExpression(SyntaxKind.NotEqualsExpression, sourceArrayExpression, SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)); return(SyntaxFactory.IfStatement(oldTargetNotEqualToNull, arrayCopyStatement)); }
public MethodBodyVisitor(VBasic.VisualBasicSyntaxNode methodNode, SemanticModel semanticModel, VBasic.VisualBasicSyntaxVisitor <CSharpSyntaxNode> nodesVisitor, CommonConversions commonConversions, Stack <string> withBlockTempVariableNames, HashSet <string> extraUsingDirectives, AdditionalLocals additionalLocals, TriviaConverter triviaConverter) { _methodNode = methodNode; _semanticModel = semanticModel; _nodesVisitor = nodesVisitor; CommonConversions = commonConversions; _withBlockTempVariableNames = withBlockTempVariableNames; _extraUsingDirectives = extraUsingDirectives; var byRefParameterVisitor = new ByRefParameterVisitor(this, additionalLocals, semanticModel, _generatedNames); CommentConvertingVisitor = new CommentConvertingMethodBodyVisitor(byRefParameterVisitor, triviaConverter); }
public MethodBodyExecutableStatementVisitor(VBasic.VisualBasicSyntaxNode methodNode, SemanticModel semanticModel, CommentConvertingVisitorWrapper <CSharpSyntaxNode> expressionVisitor, CommonConversions commonConversions, Stack <ExpressionSyntax> withBlockLhs, HashSet <string> extraUsingDirectives, AdditionalLocals additionalLocals, MethodsWithHandles methodsWithHandles, TriviaConverter triviaConverter) { _methodNode = methodNode; _semanticModel = semanticModel; _expressionVisitor = expressionVisitor; CommonConversions = commonConversions; _withBlockLhs = withBlockLhs; _extraUsingDirectives = extraUsingDirectives; _methodsWithHandles = methodsWithHandles; var byRefParameterVisitor = new ByRefParameterVisitor(this, additionalLocals, semanticModel, _generatedNames); CommentConvertingVisitor = new CommentConvertingMethodBodyVisitor(byRefParameterVisitor, triviaConverter); }
public static bool PrecedenceCouldChange(Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode node) { bool parentIsSameBinaryKind = node is VBSyntax.BinaryExpressionSyntax && node.Parent is VBSyntax.BinaryExpressionSyntax parent && parent.Kind() == node.Kind(); bool parentIsReturn = node.Parent is VBSyntax.ReturnStatementSyntax; bool parentIsLambda = node.Parent is VBSyntax.LambdaExpressionSyntax; bool parentIsNonArgumentExpression = node.Parent is VBSyntax.ExpressionSyntax && !(node.Parent is VBSyntax.ArgumentSyntax); bool parentIsParenthesis = node.Parent is VBSyntax.ParenthesizedExpressionSyntax; // Could be a full C# precedence table - this is just a common case bool parentIsAndOr = node.Parent.IsKind(Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.AndAlsoExpression, Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.OrElseExpression); bool nodeIsRelationalOrEqual = node.IsKind(Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.EqualsExpression, Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.NotEqualsExpression, Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.LessThanExpression, Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.LessThanOrEqualExpression, Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.GreaterThanExpression, Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.GreaterThanOrEqualExpression); bool csharpPrecedenceSame = parentIsAndOr && nodeIsRelationalOrEqual; return(parentIsNonArgumentExpression && !parentIsSameBinaryKind && !parentIsReturn && !parentIsLambda && !parentIsParenthesis && !csharpPrecedenceSame); }
public override SyntaxList <StatementSyntax> VisitExitStatement(VBSyntax.ExitStatementSyntax node) { switch (VBasic.VisualBasicExtensions.Kind(node.BlockKeyword)) { case VBasic.SyntaxKind.SubKeyword: return(SingleStatement(SyntaxFactory.ReturnStatement())); case VBasic.SyntaxKind.FunctionKeyword: VBasic.VisualBasicSyntaxNode typeContainer = (VBasic.VisualBasicSyntaxNode)node.Ancestors().OfType <VBSyntax.LambdaExpressionSyntax>().FirstOrDefault() ?? node.Ancestors().OfType <VBSyntax.MethodBlockSyntax>().FirstOrDefault(); var info = typeContainer.TypeSwitch( (VBSyntax.LambdaExpressionSyntax e) => _semanticModel.GetTypeInfo(e).Type.GetReturnType(), (VBSyntax.MethodBlockSyntax e) => { var type = (TypeSyntax)e.SubOrFunctionStatement.AsClause?.Type.Accept(_nodesVisitor) ?? SyntaxFactory.ParseTypeName("object"); return(_semanticModel.GetSymbolInfo(type).Symbol?.GetReturnType()); } ); ExpressionSyntax expr; if (HasReturnVariable) { expr = ReturnVariable; } else if (info == null) { expr = null; } else if (info.IsReferenceType) { expr = SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression); } else if (info.CanBeReferencedByName) { expr = SyntaxFactory.DefaultExpression(SyntaxFactory.ParseTypeName(info.ToMinimalCSharpDisplayString(_semanticModel, node.SpanStart))); } else { throw new NotSupportedException(); } return(SingleStatement(SyntaxFactory.ReturnStatement(expr))); default: return(SingleStatement(SyntaxFactory.BreakStatement())); } }
private async Task <SyntaxList <StatementSyntax> > AddLocalVariablesAsync(VBasic.VisualBasicSyntaxNode node, VBasic.SyntaxKind exitableType = default, bool isBreakableInCs = false) { _additionalLocals.PushScope(exitableType, isBreakableInCs); try { var convertedStatements = await _wrappedVisitor.Visit(node); var withLocals = await _additionalLocals.CreateLocalsAsync(node, convertedStatements, _generatedNames, _semanticModel); var allStatements = _additionalLocals.CreateStatements(node, withLocals, _generatedNames, _semanticModel); if (isBreakableInCs && exitableType == VBasic.SyntaxKind.TryKeyword) { var doOnce = SyntaxFactory.DoStatement(SyntaxFactory.Block(allStatements), CommonConversions.Literal(false)); allStatements = SyntaxFactory.SingletonList <StatementSyntax>(doOnce); } return(allStatements); } finally { _additionalLocals.PopScope(); } }
private static T LastOrDefaultDescendant <T>(this VBasic.VisualBasicSyntaxNode syntaxNode) { return(syntaxNode.DescendantNodes().OfType <T>().LastOrDefault()); }
public static CSSyntax.ExpressionSyntax ParenthesizeIfPrecedenceCouldChange(this VBasic.VisualBasicSyntaxNode node, CSSyntax.ExpressionSyntax expression) { return(PrecedenceCouldChange(node) ? SyntaxFactory.ParenthesizedExpression(expression) : expression); }
public static ExpressionSyntax ParenthesizeIfPrecedenceCouldChange(Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode node, ExpressionSyntax expression) { return(PrecedenceCouldChange(node) ? SyntaxFactory.ParenthesizedExpression(expression) : expression); }
private static List <int> GetScopeStarts(VBasic.VisualBasicSyntaxNode node) { return(node.GetAncestorOrThis <VBSyntax.StatementSyntax>().DescendantNodesAndSelf() .OfType <VBSyntax.StatementSyntax>().Select(n => n.SpanStart).ToList()); }
public static string GetUniqueVariableNameInScope(SemanticModel semanticModel, HashSet <string> generatedNames, VBasic.VisualBasicSyntaxNode node, string variableNameBase) { // Need to check not just the symbols this node has access to, but whether there are any nested blocks which have access to this node and contain a conflicting name var scopeStarts = GetScopeStarts(node); return(GenerateUniqueVariableNameInScope(semanticModel, generatedNames, variableNameBase, scopeStarts)); }
private string GetUniqueVariableNameInScope(VBasic.VisualBasicSyntaxNode node, string variableNameBase) { return(NameGenerator.GetUniqueVariableNameInScope(_semanticModel, _generatedNames, node, variableNameBase)); }
public static CSharpSyntaxNode Convert(VBasic.VisualBasicSyntaxNode input, SemanticModel semanticModel, Document targetDocument) { return(input.Accept(new NodesVisitor(semanticModel, targetDocument))); }