-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #65592 from jasonmalinowski/introduce-brokered-ser…
…vice-for-project-system Implement a new brokered service for passing project information
- Loading branch information
Showing
12 changed files
with
319 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
146 changes: 146 additions & 0 deletions
146
src/VisualStudio/Core/Def/ProjectSystem/BrokeredService/WorkspaceProject.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
// 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.Collections.Immutable; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.Remote.ProjectSystem; | ||
using Roslyn.Utilities; | ||
|
||
namespace Microsoft.VisualStudio.LanguageServices.ProjectSystem.BrokeredService | ||
{ | ||
internal sealed class WorkspaceProject : IWorkspaceProject | ||
{ | ||
// For the sake of the in-proc implementation here, we're going to build this atop IWorkspaceProjectContext so semantics are preserved | ||
// for a few edge cases. Once the project system has moved onto this directly, we can flatten the implementations out. | ||
private readonly IWorkspaceProjectContext _project; | ||
|
||
public WorkspaceProject(IWorkspaceProjectContext project) | ||
{ | ||
_project = project; | ||
} | ||
|
||
public ValueTask DisposeAsync() | ||
{ | ||
_project.Dispose(); | ||
return ValueTaskFactory.CompletedTask; | ||
} | ||
|
||
public async Task AddAdditionalFilesAsync(IReadOnlyList<string> additionalFilePaths, CancellationToken cancellationToken) | ||
{ | ||
await using var batch = _project.CreateBatchScope().ConfigureAwait(false); | ||
|
||
foreach (var additionalFilePath in additionalFilePaths) | ||
_project.AddAdditionalFile(additionalFilePath); | ||
} | ||
|
||
public async Task RemoveAdditionalFilesAsync(IReadOnlyList<string> additionalFilePaths, CancellationToken cancellationToken) | ||
{ | ||
await using var batch = _project.CreateBatchScope().ConfigureAwait(false); | ||
|
||
foreach (var additionalFilePath in additionalFilePaths) | ||
_project.RemoveAdditionalFile(additionalFilePath); | ||
} | ||
|
||
public async Task AddAnalyzerConfigFilesAsync(IReadOnlyList<string> analyzerConfigPaths, CancellationToken cancellationToken) | ||
{ | ||
await using var batch = _project.CreateBatchScope().ConfigureAwait(false); | ||
|
||
foreach (var analyzerConfigPath in analyzerConfigPaths) | ||
_project.AddAnalyzerConfigFile(analyzerConfigPath); | ||
} | ||
public async Task RemoveAnalyzerConfigFilesAsync(IReadOnlyList<string> analyzerConfigPaths, CancellationToken cancellationToken) | ||
{ | ||
await using var batch = _project.CreateBatchScope().ConfigureAwait(false); | ||
|
||
foreach (var analyzerConfigPath in analyzerConfigPaths) | ||
_project.RemoveAnalyzerConfigFile(analyzerConfigPath); | ||
} | ||
|
||
public async Task AddAnalyzerReferencesAsync(IReadOnlyList<string> analyzerPaths, CancellationToken cancellationToken) | ||
{ | ||
await using var batch = _project.CreateBatchScope().ConfigureAwait(false); | ||
|
||
foreach (var analyzerPath in analyzerPaths) | ||
_project.AddAnalyzerReference(analyzerPath); | ||
} | ||
|
||
public async Task RemoveAnalyzerReferencesAsync(IReadOnlyList<string> analyzerPaths, CancellationToken cancellationToken) | ||
{ | ||
await using var batch = _project.CreateBatchScope().ConfigureAwait(false); | ||
|
||
foreach (var analyzerPath in analyzerPaths) | ||
_project.RemoveAnalyzerReference(analyzerPath); | ||
} | ||
|
||
public async Task AddMetadataReferencesAsync(IReadOnlyList<MetadataReferenceInfo> metadataReferences, CancellationToken cancellationToken) | ||
{ | ||
await using var batch = _project.CreateBatchScope().ConfigureAwait(false); | ||
|
||
foreach (var metadataReference in metadataReferences) | ||
{ | ||
_project.AddMetadataReference( | ||
metadataReference.FilePath, | ||
new MetadataReferenceProperties(MetadataImageKind.Assembly, default, metadataReference.EmbedInteropTypes)); | ||
} | ||
} | ||
|
||
public async Task RemoveMetadataReferencesAsync(IReadOnlyList<MetadataReferenceInfo> metadataReferences, CancellationToken cancellationToken) | ||
{ | ||
await using var batch = _project.CreateBatchScope().ConfigureAwait(false); | ||
|
||
// The existing IWorkspaceProjectContext API here is a bit odd in that it only looks at the file path, and trusts that there aren't two | ||
// references with the same path but different properties. | ||
foreach (var metadataReference in metadataReferences) | ||
_project.RemoveMetadataReference(metadataReference.FilePath); | ||
} | ||
|
||
public async Task AddSourceFilesAsync(IReadOnlyList<SourceFileInfo> sourceFiles, CancellationToken cancellationToken) | ||
{ | ||
await using var batch = _project.CreateBatchScope().ConfigureAwait(false); | ||
|
||
foreach (var sourceFile in sourceFiles) | ||
{ | ||
_project.AddSourceFile( | ||
sourceFile.FilePath, | ||
folderNames: sourceFile.FolderNames); | ||
} | ||
} | ||
public async Task RemoveSourceFilesAsync(IReadOnlyList<string> sourceFiles, CancellationToken cancellationToken) | ||
{ | ||
await using var batch = _project.CreateBatchScope().ConfigureAwait(false); | ||
|
||
foreach (var sourceFile in sourceFiles) | ||
_project.RemoveSourceFile(sourceFile); | ||
} | ||
|
||
public async Task SetBuildSystemPropertiesAsync(IReadOnlyDictionary<string, string> properties, CancellationToken cancellationToken) | ||
{ | ||
await using var batch = _project.CreateBatchScope().ConfigureAwait(false); | ||
|
||
foreach (var property in properties) | ||
_project.SetProperty(property.Key, property.Value); | ||
} | ||
|
||
public Task SetCommandLineArgumentsAsync(IReadOnlyList<string> arguments, CancellationToken cancellationToken) | ||
{ | ||
_project.SetOptions(arguments.ToImmutableArray()); | ||
return Task.CompletedTask; | ||
} | ||
|
||
public Task SetDisplayNameAsync(string displayName, CancellationToken cancellationToken) | ||
{ | ||
_project.DisplayName = displayName; | ||
return Task.CompletedTask; | ||
} | ||
|
||
public Task<IAsyncDisposable> StartBatchAsync(CancellationToken cancellationToken) | ||
{ | ||
return Task.FromResult(_project.CreateBatchScope()); | ||
} | ||
} | ||
} |
64 changes: 64 additions & 0 deletions
64
src/VisualStudio/Core/Def/ProjectSystem/BrokeredService/WorkspaceProjectFactoryService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// 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.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using Microsoft.CodeAnalysis.Remote; | ||
using Microsoft.CodeAnalysis.Remote.ProjectSystem; | ||
using Microsoft.ServiceHub.Framework; | ||
|
||
namespace Microsoft.VisualStudio.LanguageServices.ProjectSystem.BrokeredService | ||
{ | ||
internal class WorkspaceProjectFactoryService : IWorkspaceProjectFactoryService | ||
{ | ||
public const string ServiceName = "WorkspaceProjectFactoryService"; | ||
public static readonly ServiceDescriptor ServiceDescriptor = ServiceDescriptor.CreateInProcServiceDescriptor(ServiceDescriptors.ComponentName, ServiceName, suffix: "", ServiceDescriptors.GetFeatureDisplayName); | ||
|
||
private readonly IWorkspaceProjectContextFactory _workspaceProjectContextFactory; | ||
|
||
// For the sake of the in-proc implementation here, we're going to build this atop IWorkspaceProjectContext so semantics are preserved | ||
// for a few edge cases. Once the project system has moved onto this directly, we can flatten the implementations out. | ||
public WorkspaceProjectFactoryService(IWorkspaceProjectContextFactory workspaceProjectContextFactory) | ||
{ | ||
_workspaceProjectContextFactory = workspaceProjectContextFactory; | ||
} | ||
|
||
public async Task<IWorkspaceProject> CreateAndAddProjectAsync(WorkspaceProjectCreationInfo creationInfo, CancellationToken cancellationToken) | ||
{ | ||
var project = await _workspaceProjectContextFactory.CreateProjectContextAsync( | ||
Guid.NewGuid(), // TODO: figure out some other side-channel way of communicating this | ||
creationInfo.DisplayName, | ||
creationInfo.Language, | ||
new EvaluationDataShim(creationInfo.BuildSystemProperties), | ||
hostObject: null, // TODO: figure out some other side-channel way of communicating this | ||
cancellationToken).ConfigureAwait(false); | ||
|
||
return new WorkspaceProject(project); | ||
} | ||
|
||
public Task<IReadOnlyCollection<string>> GetSupportedBuildSystemPropertiesAsync(CancellationToken cancellationToken) | ||
{ | ||
return Task.FromResult((IReadOnlyCollection<string>)_workspaceProjectContextFactory.EvaluationItemNames); | ||
} | ||
|
||
private sealed class EvaluationDataShim : EvaluationData | ||
{ | ||
private readonly IReadOnlyDictionary<string, string> _buildSystemProperties; | ||
|
||
public EvaluationDataShim(IReadOnlyDictionary<string, string> buildSystemProperties) | ||
{ | ||
_buildSystemProperties = buildSystemProperties; | ||
} | ||
|
||
public override string GetPropertyValue(string name) | ||
{ | ||
return _buildSystemProperties.TryGetValue(name, out var value) ? value : ""; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
src/Workspaces/Remote/Core/ProjectSystem/IWorkspaceProject.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// 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.Threading; | ||
using System.Threading.Tasks; | ||
using StreamJsonRpc; | ||
|
||
namespace Microsoft.CodeAnalysis.Remote.ProjectSystem; | ||
|
||
[RpcMarshalable] | ||
internal interface IWorkspaceProject : IAsyncDisposable | ||
{ | ||
Task SetDisplayNameAsync(string displayName, CancellationToken cancellationToken); | ||
|
||
Task SetCommandLineArgumentsAsync(IReadOnlyList<string> arguments, CancellationToken cancellationToken); | ||
Task SetBuildSystemPropertiesAsync(IReadOnlyDictionary<string, string> properties, CancellationToken cancellationToken); | ||
|
||
Task AddSourceFilesAsync(IReadOnlyList<SourceFileInfo> sourceFiles, CancellationToken cancellationToken); | ||
Task RemoveSourceFilesAsync(IReadOnlyList<string> sourceFiles, CancellationToken cancellationToken); | ||
|
||
Task AddMetadataReferencesAsync(IReadOnlyList<MetadataReferenceInfo> metadataReferences, CancellationToken cancellationToken); | ||
Task RemoveMetadataReferencesAsync(IReadOnlyList<MetadataReferenceInfo> metadataReferences, CancellationToken cancellationToken); | ||
|
||
Task AddAdditionalFilesAsync(IReadOnlyList<string> additionalFilePaths, CancellationToken cancellationToken); | ||
Task RemoveAdditionalFilesAsync(IReadOnlyList<string> additionalFilePaths, CancellationToken cancellationToken); | ||
|
||
Task AddAnalyzerReferencesAsync(IReadOnlyList<string> analyzerPaths, CancellationToken cancellationToken); | ||
Task RemoveAnalyzerReferencesAsync(IReadOnlyList<string> analyzerPaths, CancellationToken cancellationToken); | ||
|
||
Task AddAnalyzerConfigFilesAsync(IReadOnlyList<string> analyzerConfigPaths, CancellationToken cancellationToken); | ||
Task RemoveAnalyzerConfigFilesAsync(IReadOnlyList<string> analyzerConfigPaths, CancellationToken cancellationToken); | ||
|
||
Task<IAsyncDisposable> StartBatchAsync(CancellationToken cancellationToken); | ||
} |
24 changes: 24 additions & 0 deletions
24
src/Workspaces/Remote/Core/ProjectSystem/IWorkspaceProjectFactoryService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// 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.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace Microsoft.CodeAnalysis.Remote.ProjectSystem; | ||
|
||
internal interface IWorkspaceProjectFactoryService | ||
{ | ||
Task<IWorkspaceProject> CreateAndAddProjectAsync(WorkspaceProjectCreationInfo creationInfo, CancellationToken cancellationToken); | ||
|
||
/// <summary> | ||
/// Returns the list of properties that are understood by the language service and can be passed to | ||
/// <see cref="IWorkspaceProject.SetBuildSystemPropertiesAsync(IReadOnlyDictionary{string, string}, CancellationToken)"/> and to | ||
/// <see cref="WorkspaceProjectCreationInfo.BuildSystemProperties"/>. | ||
/// </summary> | ||
Task<IReadOnlyCollection<string>> GetSupportedBuildSystemPropertiesAsync(CancellationToken cancellationToken); | ||
} |
7 changes: 7 additions & 0 deletions
7
src/Workspaces/Remote/Core/ProjectSystem/MetadataReferenceInfo.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// 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. | ||
|
||
namespace Microsoft.CodeAnalysis.Remote.ProjectSystem; | ||
|
||
internal readonly record struct MetadataReferenceInfo(string FilePath, string Aliases, bool EmbedInteropTypes); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// 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.Generic; | ||
|
||
namespace Microsoft.CodeAnalysis.Remote.ProjectSystem; | ||
|
||
internal readonly record struct SourceFileInfo(string FilePath, IReadOnlyList<string> FolderNames); |
9 changes: 9 additions & 0 deletions
9
src/Workspaces/Remote/Core/ProjectSystem/WorkspaceProjectCreationInfo.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// 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.Generic; | ||
|
||
namespace Microsoft.CodeAnalysis.Remote.ProjectSystem; | ||
|
||
internal record WorkspaceProjectCreationInfo(string Language, string DisplayName, string? FilePath, IReadOnlyDictionary<string, string> BuildSystemProperties); |