ServiceHubRemoteHostClient.WorkspaceHost.cs 7.3 KB
Newer Older
C
CyrusNajmabadi 已提交
1 2 3
// 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.Threading;
4
using System.Threading.Tasks;
C
CyrusNajmabadi 已提交
5 6
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
7
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
C
CyrusNajmabadi 已提交
8 9 10 11 12 13 14 15
using Microsoft.CodeAnalysis.Remote;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
using Microsoft.VisualStudio.Text;

namespace Microsoft.VisualStudio.LanguageServices.Remote
{
    internal partial class ServiceHubRemoteHostClient
    {
16
        private class WorkspaceHost : ForegroundThreadAffinitizedObject, IVisualStudioWorkspaceHost, IVisualStudioWorkingFolder
C
CyrusNajmabadi 已提交
17 18
        {
            private readonly VisualStudioWorkspaceImpl _workspace;
19
            private readonly RemoteHostClient _client;
20

21 22 23 24 25 26
            /// <summary>
            /// A <see cref="RemoteHostClient.Connection"/> to use if non-null.  If null, we'll create 
            /// our own connection to the OOP process.
            /// </summary>
            private Connection _preferredConnection;

27 28 29 30
            // We have to capture the solution ID because otherwise we won't know
            // what is is when we get told about OnSolutionRemoved.  If we try
            // to access the solution off of _workspace at that point, it will be
            // gone.
C
CyrusNajmabadi 已提交
31 32
            private SolutionId _currentSolutionId;

33 34 35
            public WorkspaceHost(
                VisualStudioWorkspaceImpl workspace,
                RemoteHostClient client)
C
CyrusNajmabadi 已提交
36 37
            {
                _workspace = workspace;
38
                _client = client;
C
CyrusNajmabadi 已提交
39
                _currentSolutionId = workspace.CurrentSolution.Id;
40
            }
41

42 43 44 45 46 47
            public void SetPreferredConnection(Connection connection)
            {
                this.AssertIsForeground();
                _preferredConnection = connection;
            }

48
            public void OnAfterWorkingFolderChange()
C
CyrusNajmabadi 已提交
49
            {
50
                this.AssertIsForeground();
51
                RegisterPrimarySolutionAsync().Wait();
C
CyrusNajmabadi 已提交
52 53
            }

54
            public void OnSolutionAdded(SolutionInfo solutionInfo)
C
CyrusNajmabadi 已提交
55
            {
56
                this.AssertIsForeground();
57
                RegisterPrimarySolutionAsync().Wait();
58
            }
59

60 61 62 63 64 65 66 67 68 69 70 71
            private async Task<(Connection, bool dispose)> GetConnectionAsync()
            {
                this.AssertIsForeground();
                if (_preferredConnection != null)
                {
                    return (_preferredConnection, dispose: false);
                }

                var connection = await _client.TryCreateConnectionAsync(WellKnownRemoteHostServices.RemoteHostService, CancellationToken.None).ConfigureAwait(false);
                return (connection, dispose: true);
            }

72
            private async Task RegisterPrimarySolutionAsync()
73
            {
C
CyrusNajmabadi 已提交
74
                _currentSolutionId = _workspace.CurrentSolution.Id;
75 76
                var solutionId = _currentSolutionId;

77 78
                var (connection, dispose) = await GetConnectionAsync().ConfigureAwait(false);
                try
79
                {
80
                    if (connection == null)
81
                    {
82
                        // failed to create connection. remote host might not responding or gone. 
83 84 85
                        return;
                    }

86
                    var storageLocation = _workspace.DeferredState?.ProjectTracker.GetWorkingFolderPath(_workspace.CurrentSolution);
87

88
                    await connection.InvokeAsync(
89 90 91 92 93 94 95 96 97
                        nameof(IRemoteHostService.RegisterPrimarySolutionId), 
                        new object[] { solutionId, storageLocation }, CancellationToken.None).ConfigureAwait(false);
                }
                finally
                {
                    if (dispose)
                    {
                        connection?.Dispose();
                    }
98
                }
C
CyrusNajmabadi 已提交
99 100
            }

101
            public void OnBeforeWorkingFolderChange()
C
CyrusNajmabadi 已提交
102
            {
103 104
                this.AssertIsForeground();

105
                _currentSolutionId = _workspace.CurrentSolution.Id;
106 107
                var solutionId = _currentSolutionId;

108
                UnregisterPrimarySolutionAsync(solutionId, synchronousShutdown: true).Wait();
C
CyrusNajmabadi 已提交
109 110 111 112
            }

            public void OnSolutionRemoved()
            {
113 114 115 116 117
                this.AssertIsForeground();

                // Have to use the cached solution ID we've got as the workspace will
                // no longer have a solution we can look at.
                var solutionId = _currentSolutionId;
C
CyrusNajmabadi 已提交
118
                _currentSolutionId = null;
119

120
                UnregisterPrimarySolutionAsync(solutionId, synchronousShutdown: false).Wait();
C
CyrusNajmabadi 已提交
121 122
            }

123
            private async Task UnregisterPrimarySolutionAsync(
124
                SolutionId solutionId, bool synchronousShutdown)
C
CyrusNajmabadi 已提交
125
            {
126
                await _client.TryRunRemoteAsync(
127
                    WellKnownRemoteHostServices.RemoteHostService, _workspace.CurrentSolution,
128 129
                    nameof(IRemoteHostService.UnregisterPrimarySolutionId), new object[] { solutionId, synchronousShutdown },
                    CancellationToken.None).ConfigureAwait(false);
C
CyrusNajmabadi 已提交
130 131 132 133 134
            }

            public void ClearSolution() { }
            public void OnAdditionalDocumentAdded(DocumentInfo documentInfo) { }
            public void OnAdditionalDocumentClosed(DocumentId documentId, ITextBuffer textBuffer, TextLoader loader) { }
135
            public void OnAdditionalDocumentOpened(DocumentId documentId, ITextBuffer textBuffer, bool isCurrentContext) { }
C
CyrusNajmabadi 已提交
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
            public void OnAdditionalDocumentRemoved(DocumentId documentInfo) { }
            public void OnAdditionalDocumentTextUpdatedOnDisk(DocumentId id) { }
            public void OnAnalyzerReferenceAdded(ProjectId projectId, AnalyzerReference analyzerReference) { }
            public void OnAnalyzerReferenceRemoved(ProjectId projectId, AnalyzerReference analyzerReference) { }
            public void OnAssemblyNameChanged(ProjectId id, string assemblyName) { }
            public void OnDocumentAdded(DocumentInfo documentInfo) { }
            public void OnDocumentClosed(DocumentId documentId, ITextBuffer textBuffer, TextLoader loader, bool updateActiveContext) { }
            public void OnDocumentOpened(DocumentId documentId, ITextBuffer textBuffer, bool isCurrentContext) { }
            public void OnDocumentRemoved(DocumentId documentId) { }
            public void OnDocumentTextUpdatedOnDisk(DocumentId id) { }
            public void OnMetadataReferenceAdded(ProjectId projectId, PortableExecutableReference metadataReference) { }
            public void OnMetadataReferenceRemoved(ProjectId projectId, PortableExecutableReference metadataReference) { }
            public void OnOptionsChanged(ProjectId projectId, CompilationOptions compilationOptions, ParseOptions parseOptions) { }
            public void OnOutputFilePathChanged(ProjectId id, string outputFilePath) { }
            public void OnProjectAdded(ProjectInfo projectInfo) { }
            public void OnProjectNameChanged(ProjectId projectId, string name, string filePath) { }
            public void OnProjectReferenceAdded(ProjectId projectId, ProjectReference projectReference) { }
            public void OnProjectReferenceRemoved(ProjectId projectId, ProjectReference projectReference) { }
            public void OnProjectRemoved(ProjectId projectId) { }
        }
    }
S
Sam Harwell 已提交
157
}