예제 #1
0
        private (TypeSyntax, ExpressionSyntax) AdjustFromName(TypeSyntax rawType,
                                                              ModifiedIdentifierSyntax name, ExpressionSyntax initializer)
        {
            var type = rawType;

            if (!SyntaxTokenExtensions.IsKind(name.Nullable, SyntaxKind.None))
            {
                if (type is ArrayTypeSyntax)
                {
                    type = ((ArrayTypeSyntax)type).WithElementType(
                        SyntaxFactory.NullableType(((ArrayTypeSyntax)type).ElementType));
                    initializer = null;
                }
                else
                {
                    type = SyntaxFactory.NullableType(type);
                }
            }

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

            if (rankSpecifiers.Count > 0)
            {
                var rankSpecifiersWithSizes = ConvertArrayRankSpecifierSyntaxes(name.ArrayRankSpecifiers,
                                                                                name.ArrayBounds);
                if (!rankSpecifiersWithSizes.SelectMany(ars => ars.Sizes).OfType <OmittedArraySizeExpressionSyntax>().Any())
                {
                    initializer =
                        SyntaxFactory.ArrayCreationExpression(
                            SyntaxFactory.ArrayType(type, rankSpecifiersWithSizes));
                }

                type = SyntaxFactory.ArrayType(type, rankSpecifiers);
            }

            return(type, initializer);
        }
        /// <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, ModifiedIdentifierSyntax syntaxForSymbol)
        {
            var methodBlockBaseSyntax = syntaxForSymbol.GetAncestor <MethodBlockBaseSyntax>();
            var methodFlow            = semanticModel.AnalyzeDataFlow(methodBlockBaseSyntax.Statements.First(), methodBlockBaseSyntax.Statements.Last());

            return(DefiniteAssignmentAnalyzer.IsDefinitelyAssignedBeforeRead(locallyDeclaredSymbol, methodFlow));
        }
예제 #3
0
        /// <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, VariableDeclaratorSyntax localDeclarator, ModifiedIdentifierSyntax name)
        {
            Func <string, bool> equalsId = s => s.Equals(name.Identifier.ValueText, StringComparison.OrdinalIgnoreCase);

            // Find the first and second statements in the method (property, constructor, etc.) which contain the identifier
            // This may overshoot where there are multiple identifiers with the same name - this is ok, it just means we could output an initializer where one is not needed
            var statements = localDeclarator.GetAncestor <MethodBlockBaseSyntax>().Statements.Where(s =>
                                                                                                    s.DescendantTokens().Any(id => ((SyntaxToken)id).IsKind(SyntaxKind.IdentifierToken) && equalsId(id.ValueText))
                                                                                                    ).Take(2).ToList();
            var first  = statements.First();
            var second = statements.Last();

            // Analyze the data flow in this block to see if initialization is required
            // If the second statement where the identifier is used is an if block, we look at the condition rather than the whole statement. This is an easy special
            // case which catches eg. the if (TryParse()) pattern. This could happen for any node which allows multiple statements.
            var dataFlow = second is MultiLineIfBlockSyntax ifBlock
                ? semanticModel.AnalyzeDataFlow(ifBlock.IfStatement.Condition)
                : semanticModel.AnalyzeDataFlow(first, second);

            bool alwaysAssigned = dataFlow.AlwaysAssigned.Any(s => equalsId(s.Name));
            bool readInside     = dataFlow.ReadInside.Any(s => equalsId(s.Name));
            bool writtenInside  = dataFlow.WrittenInside.Any(s => equalsId(s.Name));

            return(alwaysAssigned && !writtenInside || !readInside);
        }
        /// <summary>
        /// Generates .NET code a constant field decl.
        /// </summary>
        /// <param name="context">Const decl AST.</param>
        /// <returns></returns>
        public override CodeGeneratorBase VisitConstStmt(VisualBasic6Parser.ConstStmtContext context)
        {
            List <SyntaxToken> modifiers = new List <SyntaxToken>();

            VisualBasic6Parser.PublicPrivateGlobalVisibilityContext vis = context.publicPrivateGlobalVisibility();

            if (vis != null)
            {
                if (vis.PUBLIC() != null || vis.GLOBAL() != null)
                {
                    modifiers.Add(SyntaxFactory.Token(SyntaxKind.PublicKeyword));
                }
                else if (vis.PRIVATE() != null)
                {
                    modifiers.Add(SyntaxFactory.Token(SyntaxKind.PrivateKeyword));
                }
            }

            modifiers.Add(SyntaxFactory.Token(SyntaxKind.ConstKeyword));

            foreach (VisualBasic6Parser.ConstSubStmtContext subStmt in context.constSubStmt())
            {
                SimpleAsClauseSyntax asClause = null;

                if (subStmt.asTypeClause() != null)
                {
                    asClause = SyntaxFactory.SimpleAsClause(SyntaxFactory.ParseTypeName(subStmt.asTypeClause().type().GetText()));
                }

                ModifiedIdentifierSyntax identifier  = SyntaxFactory.ModifiedIdentifier(subStmt.ambiguousIdentifier().GetText());
                ExpressionSyntax         initialiser = null;

                string initialiserExpr = subStmt.valueStmt().GetText();

                //ParseExpression can't handle date/time literals - Roslyn bug? - //so handle them manually here
                if (initialiserExpr.StartsWith("#"))
                {
                    string   trimmedInitialiser = initialiserExpr.Trim(new char[] { '#' });
                    DateTime parsedVal          = new DateTime();

                    if (trimmedInitialiser.Contains("AM") || trimmedInitialiser.Contains("PM"))
                    {
                        parsedVal = DateTime.ParseExact(trimmedInitialiser, "M/d/yyyy h:mm:ss tt", CultureInfo.InvariantCulture);
                    }
                    else
                    {
                        parsedVal = DateTime.ParseExact(trimmedInitialiser, "M/d/yyyy", CultureInfo.InvariantCulture);
                    }

                    initialiser = SyntaxFactory.DateLiteralExpression(SyntaxFactory.DateLiteralToken(initialiserExpr, parsedVal));
                }
                else
                {
                    initialiser = SyntaxFactory.ParseExpression(initialiserExpr);
                }

                VariableDeclaratorSyntax varDecl = SyntaxFactory.VariableDeclarator(identifier).WithInitializer(SyntaxFactory.EqualsValue(initialiser));

                if (asClause != null)
                {
                    varDecl = varDecl.WithAsClause(asClause);
                }

                mMainDeclMembers.Add(SyntaxFactory.FieldDeclaration(varDecl).WithModifiers(SyntaxFactory.TokenList(modifiers)));
            }

            return(base.VisitConstStmt(context));
        }