<commit_before>﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable disable

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Shared.Extensions;

namespace Microsoft.CodeAnalysis.FindSymbols
{
    internal static class ReferenceLocationExtensions
    {
        public static async Task<Dictionary<ISymbol, List<Location>>> FindReferencingSymbolsAsync(
            this IEnumerable<ReferenceLocation> referenceLocations,
            CancellationToken cancellationToken)
        {
            var documentGroups = referenceLocations.GroupBy(loc => loc.Document);
            var projectGroups = documentGroups.GroupBy(g => g.Key.Project);
            var result = new Dictionary<ISymbol, List<Location>>();

            foreach (var projectGroup in projectGroups)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var project = projectGroup.Key;
                if (project.SupportsCompilation)
                {
                    var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

                    foreach (var documentGroup in projectGroup)
                    {
                        var document = documentGroup.Key;
                        var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
                        AddSymbols(semanticModel, documentGroup, result);
                    }

                    // Keep compilation alive so that GetSemanticModelAsync remains cheap
                    GC.KeepAlive(compilation);
                }
            }

            return result;
        }

        private static void AddSymbols(
            SemanticModel semanticModel,
            IEnumerable<ReferenceLocation> references,
            Dictionary<ISymbol, List<Location>> result)
        {
            foreach (var reference in references)
            {
                var containingSymbol = GetEnclosingMethodOrPropertyOrField(semanticModel, reference);
                if (containingSymbol != null)
                {
                    if (!result.TryGetValue(containingSymbol, out var locations))
                    {
                        locations = new List<Location>();
                        result.Add(containingSymbol, locations);
                    }

                    locations.Add(reference.Location);
                }
            }
        }

        private static ISymbol GetEnclosingMethodOrPropertyOrField(
            SemanticModel semanticModel,
            ReferenceLocation reference)
        {
            var enclosingSymbol = semanticModel.GetEnclosingSymbol(reference.Location.SourceSpan.Start);

            for (var current = enclosingSymbol; current != null; current = current.ContainingSymbol)
            {<commit_msg>NRT enable code<commit_after>﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Shared.Extensions;

namespace Microsoft.CodeAnalysis.FindSymbols
{
    internal static class ReferenceLocationExtensions
    {
        public static async Task<Dictionary<ISymbol, List<Location>>> FindReferencingSymbolsAsync(
            this IEnumerable<ReferenceLocation> referenceLocations,
            CancellationToken cancellationToken)
        {
            var documentGroups = referenceLocations.GroupBy(loc => loc.Document);
            var projectGroups = documentGroups.GroupBy(g => g.Key.Project);
            var result = new Dictionary<ISymbol, List<Location>>();

            foreach (var projectGroup in projectGroups)
            {
                cancellationToken.ThrowIfCancellationRequested();

                var project = projectGroup.Key;
                if (project.SupportsCompilation)
                {
                    var compilation = await project.GetRequiredCompilationAsync(cancellationToken).ConfigureAwait(false);

                    foreach (var documentGroup in projectGroup)
                    {
                        var document = documentGroup.Key;
                        var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);
                        AddSymbols(semanticModel, documentGroup, result);
                    }

                    // Keep compilation alive so that GetSemanticModelAsync remains cheap
                    GC.KeepAlive(compilation);
                }
            }

            return result;
        }

        private static void AddSymbols(
            SemanticModel semanticModel,
            IEnumerable<ReferenceLocation> references,
            Dictionary<ISymbol, List<Location>> result)
        {
            foreach (var reference in references)
            {
                var containingSymbol = GetEnclosingMethodOrPropertyOrField(semanticModel, reference);
                if (containingSymbol != null)
                {
                    if (!result.TryGetValue(containingSymbol, out var locations))
                    {
                        locations = new List<Location>();
                        result.Add(containingSymbol, locations);
                    }

                    locations.Add(reference.Location);
                }
            }
        }

        private static ISymbol? GetEnclosingMethodOrPropertyOrField(
            SemanticModel semanticModel,
            ReferenceLocation reference)
        {
            var enclosingSymbol = semanticModel.GetEnclosingSymbol(reference.Location.SourceSpan.Start);

            for (var current = enclosingSymbol; current != null; current = current.ContainingSymbol)
            {
{'fraction_non_alphanumeric': 0.06525974025974025, 'fraction_numerical': 0.0, 'mean_word_length': 1.947846889952153, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 27, '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': '376978', 'n_tokens_mistral': 1372, 'n_tokens_neox': 1302, 'n_words': 344}