public ExpressionSyntax AddExplicitConvertTo(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, ITypeSymbol type) { var displayType = type.ToMinimalDisplayString(_semanticModel, vbNode.SpanStart); if (csNode is InvocationExpressionSyntax invoke && invoke.Expression is MemberAccessExpressionSyntax expr && expr.Expression is IdentifierNameSyntax name && name.Identifier.ValueText == "Conversions" && expr.Name.Identifier.ValueText == $"To{displayType}") { return(csNode); } var method = typeof(Microsoft.VisualBasic.CompilerServices.Conversions).GetMethod($"To{displayType}"); if (method == null) { throw new NotImplementedException($"Unimplemented conversion for {displayType}"); } // Need to use Conversions rather than Convert to match what VB does, eg. True -> -1 _extraUsingDirectives.Add("Microsoft.VisualBasic.CompilerServices"); var memberAccess = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName("Conversions"), SyntaxFactory.IdentifierName($"To{displayType}")); var arguments = SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(csNode))); return(SyntaxFactory.InvocationExpression(memberAccess, arguments)); }
private ExpressionSyntax AddExplicitConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, TypeConversionKind conversionKind, bool addParenthesisIfNeeded) { var vbConvertedType = _semanticModel.GetTypeInfo(vbNode).ConvertedType; switch (conversionKind) { case TypeConversionKind.Unknown: case TypeConversionKind.Identity: return(addParenthesisIfNeeded ? VbSyntaxNodeExtensions.ParenthesizeIfPrecedenceCouldChange(vbNode, csNode) : csNode); case TypeConversionKind.DestructiveCast: case TypeConversionKind.NonDestructiveCast: var typeName = (TypeSyntax)_csSyntaxGenerator.TypeExpression(vbConvertedType); if (csNode is CastExpressionSyntax cast && cast.Type.IsEquivalentTo(typeName)) { return(csNode); } return(ValidSyntaxFactory.CastExpression(typeName, csNode)); case TypeConversionKind.Conversion: return(AddExplicitConvertTo(vbNode, csNode, vbConvertedType)); default: throw new ArgumentOutOfRangeException(); } }
public ExpressionSyntax AddExplicitConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, bool addParenthesisIfNeeded = false, bool alwaysExplicit = false, bool implicitCastFromIntToEnum = false) { var conversionKind = AnalyzeConversion(vbNode, csNode, alwaysExplicit, implicitCastFromIntToEnum, out var vbConvertedType); csNode = addParenthesisIfNeeded && conversionKind == TypeConversionKind.Implicit ? VbSyntaxNodeExtensions.ParenthesizeIfPrecedenceCouldChange(vbNode, csNode) : csNode; return(AddExplicitConversion(vbNode, csNode, vbConvertedType, conversionKind, addParenthesisIfNeeded)); }
private VB.Syntax.ForStatementSyntax CreateForStatement(CS.Syntax.ForStatementSyntax node) { string variableName = node.Declaration.Variables[0].Identifier.ValueText; VB.Syntax.ForStepClauseSyntax stepClause = CreateForStepClause(node); VB.Syntax.ExpressionSyntax toValue = CreateForToValue(node); return(VB.SyntaxFactory.ForStatement( controlVariable: VB.SyntaxFactory.IdentifierName(variableName), fromValue: nodeVisitor.VisitExpression(node.Declaration.Variables[0].Initializer.Value), toValue: toValue, stepClause: stepClause)); }
private void VisitMethodsEx(SyntaxNodeAnalysisContext ctx) { var node = ctx.Node as Microsoft.CodeAnalysis.VisualBasic.Syntax.MethodBlockSyntax; if (node == null) { //Not the expected node type return; } //Iterating over the list of annotation for a given method foreach (var attribute in node.BlockStatement.AttributeLists) { if (attribute.Attributes.Count == 0) { continue; //Bound check .. Unlikely to happens } var att = attribute.Attributes[0]; //Extract the annotation identifier var identifier = att.Name as Microsoft.CodeAnalysis.VisualBasic.Syntax.IdentifierNameSyntax; if (identifier == null) { continue; } if (identifier.Identifier.Text == "ValidateInput") { var hasArgumentFalse = false; Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax expression = null; foreach (var arg in att.ArgumentList.Arguments) { var literal = arg.GetExpression() as Microsoft.CodeAnalysis.VisualBasic.Syntax.LiteralExpressionSyntax; if (literal.Token.ValueText == "false") { hasArgumentFalse = true; expression = arg.GetExpression(); } } if (hasArgumentFalse && expression != null) { ctx.ReportDiagnostic(Diagnostic.Create(Rule, expression.GetLocation())); } } } }
private ExpressionSyntax AddExplicitConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, ITypeSymbol vbConvertedType, TypeConversionKind conversionKind, bool addParenthesisIfNeeded) { switch (conversionKind) { case TypeConversionKind.Unknown: case TypeConversionKind.Identity: return(addParenthesisIfNeeded ? VbSyntaxNodeExtensions.ParenthesizeIfPrecedenceCouldChange(vbNode, csNode) : csNode); case TypeConversionKind.Implicit: return(ValidSyntaxFactory.CastExpression(_semanticModel.GetCsTypeSyntax(vbConvertedType, vbNode), csNode)); case TypeConversionKind.Explicit: return(AddExplicitConvertTo(vbNode, csNode, vbConvertedType)); default: throw new ArgumentOutOfRangeException(); } }
private VB.Syntax.ExpressionSyntax CreateForToValue(CS.Syntax.ForStatementSyntax node) { VB.Syntax.ExpressionSyntax expression = nodeVisitor.VisitExpression(((CS.Syntax.BinaryExpressionSyntax)node.Condition).Right); if (!node.Condition.IsKind(CS.SyntaxKind.LessThanOrEqualExpression) && !node.Condition.IsKind(CS.SyntaxKind.GreaterThanOrEqualExpression)) { if (node.Condition.IsKind(CS.SyntaxKind.LessThanExpression)) { return(VB.SyntaxFactory.SubtractExpression( expression, CreateOneExpression())); } if (node.Condition.IsKind(CS.SyntaxKind.GreaterThanExpression)) { return(VB.SyntaxFactory.AddExpression( expression, CreateOneExpression())); } } return(expression); }
public static IOperation GetExpressionOperation(this SemanticModel semanticModel, Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax expressionSyntax) { var op = semanticModel.GetOperation(expressionSyntax); while (true) { switch (op) { case IArgumentOperation argumentOperation: op = argumentOperation.Value; continue; case IConversionOperation conversionOperation: op = conversionOperation.Operand; continue; case IParenthesizedOperation parenthesizedOperation: op = parenthesizedOperation.Operand; continue; default: return(op); } } }
public void VisitInvocationAndCreation(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax node, Microsoft.CodeAnalysis.VisualBasic.Syntax.ArgumentListSyntax argList, ExecutionState state) { }
private TypeConversionKind AnalyzeConversion(Microsoft.CodeAnalysis.VisualBasic.Syntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, bool alwaysExplicit, bool implicitCastFromIntToEnum, out ITypeSymbol vbConvertedType) { var typeInfo = _semanticModel.GetTypeInfo(vbNode); var vbType = typeInfo.Type; vbConvertedType = typeInfo.ConvertedType; if (vbType is null || vbConvertedType is null) { return(TypeConversionKind.Unknown); } if (vbType.IsEnumType()) { if (vbConvertedType.IsNumericType()) { return(TypeConversionKind.Implicit); } else if (vbType.Equals(vbConvertedType) || (vbConvertedType.IsNullable() && vbType.Equals(vbConvertedType.GetNullableUnderlyingType())) || vbConvertedType.SpecialType == SpecialType.System_Object) { return(TypeConversionKind.Identity); } else { return(TypeConversionKind.Explicit); } } var vbCompilation = _semanticModel.Compilation as Microsoft.CodeAnalysis.VisualBasic.VisualBasicCompilation; var vbConversion = vbCompilation.ClassifyConversion(vbType, vbConvertedType); var csType = _csCompilation.GetTypeByMetadataName(vbType.GetFullMetadataName()); var csConvertedType = _csCompilation.GetTypeByMetadataName(vbConvertedType.GetFullMetadataName()); if (csType == null || csConvertedType == null) { if (alwaysExplicit && vbType != vbConvertedType) { return(TypeConversionKind.Implicit); } return(TypeConversionKind.Unknown); } var csConversion = _csCompilation.ClassifyConversion(csType, csConvertedType); bool isConvertToString = vbConversion.IsString && vbConvertedType.SpecialType == SpecialType.System_String; bool isArithmetic = vbNode.IsKind(Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.AddExpression, Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.SubtractExpression, Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.MultiplyExpression, Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.DivideExpression, Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.IntegerDivideExpression); if (!csConversion.Exists || csConversion.IsUnboxing) { if (isConvertToString || vbConversion.IsNarrowing) { return(TypeConversionKind.Explicit); } } else if (vbConversion.IsWidening && vbConversion.IsNumeric && csConversion.IsImplicit && csConversion.IsNumeric) { // Safe overapproximation: A cast is really only needed to help resolve the overload for the operator/method used. // e.g. When VB "&" changes to C# "+", there are lots more overloads available that implicit casts could match. // e.g. sbyte * ulong uses the decimal * operator in VB. In C# it's ambiguous - see ExpressionTests.vb "TestMul". var typeName = _semanticModel.GetCsTypeSyntax(vbConvertedType, vbNode); if (csNode is CastExpressionSyntax cast && cast.Type.IsEquivalentTo(typeName)) { return(TypeConversionKind.Identity); } return(TypeConversionKind.Implicit); } else if (csConversion.IsExplicit && csConversion.IsEnumeration) { return(implicitCastFromIntToEnum ? TypeConversionKind.Identity : TypeConversionKind.Implicit); } else if (csConversion.IsExplicit && vbConversion.IsNumeric && vbType.TypeKind != TypeKind.Enum) { return(TypeConversionKind.Explicit); } else if (isArithmetic) { var arithmeticConversion = vbCompilation.ClassifyConversion(vbConvertedType, vbCompilation.GetTypeByMetadataName("System.Int32")); if (arithmeticConversion.IsWidening && !arithmeticConversion.IsIdentity) { return(TypeConversionKind.Explicit); } } else if (alwaysExplicit && vbType != vbConvertedType) { return(TypeConversionKind.Implicit); } return(TypeConversionKind.Identity); }