File: HostWorkspace\WorkspaceProjectFactoryService.cs
Web Access
Project: src\src\LanguageServer\Microsoft.CodeAnalysis.LanguageServer\Microsoft.CodeAnalysis.LanguageServer.csproj (Microsoft.CodeAnalysis.LanguageServer)
// 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.ComponentModel.Composition;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServer.Telemetry;
using Microsoft.CodeAnalysis.Remote.ProjectSystem;
using Microsoft.Extensions.Logging;
using Microsoft.ServiceHub.Framework;
using Microsoft.VisualStudio.Shell.ServiceBroker;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace;
#pragma warning disable RS0030 // This is intentionally using System.ComponentModel.Composition for compatibility with MEF service broker.
/// <summary>
/// An implementation of the brokered service <see cref="IWorkspaceProjectFactoryService"/> that just maps calls to the underlying project system.
/// </summary>
[ExportBrokeredService("Microsoft.VisualStudio.LanguageServices.WorkspaceProjectFactoryService", null, Audience = ServiceAudience.Local)]
internal class WorkspaceProjectFactoryService : IWorkspaceProjectFactoryService, IExportedBrokeredService
{
    private readonly LanguageServerWorkspaceFactory _workspaceFactory;
    private readonly ProjectInitializationHandler _projectInitializationHandler;
    private readonly ILogger _logger;
    private readonly ILoggerFactory _loggerFactory;
 
    [ImportingConstructor]
    [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
    public WorkspaceProjectFactoryService(LanguageServerWorkspaceFactory workspaceFactory, ProjectInitializationHandler projectInitializationHandler, ILoggerFactory loggerFactory)
    {
        _workspaceFactory = workspaceFactory;
        _projectInitializationHandler = projectInitializationHandler;
        _loggerFactory = loggerFactory;
        _logger = loggerFactory.CreateLogger(nameof(WorkspaceProjectFactoryService));
    }
 
    ServiceRpcDescriptor IExportedBrokeredService.Descriptor => WorkspaceProjectFactoryServiceDescriptor.ServiceDescriptor;
 
    async Task IExportedBrokeredService.InitializeAsync(CancellationToken cancellationToken)
    {
        await _projectInitializationHandler.SubscribeToInitializationCompleteAsync(cancellationToken);
    }
 
    public async Task<IWorkspaceProject> CreateAndAddProjectAsync(WorkspaceProjectCreationInfo creationInfo, CancellationToken _)
    {
        _logger.LogInformation(string.Format(LanguageServerResources.Project_0_loaded_by_CSharp_Dev_Kit, creationInfo.FilePath));
        VSCodeRequestTelemetryLogger.ReportProjectLoadStarted();
        try
        {
            if (creationInfo.BuildSystemProperties.TryGetValue("SolutionPath", out var solutionPath))
            {
                _workspaceFactory.ProjectSystemProjectFactory.SolutionPath = solutionPath;
            }
 
            var project = await _workspaceFactory.ProjectSystemProjectFactory.CreateAndAddToWorkspaceAsync(
                creationInfo.DisplayName,
                creationInfo.Language,
                new Workspaces.ProjectSystem.ProjectSystemProjectCreationInfo { FilePath = creationInfo.FilePath },
                _workspaceFactory.ProjectSystemHostInfo);
 
            var workspaceProject = new WorkspaceProject(project, _workspaceFactory.Workspace.Services.SolutionServices, _workspaceFactory.TargetFrameworkManager, _loggerFactory);
 
            // We've created a new project, so initialize properties we have
            await workspaceProject.SetBuildSystemPropertiesAsync(creationInfo.BuildSystemProperties, CancellationToken.None);
 
            return workspaceProject;
        }
        catch (Exception e) when (LanguageServerFatalError.ReportAndLogAndPropagate(e, _logger, $"Failed to create project {creationInfo.DisplayName}"))
        {
            throw ExceptionUtilities.Unreachable();
        }
    }
 
    public Task<IReadOnlyCollection<string>> GetSupportedBuildSystemPropertiesAsync(CancellationToken _)
    {
        // TODO: implement
        return Task.FromResult((IReadOnlyCollection<string>)ImmutableArray<string>.Empty);
    }
}
#pragma warning restore RS0030 // Do not used banned APIs