<commit_before>﻿// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Microsoft.CodeAnalysis.CSharp
{
    /// <summary>
    /// This portion of the binder converts a AnonymousObjectCreationExpressionSyntax into 
    /// a bound anonymous object creation node
    /// </summary>
    internal partial class Binder
    {
        private BoundExpression BindAnonymousObjectCreation(AnonymousObjectCreationExpressionSyntax node, DiagnosticBag diagnostics)
        {
            //  prepare
            var initializers = node.Initializers;
            int fieldCount = initializers.Count;
            bool hasError = false;

            //  bind field initializers
            BoundExpression[] boundExpressions = new BoundExpression[fieldCount];
            AnonymousTypeField[] fields = new AnonymousTypeField[fieldCount];
            CSharpSyntaxNode[] fieldSyntaxNodes = new CSharpSyntaxNode[fieldCount];

            // WARNING: Note that SemanticModel.GetDeclaredSymbol for field initializer node relies on 
            //          the fact that the order of properties in anonymous type template corresponds 
            //          1-to-1 to the appropriate filed initializer syntax nodes; This means such 
            //          correspondence must be preserved all the time including erroneous scenarios

            // set of names already used
            HashSet<string> uniqueFieldNames = new HashSet<string>();

            for (int i = 0; i < fieldCount; i++)
            {
                AnonymousObjectMemberDeclaratorSyntax fieldInitializer = initializers[i];
                NameEqualsSyntax nameEquals = fieldInitializer.NameEquals;
                ExpressionSyntax expression = fieldInitializer.Expression;

                SyntaxToken nameToken = default(SyntaxToken);
                if (nameEquals != null)
                {
                    nameToken = nameEquals.Name.Identifier;
                }
                else
                {
                    nameToken = expression.ExtractAnonymousTypeMemberName();
                }

                hasError = hasError || expression.HasErrors;
                boundExpressions[i] = this.BindValue(expression, diagnostics, BindValueKind.RValue);

                //  check the name to be unique
                string fieldName = null;
                if (nameToken.Kind() == SyntaxKind.IdentifierToken)
                {
                    fieldName = nameToken.ValueText;
                    if (uniqueFieldNames.Contains(fieldName))
                    {
                        //  name duplication
                        Error(diagnostics, ErrorCode.ERR_AnonymousTypeDuplicatePropertyName, fieldInitializer);
                        hasError = true;
                        fieldName = null;
                    }
                    else
                    {
                        uniqueFieldNames.Add(fieldName);
                    }
                }
                else
                {
                    // there is something wrong with field's name
                    hasError = true;
                }

                //  calculate the expression's type and report errors if needed
                TypeSymbol fieldType = GetAnonymousTypeFieldType(boundExpressions[i], fieldInitializer, diagnostics, ref hasError);

                // build anonymous type field descriptor
                fieldSyntaxNodes[i] = (nameToken.Kind() == SyntaxKind.IdentifierToken) ? (CSharpSyntaxNode)nameToken.Parent : fieldInitializer;
                fields[i] = new AnonymousTypeField(fieldName == null ? "$" + i.ToString() : fieldName, fieldSyntaxNodes[i].Location, fieldType);

                //  NOTE: ERR_InvalidAnonymousTypeMemberDeclarator (CS0746) would be generated by parser if needed
            }<commit_msg>Do not check uniqueness of field names twice (#16904)<commit_after>﻿// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Microsoft.CodeAnalysis.CSharp
{
    /// <summary>
    /// This portion of the binder converts a AnonymousObjectCreationExpressionSyntax into 
    /// a bound anonymous object creation node
    /// </summary>
    internal partial class Binder
    {
        private BoundExpression BindAnonymousObjectCreation(AnonymousObjectCreationExpressionSyntax node, DiagnosticBag diagnostics)
        {
            //  prepare
            var initializers = node.Initializers;
            int fieldCount = initializers.Count;
            bool hasError = false;

            //  bind field initializers
            BoundExpression[] boundExpressions = new BoundExpression[fieldCount];
            AnonymousTypeField[] fields = new AnonymousTypeField[fieldCount];
            CSharpSyntaxNode[] fieldSyntaxNodes = new CSharpSyntaxNode[fieldCount];

            // WARNING: Note that SemanticModel.GetDeclaredSymbol for field initializer node relies on 
            //          the fact that the order of properties in anonymous type template corresponds 
            //          1-to-1 to the appropriate filed initializer syntax nodes; This means such 
            //          correspondence must be preserved all the time including erroneous scenarios

            // set of names already used
            var uniqueFieldNames = PooledHashSet<string>.GetInstance();

            for (int i = 0; i < fieldCount; i++)
            {
                AnonymousObjectMemberDeclaratorSyntax fieldInitializer = initializers[i];
                NameEqualsSyntax nameEquals = fieldInitializer.NameEquals;
                ExpressionSyntax expression = fieldInitializer.Expression;

                SyntaxToken nameToken = default(SyntaxToken);
                if (nameEquals != null)
                {
                    nameToken = nameEquals.Name.Identifier;
                }
                else
                {
                    nameToken = expression.ExtractAnonymousTypeMemberName();
                }

                hasError = hasError || expression.HasErrors;
                boundExpressions[i] = this.BindValue(expression, diagnostics, BindValueKind.RValue);

                //  check the name to be unique
                string fieldName = null;
                if (nameToken.Kind() == SyntaxKind.IdentifierToken)
                {
                    fieldName = nameToken.ValueText;
                    if (!uniqueFieldNames.Add(fieldName))
                    {
                        //  name duplication
                        Error(diagnostics, ErrorCode.ERR_AnonymousTypeDuplicatePropertyName, fieldInitializer);
                        hasError = true;
                        fieldName = null;
                    }
                }
                else
                {
                    // there is something wrong with field's name
                    hasError = true;
                }

                //  calculate the expression's type and report errors if needed
                TypeSymbol fieldType = GetAnonymousTypeFieldType(boundExpressions[i], fieldInitializer, diagnostics, ref hasError);

                // build anonymous type field descriptor
                fieldSyntaxNodes[i] = (nameToken.Kind() == SyntaxKind.IdentifierToken) ? (CSharpSyntaxNode)nameToken.Parent : fieldInitializer;
                fields[i] = new AnonymousTypeField(fieldName == null ? "$" + i.ToString() : fieldName, fieldSyntaxNodes[i].Location, fieldType);

                //  NOTE: ERR_InvalidAnonymousTypeMemberDeclarator (CS0746) would be generated by parser if needed
            }

            uniqueFieldNames.Free();
{'fraction_non_alphanumeric': 0.06665027053615347, 'fraction_numerical': 0.0028283325135268077, 'mean_word_length': 1.8546858546858547, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1563074', 'n_tokens_mistral': 1889, 'n_tokens_neox': 1714, 'n_words': 512}