public TypeConversionKind AnalyzeConversion(VBSyntax.ExpressionSyntax vbNode, bool alwaysExplicit = false, bool isConst = false, ITypeSymbol forceSourceType = null, ITypeSymbol forceTargetType = null)
    {
        var(vbType, vbConvertedType) = GetTypeInfo(vbNode, forceSourceType, forceTargetType);

        if (vbConvertedType is null)
        {
            return(TypeConversionKind.Unknown);
        }

        if (vbType is null)
        {
            return(GetCommonDelegateTypeOrNull(vbNode, vbConvertedType) is {} ? TypeConversionKind.DelegateConstructor : TypeConversionKind.Unknown);
    private ExpressionSyntax AddTypeConversion(VBSyntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, TypeConversionKind conversionKind, bool addParenthesisIfNeeded, ITypeSymbol vbType, ITypeSymbol vbConvertedType)
    {
        switch (conversionKind)
        {
        case TypeConversionKind.FractionalNumberRoundThenCast:
            csNode = vbType.IsNullable() && vbConvertedType.IsNullable()
                    ? _vbNullableExpressionsConverter.InvokeConversionWhenNotNull(csNode, GetMathRoundMemberAccess(), GetTypeSyntax(vbConvertedType))
                    : AddRoundInvocation(vbType.IsNullable() ? csNode.NullableGetValueExpression() : csNode);

            return(AddTypeConversion(vbNode, csNode, TypeConversionKind.NonDestructiveCast, addParenthesisIfNeeded, vbType, vbConvertedType));

        case TypeConversionKind.EnumConversionThenCast:
            vbConvertedType.IsNullable(out var convertedNullableType);
            var underlyingEnumType = ((INamedTypeSymbol)(convertedNullableType ?? vbConvertedType)).EnumUnderlyingType;
            csNode = vbType.IsNullable() && convertedNullableType != null
                    ? _vbNullableExpressionsConverter.InvokeConversionWhenNotNull(csNode, GetConversionsMemberAccess(underlyingEnumType), GetTypeSyntax(vbConvertedType))
                    : AddTypeConversion(vbNode, csNode, TypeConversionKind.Conversion, addParenthesisIfNeeded, vbType, underlyingEnumType);

            return(AddTypeConversion(vbNode, csNode, TypeConversionKind.NonDestructiveCast, addParenthesisIfNeeded, vbType, vbConvertedType));

        case TypeConversionKind.EnumCastThenConversion:
            var enumUnderlyingType = ((INamedTypeSymbol)vbType).EnumUnderlyingType;
            csNode = AddTypeConversion(vbNode, csNode, TypeConversionKind.NonDestructiveCast, addParenthesisIfNeeded, vbType, enumUnderlyingType);
            return(AddTypeConversion(vbNode, csNode, TypeConversionKind.Conversion, addParenthesisIfNeeded, enumUnderlyingType, vbConvertedType));

        case TypeConversionKind.Unknown:
        case TypeConversionKind.Identity:
            return(addParenthesisIfNeeded ? vbNode.ParenthesizeIfPrecedenceCouldChange(csNode) : csNode);

        case TypeConversionKind.DestructiveCast:
        case TypeConversionKind.NonDestructiveCast:
            return(CreateCast(csNode, vbConvertedType));

        case TypeConversionKind.Conversion:
            return(AddExplicitConvertTo(vbNode, csNode, vbType, vbConvertedType));

        case TypeConversionKind.NullableBool:
            return(SyntaxFactory.BinaryExpression(SyntaxKind.EqualsExpression, csNode,
                                                  LiteralConversions.GetLiteralExpression(true)));

        case TypeConversionKind.StringToCharArray:
            var memberAccessExpressionSyntax = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, csNode, SyntaxFactory.IdentifierName(nameof(string.ToCharArray)));
            return(SyntaxFactory.InvocationExpression(memberAccessExpressionSyntax,
                                                      SyntaxFactory.ArgumentList()));

        case TypeConversionKind.DelegateConstructor:
            return(SyntaxFactory.ObjectCreationExpression(GetCommonDelegateTypeOrNull(vbNode, vbConvertedType)).WithArgumentList(new[] { csNode }.CreateCsArgList()));

        default:
            throw new ArgumentOutOfRangeException(nameof(conversionKind), conversionKind, null);
        }
    }
Пример #3
0
    private async Task <CSSyntax.EqualsValueClauseSyntax> ConvertEqualsValueClauseSyntaxAsync(
        VariableDeclaratorSyntax vbDeclarator, VBSyntax.ModifiedIdentifierSyntax vbName,
        VBSyntax.ExpressionSyntax vbInitValue,
        ITypeSymbol declaredSymbolType,
        ISymbol declaredSymbol, CSharpSyntaxNode initializerOrMethodDecl)
    {
        var csTypeSyntax = GetTypeSyntax(declaredSymbolType);

        bool isField       = vbDeclarator.Parent.IsKind(SyntaxKind.FieldDeclaration);
        bool declaredConst = declaredSymbol is IFieldSymbol fieldSymbol && fieldSymbol.IsConst ||
                             declaredSymbol is ILocalSymbol localSymbol && localSymbol.IsConst;

        CSSyntax.EqualsValueClauseSyntax equalsValueClauseSyntax;
        if (await GetInitializerFromNameAndTypeAsync(declaredSymbolType, vbName, initializerOrMethodDecl) is ExpressionSyntax
            adjustedInitializerExpr)
        {
            var convertedInitializer = vbInitValue != null
                ? TypeConversionAnalyzer.AddExplicitConversion(vbInitValue, adjustedInitializerExpr, isConst : declaredConst)
                : adjustedInitializerExpr;

            if (isField && !declaredSymbol.IsStatic && !SemanticModel.IsDefinitelyStatic(vbName, vbInitValue))
            {
                if (!_typeContext.Initializers.HasInstanceConstructorsOutsideThisPart)
                {
                    var lhs = SyntaxFactory.IdentifierName(ConvertIdentifier(vbName.Identifier, sourceTriviaMapKind: SourceTriviaMapKind.None));
                    _typeContext.Initializers.AdditionalInstanceInitializers.Add(new Assignment(lhs, CSSyntaxKind.SimpleAssignmentExpression, adjustedInitializerExpr));
                    equalsValueClauseSyntax = null;
                }
                else
                {
                    var returnBlock = SyntaxFactory.Block(SyntaxFactory.ReturnStatement(adjustedInitializerExpr));
                    _typeContext.PerScopeState.Hoist(new HoistedParameterlessFunction(GetInitialValueFunctionName(vbName), csTypeSyntax, returnBlock));
                    equalsValueClauseSyntax = null;
                }
            }
            else
            {
                equalsValueClauseSyntax = SyntaxFactory.EqualsValueClause(convertedInitializer);
            }
        }
        else if (isField || declaredSymbol != null && SemanticModel.IsDefinitelyAssignedBeforeRead(declaredSymbol, vbName))
        {
            equalsValueClauseSyntax = null;
        }
        else
        {
            // VB initializes variables to their default
            equalsValueClauseSyntax = SyntaxFactory.EqualsValueClause(SyntaxFactory.DefaultExpression(csTypeSyntax));
        }

        return(equalsValueClauseSyntax);
    }
    public ExpressionSyntax AddExplicitConversion(VBSyntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, bool addParenthesisIfNeeded = true, bool defaultToCast = false, bool isConst = false, ITypeSymbol forceSourceType = null, ITypeSymbol forceTargetType = null)
    {
        if (csNode == null)
        {
            return(null);
        }
        var conversionKind = AnalyzeConversion(vbNode, defaultToCast, isConst, forceSourceType, forceTargetType);

        csNode = addParenthesisIfNeeded && conversionKind is TypeConversionKind.DestructiveCast or TypeConversionKind.NonDestructiveCast
            ? vbNode.ParenthesizeIfPrecedenceCouldChange(csNode)
            : csNode;
        return(AddExplicitConversion(vbNode, csNode, conversionKind, addParenthesisIfNeeded, isConst, forceSourceType: forceSourceType, forceTargetType: forceTargetType).Expr);
    }
Пример #5
0
    public bool ShouldPreferExplicitType(VBSyntax.ExpressionSyntax exp,
                                         ITypeSymbol expConvertedType,
                                         out bool isNothingLiteral)
    {
        var op = SemanticModel.GetExpressionOperation(exp);

        exp = op.Syntax as VBSyntax.ExpressionSyntax;
        var vbInitConstantValue = SemanticModel.GetConstantValue(exp);

        isNothingLiteral = vbInitConstantValue.HasValue && vbInitConstantValue.Value == null || exp is VBSyntax.LiteralExpressionSyntax les && les.IsKind(SyntaxKind.NothingLiteralExpression);
        bool shouldPreferExplicitType = expConvertedType != null && (expConvertedType.HasCsKeyword() || !expConvertedType.Equals(op.Type, SymbolEqualityComparer.IncludeNullability));

        return(shouldPreferExplicitType);
    }
    public (ExpressionSyntax Expr, bool IsConst) AddExplicitConversion(VBSyntax.ExpressionSyntax vbNode, ExpressionSyntax csNode, TypeConversionKind conversionKind, bool addParenthesisIfNeeded = false, bool requiresConst = false, ITypeSymbol forceSourceType = null, ITypeSymbol forceTargetType = null)
    {
        var(vbType, vbConvertedType) = GetTypeInfo(vbNode, forceSourceType, forceTargetType);
        bool resultConst = false;

        if (requiresConst)
        {
            var(constExpression, isCorrectType) = _expressionEvaluator.GetConstantOrNull(vbNode, vbConvertedType, conversionKind, csNode);
            if (isCorrectType)
            {
                return(constExpression, true);
            }
            if (constExpression != null)
            {
                csNode      = constExpression ?? csNode;
                resultConst = true;
            }
        }

        var typeConvertedResult = AddTypeConversion(vbNode, csNode, conversionKind, addParenthesisIfNeeded, vbType, vbConvertedType);

        return(typeConvertedResult, resultConst);
    }