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); } }
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); }
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); }