Beispiel #1
0
        private async Task <CSharpSyntaxNode> GetInitializerFromNameAndTypeAsync(ITypeSymbol typeSymbol,
                                                                                 VBSyntax.ModifiedIdentifierSyntax name, CSharpSyntaxNode initializer)
        {
            if (!SyntaxTokenExtensions.IsKind(name.Nullable, SyntaxKind.None))
            {
                if (typeSymbol.IsArrayType())
                {
                    initializer = null;
                }
            }

            var rankSpecifiers = await ConvertArrayRankSpecifierSyntaxesAsync(name.ArrayRankSpecifiers, name.ArrayBounds, false);

            if (rankSpecifiers.Count > 0)
            {
                var rankSpecifiersWithSizes = await ConvertArrayRankSpecifierSyntaxesAsync(name.ArrayRankSpecifiers, name.ArrayBounds);

                var arrayTypeSyntax = ((ArrayTypeSyntax)GetTypeSyntax(typeSymbol)).WithRankSpecifiers(rankSpecifiersWithSizes);
                if (rankSpecifiersWithSizes.SelectMany(ars => ars.Sizes).Any(e => !e.IsKind(CSSyntaxKind.OmittedArraySizeExpression)))
                {
                    initializer = SyntaxFactory.ArrayCreationExpression(arrayTypeSyntax);
                }
                else if (initializer is ImplicitArrayCreationExpressionSyntax iaces && iaces.Initializer != null)
                {
                    initializer = SyntaxFactory.ArrayCreationExpression(arrayTypeSyntax, iaces.Initializer);
                }
            }

            return(initializer);
        }
        /// <summary>
        /// Returns true only if expressions static (i.e. doesn't reference the containing instance)
        /// </summary>
        public static bool IsDefinitelyStatic(this SemanticModel semanticModel, VBSyntax.ModifiedIdentifierSyntax vbName, VBSyntax.ExpressionSyntax vbInitValue)
        {
            var arrayBoundExpressions = vbName.ArrayBounds != null?vbName.ArrayBounds.Arguments.Select(a => a.GetExpression()) : Enumerable.Empty <VBSyntax.ExpressionSyntax>();

            var expressions = vbInitValue.Yield().Concat(arrayBoundExpressions).Where(x => x != null).ToArray();

            return(expressions.All(e => semanticModel.IsDefinitelyStatic(e)));
        }
Beispiel #3
0
        private async Task <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;

            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.ShouldAddTypeWideInitToThisPart)
                    {
                        var lhs = SyntaxFactory.IdentifierName(ConvertIdentifier(vbName.Identifier, sourceTriviaMapKind: SourceTriviaMapKind.None));
                        _typeContext.Initializers.AdditionalInstanceInitializers.Add((lhs, CSSyntaxKind.SimpleAssignmentExpression, adjustedInitializerExpr));
                        equalsValueClauseSyntax = null;
                    }
                    else
                    {
                        var returnBlock = SyntaxFactory.Block(SyntaxFactory.ReturnStatement(adjustedInitializerExpr));
                        _typeContext.HoistedState.Hoist <HoistedParameterlessFunction>(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);
        }
Beispiel #4
0
 /// <remarks>
 /// In CS we need to lift non-static initializers to the constructor. But for partial classes these can be in different files.
 /// Rather than re-architect to allow communication between files, we create an initializer function, and call it from the other part, and just hope the name doesn't clash.
 /// </remarks>
 public static string GetInitialValueFunctionName(VBSyntax.ModifiedIdentifierSyntax vbName)
 {
     return("initial" + vbName.Identifier.ValueText.ToPascalCase());
 }
        /// <summary>
        /// This check is entirely to avoid some unnecessary default initializations so the code looks less cluttered and more like the VB did.
        /// The caller should default to outputting an initializer which is always safe for equivalence/correctness.
        /// </summary>
        public static bool IsDefinitelyAssignedBeforeRead(this SemanticModel semanticModel,
                                                          ISymbol locallyDeclaredSymbol, VBSyntax.ModifiedIdentifierSyntax syntaxForSymbol)
        {
            var methodBlockBaseSyntax = syntaxForSymbol.GetAncestor <VBSyntax.MethodBlockBaseSyntax>();
            var methodFlow            = semanticModel.AnalyzeDataFlow(methodBlockBaseSyntax.Statements.First(), methodBlockBaseSyntax.Statements.Last());

            return(DefiniteAssignmentAnalyzer.IsDefinitelyAssignedBeforeRead(locallyDeclaredSymbol, methodFlow));
        }