File: Serialization\SerializationExtensions.cs
Web Access
Project: src\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces)
// 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.Collections.Immutable;
using System.IO;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.Serialization;
 
internal static class SerializationExtensions
{
    public static WellKnownSynchronizationKind GetWellKnownSynchronizationKind(this object value)
        => value switch
        {
            SolutionCompilationStateChecksums => WellKnownSynchronizationKind.SolutionCompilationState,
            SolutionStateChecksums => WellKnownSynchronizationKind.SolutionState,
            ProjectStateChecksums => WellKnownSynchronizationKind.ProjectState,
            SolutionInfo.SolutionAttributes => WellKnownSynchronizationKind.SolutionAttributes,
            ProjectInfo.ProjectAttributes => WellKnownSynchronizationKind.ProjectAttributes,
            DocumentInfo.DocumentAttributes => WellKnownSynchronizationKind.DocumentAttributes,
            CompilationOptions => WellKnownSynchronizationKind.CompilationOptions,
            ParseOptions => WellKnownSynchronizationKind.ParseOptions,
            ProjectReference => WellKnownSynchronizationKind.ProjectReference,
            MetadataReference => WellKnownSynchronizationKind.MetadataReference,
            AnalyzerReference => WellKnownSynchronizationKind.AnalyzerReference,
            SerializableSourceText => WellKnownSynchronizationKind.SerializableSourceText,
            SourceGeneratedDocumentIdentity => WellKnownSynchronizationKind.SourceGeneratedDocumentIdentity,
            SourceGeneratorExecutionVersionMap => WellKnownSynchronizationKind.SourceGeneratorExecutionVersionMap,
            ImmutableDictionary<string, StructuredAnalyzerConfigOptions> => WellKnownSynchronizationKind.FallbackAnalyzerOptions,
            _ => throw ExceptionUtilities.UnexpectedValue(value),
        };
 
    public static CompilationOptions FixUpCompilationOptions(this ProjectInfo.ProjectAttributes info, CompilationOptions compilationOptions)
    {
        return compilationOptions.WithXmlReferenceResolver(GetXmlResolver(info.FilePath))
                                 .WithStrongNameProvider(new DesktopStrongNameProvider(GetStrongNameKeyPaths(info), Path.GetTempPath()));
    }
 
    private static XmlFileResolver GetXmlResolver(string? filePath)
    {
        // Given filePath can be any arbitrary string project is created with.
        // for primary solution in host such as VSWorkspace, ETA or MSBuildWorkspace
        // filePath will point to actual file on disk, but in memory solultion, or
        // one from AdhocWorkspace and etc, FilePath can be a random string.
        // Make sure we return only if given filePath is in right form.
        if (!PathUtilities.IsAbsolute(filePath))
        {
            // xmlFileResolver can only deal with absolute path
            // return Default
            return XmlFileResolver.Default;
        }
 
        return new XmlFileResolver(PathUtilities.GetDirectoryName(filePath));
    }
 
    private static ImmutableArray<string> GetStrongNameKeyPaths(ProjectInfo.ProjectAttributes info)
    {
        // Given FilePath/OutputFilePath can be any arbitrary strings project is created with.
        // for primary solution in host such as VSWorkspace, ETA or MSBuildWorkspace
        // filePath will point to actual file on disk, but in memory solultion, or
        // one from AdhocWorkspace and etc, FilePath/OutputFilePath can be a random string.
        // Make sure we return only if given filePath is in right form.
        if (info.FilePath == null && info.OutputFilePath == null)
        {
            // return empty since that is what IDE does for this case
            // see AbstractProject.GetStrongNameKeyPaths
            return [];
        }
 
        var builder = ArrayBuilder<string>.GetInstance();
        if (PathUtilities.IsAbsolute(info.FilePath))
        {
            // desktop strong name provider only knows how to deal with absolute path
            builder.Add(PathUtilities.GetDirectoryName(info.FilePath)!);
        }
 
        if (PathUtilities.IsAbsolute(info.OutputFilePath))
        {
            // desktop strong name provider only knows how to deal with absolute path
            builder.Add(PathUtilities.GetDirectoryName(info.OutputFilePath)!);
        }
 
        return builder.ToImmutableAndFree();
    }
}