コード例 #1
0
 private StatementSyntax GenerateObjectModelTypeHashCodeContribution(ExpressionSyntax expression)
 {
     // if (x != null)
     // {
     //     result = (result * 31) + x.ValueGetHashCode();
     // }
     return(SyntaxFactory.IfStatement(
                SyntaxHelper.IsNotNull(expression),
                SyntaxFactory.Block(
                    SyntaxFactory.ExpressionStatement(
                        SyntaxFactory.AssignmentExpression(
                            SyntaxKind.SimpleAssignmentExpression,
                            SyntaxFactory.IdentifierName(GetHashCodeResultVariableName),
                            SyntaxFactory.BinaryExpression(
                                SyntaxKind.AddExpression,
                                SyntaxFactory.ParenthesizedExpression(
                                    SyntaxFactory.BinaryExpression(
                                        SyntaxKind.MultiplyExpression,
                                        SyntaxFactory.IdentifierName(GetHashCodeResultVariableName),
                                        SyntaxFactory.LiteralExpression(
                                            SyntaxKind.NumericLiteralExpression,
                                            SyntaxFactory.Literal(GetHashCodeCombiningValue)))),
                                SyntaxFactory.InvocationExpression(
                                    SyntaxFactory.MemberAccessExpression(
                                        SyntaxKind.SimpleMemberAccessExpression,
                                        expression,
                                        SyntaxFactory.IdentifierName(GetValueHashCodeMethodName)))))))));
 }
コード例 #2
0
        private StatementSyntax GenerateCollectionHashCodeContribution(
            string hashKindKey,
            ExpressionSyntax expression)
        {
            string collectionElementVariableName = _localVariableNameGenerator.GetNextCollectionElementVariableName();

            // From the type of the element (primitive, object, list, or dictionary), create
            // the appropriate hash generation code.
            string elementHashTypeKey = PropertyInfoDictionary.MakeElementKeyName(hashKindKey);

            StatementSyntax hashCodeContribution =
                GeneratePropertyHashCodeContribution(
                    elementHashTypeKey,
                    SyntaxFactory.IdentifierName(collectionElementVariableName));

            return(SyntaxFactory.IfStatement(
                       SyntaxHelper.IsNotNull(expression),
                       SyntaxFactory.Block(
                           SyntaxFactory.ForEachStatement(
                               SyntaxHelper.Var(),
                               collectionElementVariableName,
                               expression,
                               SyntaxFactory.Block(
                                   SyntaxFactory.ExpressionStatement(
                                       SyntaxFactory.AssignmentExpression(
                                           SyntaxKind.SimpleAssignmentExpression,
                                           SyntaxFactory.IdentifierName(GetHashCodeResultVariableName),
                                           SyntaxFactory.BinaryExpression(
                                               SyntaxKind.MultiplyExpression,
                                               SyntaxFactory.IdentifierName(GetHashCodeResultVariableName),
                                               SyntaxFactory.LiteralExpression(
                                                   SyntaxKind.NumericLiteralExpression,
                                                   SyntaxFactory.Literal(GetHashCodeCombiningValue))))),
                                   hashCodeContribution)))));
        }
コード例 #3
0
        private StatementSyntax GenerateDictionaryHashCodeContribution(ExpressionSyntax expression)
        {
            string xorValueVariableName          = _localVariableNameGenerator.GetNextXorVariableName();
            string collectionElementVariableName = _localVariableNameGenerator.GetNextCollectionElementVariableName();

            return(SyntaxFactory.IfStatement(
                       SyntaxHelper.IsNotNull(expression),
                       SyntaxFactory.Block(
                           // int xor_0 = 0;
                           SyntaxFactory.LocalDeclarationStatement(
                               SyntaxFactory.VariableDeclaration(
                                   SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.IntKeyword)),
                                   SyntaxFactory.SingletonSeparatedList(
                                       SyntaxFactory.VariableDeclarator(
                                           SyntaxFactory.Identifier(xorValueVariableName),
                                           default(BracketedArgumentListSyntax),
                                           SyntaxFactory.EqualsValueClause(
                                               SyntaxFactory.LiteralExpression(
                                                   SyntaxKind.NumericLiteralExpression,
                                                   SyntaxFactory.Literal(0)))))))
                           .WithLeadingTrivia(
                               SyntaxFactory.ParseLeadingTrivia(Resources.XorDictionaryComment)),

                           SyntaxFactory.ForEachStatement(
                               SyntaxHelper.Var(),
                               collectionElementVariableName,
                               expression,
                               SyntaxFactory.Block(
                                   // xor_0 ^= value_0.Key.GetHashCode();
                                   Xor(xorValueVariableName, collectionElementVariableName, KeyPropertyName),
                                   SyntaxFactory.IfStatement(
                                       SyntaxHelper.IsNotNull(
                                           SyntaxFactory.MemberAccessExpression(
                                               SyntaxKind.SimpleMemberAccessExpression,
                                               SyntaxFactory.IdentifierName(collectionElementVariableName),
                                               SyntaxFactory.IdentifierName(ValuePropertyName))),
                                       SyntaxFactory.Block(
                                           Xor(xorValueVariableName, collectionElementVariableName, ValuePropertyName))))),

                           SyntaxFactory.ExpressionStatement(
                               SyntaxFactory.AssignmentExpression(
                                   SyntaxKind.SimpleAssignmentExpression,
                                   SyntaxFactory.IdentifierName(GetHashCodeResultVariableName),
                                   SyntaxFactory.BinaryExpression(
                                       SyntaxKind.AddExpression,
                                       SyntaxFactory.ParenthesizedExpression(
                                           SyntaxFactory.BinaryExpression(
                                               SyntaxKind.MultiplyExpression,
                                               SyntaxFactory.IdentifierName(GetHashCodeResultVariableName),
                                               SyntaxFactory.LiteralExpression(
                                                   SyntaxKind.NumericLiteralExpression,
                                                   SyntaxFactory.Literal(GetHashCodeCombiningValue)))),
                                       SyntaxFactory.IdentifierName(xorValueVariableName)))))));
        }
コード例 #4
0
        /// <summary>
        /// Generate the visitor method for one of the classes defined by the schema.
        /// </summary>
        /// <param name="className">
        /// The name of the class for which a visitor method is to be generated.
        /// </param>
        /// <returns>
        /// A method declaration for the vistor method.
        /// </returns>
        /// <example>
        /// <code>
        /// public virtual VisitLocation(Location node)
        /// {
        ///     if (node != null)
        ///     {
        ///         // GenerateVisitClassBodyStatements()
        ///     }
        ///
        ///     return node;
        /// }
        /// </code>
        /// </example>
        private MethodDeclarationSyntax GenerateVisitClassMethod(string className)
        {
            string     methodName         = MakeVisitClassMethodName(className);
            TypeSyntax generatedClassType = SyntaxFactory.ParseTypeName(className);

            return(SyntaxFactory.MethodDeclaration(generatedClassType, methodName)
                   .AddModifiers(
                       SyntaxFactory.Token(SyntaxKind.PublicKeyword),
                       SyntaxFactory.Token(SyntaxKind.VirtualKeyword))
                   .AddParameterListParameters(
                       SyntaxFactory.Parameter(SyntaxFactory.Identifier(NodeParameterName))
                       .WithType(generatedClassType))
                   .AddBodyStatements(
                       SyntaxFactory.IfStatement(
                           SyntaxHelper.IsNotNull(NodeParameterName),
                           SyntaxFactory.Block(
                               GeneratePropertyVisits(className))),
                       SyntaxFactory.ReturnStatement(
                           SyntaxFactory.IdentifierName(NodeParameterName))));
        }
コード例 #5
0
 private StatementSyntax GenerateScalarReferenceTypeHashCodeContribution(ExpressionSyntax expression)
 {
     return(SyntaxFactory.IfStatement(
                SyntaxHelper.IsNotNull(expression),
                SyntaxFactory.Block(GenerateScalarHashCodeContribution(expression))));
 }
コード例 #6
0
        private StatementSyntax[] GenerateArrayVisit(
            int arrayRank,
            int nestingLevel,
            ExpressionSyntax arrayValuedExpression)
        {
            ExpressionSyntax loopLimitExpression;

            if (nestingLevel == 0)
            {
                // node.Locations.Count
                loopLimitExpression = SyntaxFactory.MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression,
                    arrayValuedExpression,
                    SyntaxFactory.IdentifierName(CountPropertyName));
            }
            else
            {
                // value_0.Count
                loopLimitExpression = SyntaxFactory.MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression,
                    SyntaxFactory.IdentifierName(
                        LocalVariableNameGenerator.GetCollectionElementVariableName(nestingLevel - 1)),
                    SyntaxFactory.IdentifierName(CountPropertyName));
            }

            var statements = new List <StatementSyntax>();

            if (nestingLevel < arrayRank)
            {
                // We're not yet at the innermost level, so we need another for loop.
                string loopVariableName         = LocalVariableNameGenerator.GetLoopIndexVariableName(nestingLevel);
                string outerLoopVariableName    = LocalVariableNameGenerator.GetLoopIndexVariableName(nestingLevel - 1);
                string arrayElementVariableName = LocalVariableNameGenerator.GetCollectionElementVariableName(nestingLevel - 1);

                // For every level except the outermost, we need to get an array element and test whether
                // it's null.
                if (nestingLevel > 0)
                {
                    // var value_0 = node.Locations[index_0];
                    statements.Add(
                        SyntaxFactory.LocalDeclarationStatement(
                            SyntaxFactory.VariableDeclaration(
                                SyntaxHelper.Var(),
                                SyntaxFactory.SingletonSeparatedList(
                                    SyntaxFactory.VariableDeclarator(
                                        SyntaxFactory.Identifier(arrayElementVariableName),
                                        default(BracketedArgumentListSyntax),
                                        SyntaxFactory.EqualsValueClause(
                                            SyntaxFactory.ElementAccessExpression(
                                                arrayValuedExpression,
                                                SyntaxFactory.BracketedArgumentList(
                                                    SyntaxFactory.SingletonSeparatedList(
                                                        SyntaxFactory.Argument(
                                                            SyntaxFactory.IdentifierName(outerLoopVariableName)))))))))));
                }

                // for
                ForStatementSyntax forStatement = SyntaxFactory.ForStatement(
                    // (index_0 = 0;
                    SyntaxFactory.VariableDeclaration(
                        SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.IntKeyword)),
                        SyntaxFactory.SingletonSeparatedList(
                            SyntaxFactory.VariableDeclarator(loopVariableName)
                            .WithInitializer(
                                SyntaxFactory.EqualsValueClause(SyntaxFactory.LiteralExpression(
                                                                    SyntaxKind.NumericLiteralExpression,
                                                                    SyntaxFactory.Literal(0)))))),
                    default(SeparatedSyntaxList <ExpressionSyntax>),
                    // index_0 < value_0.Count;
                    SyntaxFactory.BinaryExpression(
                        SyntaxKind.LessThanExpression,
                        SyntaxFactory.IdentifierName(loopVariableName),
                        loopLimitExpression),
                    // ++index_0)
                    SyntaxFactory.SingletonSeparatedList <ExpressionSyntax>(
                        SyntaxFactory.PrefixUnaryExpression(
                            SyntaxKind.PreIncrementExpression,
                            SyntaxFactory.IdentifierName(loopVariableName))),
                    // { ... }
                    SyntaxFactory.Block(
                        GenerateArrayVisit(arrayRank, nestingLevel + 1, arrayValuedExpression)));

                if (nestingLevel > 0)
                {
                    statements.Add(
                        SyntaxFactory.IfStatement(
                            SyntaxHelper.IsNotNull(arrayElementVariableName),
                            SyntaxFactory.Block(
                                forStatement)));
                }
                else
                {
                    statements.Add(forStatement);
                }
            }
            else
            {
                string loopVariableName = LocalVariableNameGenerator.GetLoopIndexVariableName(nestingLevel - 1);

                // We're in the body of the innermost loop over array elements. This is
                // where we do the assignment. For arrays of rank 1, the assignment is
                // to an element of the property itself. For arrays of rank > 1, the
                // assignment is to an array element of a temporary variable representing
                // one of the elements of the property.
                ElementAccessExpressionSyntax elementAccessExpression;
                if (arrayRank == 1)
                {
                    // node.Location[index_0]
                    elementAccessExpression =
                        SyntaxFactory.ElementAccessExpression(
                            arrayValuedExpression,
                            SyntaxFactory.BracketedArgumentList(
                                SyntaxFactory.SingletonSeparatedList(
                                    SyntaxFactory.Argument(
                                        SyntaxFactory.IdentifierName(loopVariableName)))));
                }
                else
                {
                    string arrayElementVariableName = LocalVariableNameGenerator.GetCollectionElementVariableName(nestingLevel - 2);

                    // value_0[index_1]
                    elementAccessExpression =
                        SyntaxFactory.ElementAccessExpression(
                            SyntaxFactory.IdentifierName(arrayElementVariableName),
                            SyntaxFactory.BracketedArgumentList(
                                SyntaxFactory.SingletonSeparatedList(
                                    SyntaxFactory.Argument(
                                        SyntaxFactory.IdentifierName(loopVariableName)))));
                }

                statements.Add(
                    SyntaxFactory.ExpressionStatement(
                        SyntaxFactory.AssignmentExpression(
                            SyntaxKind.SimpleAssignmentExpression,
                            elementAccessExpression,
                            SyntaxFactory.InvocationExpression(
                                SyntaxFactory.IdentifierName(VisitNullCheckedMethodName),
                                SyntaxHelper.ArgumentList(elementAccessExpression)))));
            }

            return(statements.ToArray());
        }
コード例 #7
0
        private StatementSyntax[] GenerateDictionaryVisit(int arrayRank, string propertyName)
        {
            const string KeyVariableName   = "key";
            const string KeysVariableName  = "keys";
            const string KeysPropertyName  = "Keys";
            const string ValueVariableName = "value";

            ExpressionSyntax dictionaryValue =
                SyntaxFactory.ElementAccessExpression(
                    SyntaxFactory.MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        SyntaxFactory.IdentifierName(NodeParameterName),
                        SyntaxFactory.IdentifierName(propertyName)),
                    SyntaxFactory.BracketedArgumentList(
                        SyntaxFactory.SingletonSeparatedList(
                            SyntaxFactory.Argument(
                                SyntaxFactory.IdentifierName(KeyVariableName)))));

            // The code to visit an individual dictionary element depends on whether the
            // elements are scalar values or arrays.
            StatementSyntax[] dictionaryElementVisitStatements;

            if (arrayRank == 0)
            {
                dictionaryElementVisitStatements = new StatementSyntax[]
                {
                    GenerateScalarVisit(dictionaryValue, SyntaxFactory.IdentifierName(ValueVariableName))
                };
            }
            else
            {
                ExpressionSyntax arrayValuedExpression =
                    SyntaxFactory.ElementAccessExpression(
                        SyntaxFactory.MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            SyntaxFactory.IdentifierName(NodeParameterName),
                            SyntaxFactory.IdentifierName(propertyName)),
                        SyntaxFactory.BracketedArgumentList(
                            SyntaxFactory.SingletonSeparatedList(
                                SyntaxFactory.Argument(
                                    SyntaxFactory.IdentifierName(KeyVariableName)))));

                dictionaryElementVisitStatements = GenerateArrayVisit(
                    arrayRank,
                    nestingLevel: 0,
                    arrayValuedExpression: arrayValuedExpression);
            }

            return(new StatementSyntax[]
            {
                // var keys = node.PropertyName.Keys.ToArray();
                SyntaxFactory.LocalDeclarationStatement(
                    SyntaxFactory.VariableDeclaration(
                        SyntaxHelper.Var(),
                        SyntaxFactory.SingletonSeparatedList(
                            SyntaxFactory.VariableDeclarator(
                                SyntaxFactory.Identifier(KeysVariableName),
                                default(BracketedArgumentListSyntax),
                                SyntaxFactory.EqualsValueClause(
                                    SyntaxFactory.InvocationExpression(
                                        SyntaxFactory.MemberAccessExpression(
                                            SyntaxKind.SimpleMemberAccessExpression,
                                            SyntaxFactory.MemberAccessExpression(
                                                SyntaxKind.SimpleMemberAccessExpression,
                                                SyntaxFactory.MemberAccessExpression(
                                                    SyntaxKind.SimpleMemberAccessExpression,
                                                    SyntaxFactory.IdentifierName(NodeParameterName),
                                                    SyntaxFactory.IdentifierName(propertyName)),
                                                SyntaxFactory.IdentifierName(KeysPropertyName)),
                                            SyntaxFactory.IdentifierName(ToArrayMethodName)),
                                        SyntaxHelper.ArgumentList())))))),

                // foreach (var key in keys)
                SyntaxFactory.ForEachStatement(
                    SyntaxHelper.Var(),
                    KeyVariableName,
                    SyntaxFactory.IdentifierName(KeysVariableName),
                    SyntaxFactory.Block(
                        SyntaxFactory.LocalDeclarationStatement(
                            SyntaxFactory.VariableDeclaration(
                                SyntaxHelper.Var(),
                                SyntaxFactory.SingletonSeparatedList(
                                    SyntaxFactory.VariableDeclarator(
                                        SyntaxFactory.Identifier(ValueVariableName),
                                        default(BracketedArgumentListSyntax),
                                        SyntaxFactory.EqualsValueClause(dictionaryValue))))),
                        SyntaxFactory.IfStatement(
                            SyntaxHelper.IsNotNull(ValueVariableName),
                            SyntaxFactory.Block(dictionaryElementVisitStatements))))
            });
        }
コード例 #8
0
        /// <summary>
        /// Generate the code necessary to visit each property.
        /// </summary>
        /// <param name="className">
        /// The name of the class for which the visitor method is being generated.
        /// </param>
        /// <returns>
        /// The statements necessary to visit each property in the class.
        /// </returns>
        /// <remarks>
        /// It is only necessary to visit those properties which are themselves of a
        /// schema-defined type. Scalar properties can be visited directly. For properties
        /// of array type, each element must be visited.
        /// </remarks>
        /// <example>
        /// Visiting a class with one scalar-valued property and one array-valued property:
        /// <code>
        /// node.MessageDescriptor = VisitNullChecked(node.MessageDescriptor);
        ///
        /// if (node.Locations != null)
        /// {
        ///     // GenerateArrayVisit()
        /// }
        /// </code>
        /// </example>
        private StatementSyntax[] GeneratePropertyVisits(string className)
        {
            var statements = new List <StatementSyntax>();

            PropertyInfoDictionary propertyInfoDictionary = _classInfoDictionary[className];

            foreach (KeyValuePair <string, PropertyInfo> entry in propertyInfoDictionary.OrderBy(kvp => kvp.Value.DeclarationOrder))
            {
                string       propertyNameWithRank = entry.Key;
                PropertyInfo propertyInfo         = entry.Value;

                // We only need to visit properties whose type is one of the classes
                // defined by the schema.
                if (!propertyInfo.IsOfSchemaDefinedType)
                {
                    continue;
                }

                string propertyName = propertyNameWithRank.BasePropertyName(out int arrayRank, out bool isDictionary);

                TypeSyntax collectionType = propertyInfoDictionary.GetConcreteListType(propertyName);
                TypeSyntax elementType    = propertyInfoDictionary[propertyNameWithRank].Type;

                ExpressionSyntax propertyAccessExpression =
                    SyntaxFactory.MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        SyntaxFactory.IdentifierName(NodeParameterName),
                        SyntaxFactory.IdentifierName(propertyName));

                if (arrayRank == 0 && !isDictionary)
                {
                    // This is a simple scalar assignment.
                    statements.Add(GenerateScalarVisit(propertyAccessExpression));
                }
                else
                {
                    _localVariableNameGenerator.Reset();

                    StatementSyntax[] nullTestedStatements = null;
                    if (isDictionary)
                    {
                        nullTestedStatements = GenerateDictionaryVisit(arrayRank, propertyName);
                    }
                    else
                    {
                        nullTestedStatements = GenerateArrayVisit(
                            arrayRank,
                            nestingLevel: 0,
                            arrayValuedExpression: propertyAccessExpression);
                    }

                    statements.Add(
                        SyntaxFactory.IfStatement(
                            SyntaxHelper.IsNotNull(
                                SyntaxFactory.MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    SyntaxFactory.IdentifierName(NodeParameterName),
                                    SyntaxFactory.IdentifierName(propertyName))),
                            SyntaxFactory.Block(nullTestedStatements)));
                }
            }

            return(statements.ToArray());
        }