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))))); }
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))))))); }
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()); }
private IfStatementSyntax MakeDictionaryEqualsTest( string propertyInfoKey, ExpressionSyntax left, ExpressionSyntax right) { string dictionaryElementVariableName = _localVariableNameGenerator.GetNextCollectionElementVariableName(); string otherPropertyVariableName = _localVariableNameGenerator.GetNextCollectionElementVariableName(); // Construct the key into the PropertyInfoDictionary so we can look up how // dictionary elements are to be compared. string valuePropertyInfoKey = PropertyInfoDictionary.MakeDictionaryItemKeyName(propertyInfoKey); TypeSyntax dictionaryValueType = _propertyInfoDictionary[valuePropertyInfoKey].Type; return(SyntaxFactory.IfStatement( // if (!Object.ReferenceEquals(left, right)) SyntaxHelper.AreDifferentObjects(left, right), SyntaxFactory.Block( // if (left == null || right == null || left.Count != right.Count) SyntaxFactory.IfStatement( SyntaxFactory.BinaryExpression( SyntaxKind.LogicalOrExpression, SyntaxHelper.IsNull(left), SyntaxFactory.BinaryExpression( SyntaxKind.LogicalOrExpression, SyntaxHelper.IsNull(right), SyntaxFactory.BinaryExpression( SyntaxKind.NotEqualsExpression, SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, left, SyntaxFactory.IdentifierName(CountPropertyName)), SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, right, SyntaxFactory.IdentifierName(CountPropertyName))))), // return false; SyntaxFactory.Block(SyntaxHelper.Return(false))), // foreach (var value_0 in left) SyntaxFactory.ForEachStatement( SyntaxHelper.Var(), dictionaryElementVariableName, left, SyntaxFactory.Block( // var value_1; SyntaxFactory.LocalDeclarationStatement( default(SyntaxTokenList), // modifiers SyntaxFactory.VariableDeclaration( dictionaryValueType, SyntaxFactory.SingletonSeparatedList( SyntaxFactory.VariableDeclarator(otherPropertyVariableName)))), // if (!right.TryGetValue(value_0.Key, out value_1)) SyntaxFactory.IfStatement( SyntaxFactory.PrefixUnaryExpression( SyntaxKind.LogicalNotExpression, SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, right, SyntaxFactory.IdentifierName("TryGetValue")), SyntaxFactory.ArgumentList( SyntaxFactory.SeparatedList( new ArgumentSyntax[] { SyntaxFactory.Argument( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(dictionaryElementVariableName), SyntaxFactory.IdentifierName(KeyPropertyName))), SyntaxFactory.Argument( default(NameColonSyntax), SyntaxFactory.Token(SyntaxKind.OutKeyword), SyntaxFactory.IdentifierName(otherPropertyVariableName)) })))), // return false; SyntaxFactory.Block(SyntaxHelper.Return(false))), GeneratePropertyComparison( valuePropertyInfoKey, SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(dictionaryElementVariableName), SyntaxFactory.IdentifierName(ValuePropertyName)), SyntaxFactory.IdentifierName(otherPropertyVariableName))))))); }
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)))) }); }