<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.

using System;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.Remote
{
    #region FindReferences

    internal class SerializableFindReferencesSearchOptions
    {
        public bool AssociatePropertyReferencesWithSpecificAccessor;
        public bool Cascade;

        public static SerializableFindReferencesSearchOptions Dehydrate(FindReferencesSearchOptions options)
        {
            return new SerializableFindReferencesSearchOptions
            {
                AssociatePropertyReferencesWithSpecificAccessor = options.AssociatePropertyReferencesWithSpecificAccessor,
                Cascade = options.Cascade,
            };
        }

        public FindReferencesSearchOptions Rehydrate()
        {
            return new FindReferencesSearchOptions(
                associatePropertyReferencesWithSpecificAccessor: AssociatePropertyReferencesWithSpecificAccessor,
                cascade: Cascade);
        }
    }

    internal class SerializableSymbolAndProjectId
    {
        public string SymbolKeyData;
        public ProjectId ProjectId;

        public static SerializableSymbolAndProjectId Dehydrate(
            IAliasSymbol alias, Document document, CancellationToken cancellationToken)
        {
            return alias == null
                ? null
                : Dehydrate(document.Project.Solution, alias, cancellationToken);
        }

        public static SerializableSymbolAndProjectId Dehydrate(
            Solution solution, ISymbol symbol, CancellationToken cancellationToken)
        {
            var project = solution.GetOriginatingProject(symbol);
            Contract.ThrowIfNull(project, WorkspacesResources.Symbols_project_could_not_be_found_in_the_provided_solution);

            return Create(symbol, project, cancellationToken);
        }

        public static SerializableSymbolAndProjectId Create(ISymbol symbol, Project project, CancellationToken cancellationToken)
            => new SerializableSymbolAndProjectId
            {
                SymbolKeyData = symbol.GetSymbolKey(cancellationToken).ToString(),
                ProjectId = project.Id,
            };

        public static bool TryCreate(
            ISymbol symbol, Solution solution, CancellationToken cancellationToken,
            out SerializableSymbolAndProjectId result)
        {
            var project = solution.GetOriginatingProject(symbol);
            if (project == null)
            {
                result = null;
                return false;
            }

            return TryCreate(symbol, project, cancellationToken, out result);
        }

        public static bool TryCreate(
            ISymbol symbol, Project project, CancellationToken cancellationToken,
            out SerializableSymbolAndProjectId result)
        {
            if (!SymbolKey.CanCreate(symbol, cancellationToken))
            {
                result = null;
                return false;
            }

            result = new SerializableSymbolAndProjectId
            {
                SymbolKeyData = SymbolKey.CreateString(symbol, cancellationToken),
                ProjectId = project.Id,
            };
            return true;
        }
        public async Task<ISymbol> TryRehydrateAsync(
            Solution solution, CancellationToken cancellationToken)
        {
            var projectId = ProjectId;
            var project = solution.GetProject(projectId);
            var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            // The server and client should both be talking about the same compilation.  As such
            // locations in symbols are save to resolve as we rehydrate the SymbolKey.
            var symbol = SymbolKey.ResolveString(
                SymbolKeyData, compilation, out var failureReason, cancellationToken).GetAnySymbol();

            if (symbol == null)
            {
                try
                {
                    throw new InvalidOperationException(
                        $"We should always be able to resolve a symbol back on the host side:\r\n{SymbolKeyData}\r\n{failureReason}");
                }
                catch (Exception ex) when (FatalError.ReportWithoutCrash(ex))
                {
                    return null;
                }
            }

            return symbol;
        }
    }

    internal class SerializableSymbolUsageInfo : IEquatable<SerializableSymbolUsageInfo>
    {
        public bool IsValueUsageInfo;
        public int UsageInfoUnderlyingValue;

        public static SerializableSymbolUsageInfo Dehydrate(SymbolUsageInfo symbolUsageInfo)
        {
            bool isValueUsageInfo;
            int usageInfoUnderlyingValue;
            if (symbolUsageInfo.ValueUsageInfoOpt.HasValue)
            {
                isValueUsageInfo = true;
                usageInfoUnderlyingValue = (int)symbolUsageInfo.ValueUsageInfoOpt.Value;
            }
            else
            {
                isValueUsageInfo = false;<commit_msg>Report teh project name that we were unable to recover a symbol from.<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.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.Remote
{
    #region FindReferences

    internal class SerializableFindReferencesSearchOptions
    {
        public bool AssociatePropertyReferencesWithSpecificAccessor;
        public bool Cascade;

        public static SerializableFindReferencesSearchOptions Dehydrate(FindReferencesSearchOptions options)
        {
            return new SerializableFindReferencesSearchOptions
            {
                AssociatePropertyReferencesWithSpecificAccessor = options.AssociatePropertyReferencesWithSpecificAccessor,
                Cascade = options.Cascade,
            };
        }

        public FindReferencesSearchOptions Rehydrate()
        {
            return new FindReferencesSearchOptions(
                associatePropertyReferencesWithSpecificAccessor: AssociatePropertyReferencesWithSpecificAccessor,
                cascade: Cascade);
        }
    }

    internal class SerializableSymbolAndProjectId
    {
        public string SymbolKeyData;
        public ProjectId ProjectId;

        public static SerializableSymbolAndProjectId Dehydrate(
            IAliasSymbol alias, Document document, CancellationToken cancellationToken)
        {
            return alias == null
                ? null
                : Dehydrate(document.Project.Solution, alias, cancellationToken);
        }

        public static SerializableSymbolAndProjectId Dehydrate(
            Solution solution, ISymbol symbol, CancellationToken cancellationToken)
        {
            var project = solution.GetOriginatingProject(symbol);
            Contract.ThrowIfNull(project, WorkspacesResources.Symbols_project_could_not_be_found_in_the_provided_solution);

            return Create(symbol, project, cancellationToken);
        }

        public static SerializableSymbolAndProjectId Create(ISymbol symbol, Project project, CancellationToken cancellationToken)
            => new SerializableSymbolAndProjectId
            {
                SymbolKeyData = symbol.GetSymbolKey(cancellationToken).ToString(),
                ProjectId = project.Id,
            };

        public static bool TryCreate(
            ISymbol symbol, Solution solution, CancellationToken cancellationToken,
            out SerializableSymbolAndProjectId result)
        {
            var project = solution.GetOriginatingProject(symbol);
            if (project == null)
            {
                result = null;
                return false;
            }

            return TryCreate(symbol, project, cancellationToken, out result);
        }

        public static bool TryCreate(
            ISymbol symbol, Project project, CancellationToken cancellationToken,
            out SerializableSymbolAndProjectId result)
        {
            if (!SymbolKey.CanCreate(symbol, cancellationToken))
            {
                result = null;
                return false;
            }

            result = new SerializableSymbolAndProjectId
            {
                SymbolKeyData = SymbolKey.CreateString(symbol, cancellationToken),
                ProjectId = project.Id,
            };
            return true;
        }
        public async Task<ISymbol> TryRehydrateAsync(
            Solution solution, CancellationToken cancellationToken)
        {
            var projectId = ProjectId;
            var project = solution.GetProject(projectId);
            var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);

            // The server and client should both be talking about the same compilation.  As such
            // locations in symbols are save to resolve as we rehydrate the SymbolKey.
            var symbol = SymbolKey.ResolveString(
                SymbolKeyData, compilation, out var failureReason, cancellationToken).GetAnySymbol();

            if (symbol == null)
            {
                try
                {
                    throw new InvalidOperationException(
                        $"We should always be able to resolve a symbol back on the host side:\r\n{project.Name}\r\n{SymbolKeyData}\r\n{failureReason}");
                }
                catch (Exception ex) when (FatalError.ReportWithoutCrash(ex))
                {
                    return null;
                }
            }

            return symbol;
        }
    }

    internal class SerializableSymbolUsageInfo : IEquatable<SerializableSymbolUsageInfo>
    {
        public bool IsValueUsageInfo;
        public int UsageInfoUnderlyingValue;

        public static SerializableSymbolUsageInfo Dehydrate(SymbolUsageInfo symbolUsageInfo)
        {
            bool isValueUsageInfo;
            int usageInfoUnderlyingValue;
            if (symbolUsageInfo.ValueUsageInfoOpt.HasValue)
            {
                isValueUsageInfo = true;
                usageInfoUnderlyingValue = (int)symbolUsageInfo.ValueUsageInfoOpt.Value;
            }
            else
            {
                isValueUsageInfo = false;
{'fraction_non_alphanumeric': 0.05335032774945375, 'fraction_numerical': 0.0, 'mean_word_length': 2.123400625533125, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, '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': '5708964', 'n_tokens_mistral': 2490, 'n_tokens_neox': 2380, 'n_words': 641}