提交 fb8b3793 编写于 作者: H Heejae Chang

removed API in service hub that internally play with data (options) in...

removed API in service hub that internally play with data (options) in workspace rather than solution snapshot.

now, like other features, analyzer uses snapshot of options rather than mutable one from Workspace.

eventually we should only use OptionSet snapshot embeded in solution rather than one in workspace.
上级 e846ff7a
......@@ -93,53 +93,6 @@ public async Task TestStrongNameProviderEmpty()
Assert.Equal(((XmlFileResolver)compilationOptions.XmlReferenceResolver).BaseDirectory, null);
}
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public async Task TestCreationWithOption()
{
var code = @"class Test { void Method() { } }";
using (var workspace = TestWorkspace.CreateCSharp(code))
{
var options = new TestOptionSet().WithChangedOption(RemoteHostOptions.RemoteHostTest, true);
var solution = workspace.CurrentSolution;
var service = await GetSolutionServiceAsync(solution);
var solutionChecksum = await solution.State.GetChecksumAsync(CancellationToken.None);
var synched = await service.GetSolutionAsync(solutionChecksum, options, CancellationToken.None);
Assert.Equal(solutionChecksum, await synched.State.GetChecksumAsync(CancellationToken.None));
Assert.Empty(options.GetChangedOptions(synched.Workspace.Options));
Assert.True(options.GetOption(RemoteHostOptions.RemoteHostTest));
Assert.True(synched.Workspace.Options.GetOption(RemoteHostOptions.RemoteHostTest));
}
}
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public async Task TestOptionIsolation()
{
var code = @"class Test { void Method() { } }";
using (var workspace = TestWorkspace.CreateCSharp(code))
{
var solution = workspace.CurrentSolution;
var service = await GetSolutionServiceAsync(solution);
var solutionChecksum = await solution.State.GetChecksumAsync(CancellationToken.None);
var options = new TestOptionSet().WithChangedOption(RemoteHostOptions.RemoteHostTest, true);
var first = await service.GetSolutionAsync(solutionChecksum, options, CancellationToken.None);
var second = await service.GetSolutionAsync(solutionChecksum, options.WithChangedOption(RemoteHostOptions.RemoteHostTest, false), CancellationToken.None);
Assert.Equal(await first.State.GetChecksumAsync(CancellationToken.None), await second.State.GetChecksumAsync(CancellationToken.None));
// option change shouldn't affect other workspace
Assert.True(first.Workspace.Options.GetOption(RemoteHostOptions.RemoteHostTest));
Assert.False(second.Workspace.Options.GetOption(RemoteHostOptions.RemoteHostTest));
}
}
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public async Task TestCache()
{
......@@ -161,36 +114,6 @@ public async Task TestCache()
}
}
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public async Task TestCacheWithOption()
{
var code = @"class Test { void Method() { } }";
using (var workspace = TestWorkspace.CreateCSharp(code))
{
var options = new TestOptionSet().WithChangedOption(RemoteHostOptions.RemoteHostTest, true);
var solution = workspace.CurrentSolution;
var service = await GetSolutionServiceAsync(solution);
var solutionChecksum = await solution.State.GetChecksumAsync(CancellationToken.None);
var first = await service.GetSolutionAsync(solutionChecksum, options, CancellationToken.None);
var second = await service.GetSolutionAsync(solutionChecksum, options, CancellationToken.None);
// new solutions if option is involved for isolation
Assert.False(object.ReferenceEquals(first, second));
// but semantic of both solution should be same
Assert.Equal(await first.State.GetChecksumAsync(CancellationToken.None), await second.State.GetChecksumAsync(CancellationToken.None));
// also any sub nodes such as projects should be same
Assert.True(object.ReferenceEquals(first.Projects.First().State, second.Projects.First().State));
Assert.True(first.Workspace is TemporaryWorkspace);
}
}
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public async Task TestUpdatePrimaryWorkspace()
{
......
......@@ -9,6 +9,7 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.Telemetry;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Workspaces.Diagnostics;
using Roslyn.Utilities;
......@@ -27,6 +28,7 @@ public DiagnosticComputer(Project project)
public async Task<DiagnosticAnalysisResultMap<string, DiagnosticAnalysisResultBuilder>> GetDiagnosticsAsync(
IEnumerable<AnalyzerReference> hostAnalyzers,
OptionSet options,
IEnumerable<string> analyzerIds,
bool reportSuppressedDiagnostics,
bool logAnalyzerExecutionTime,
......@@ -43,13 +45,14 @@ public DiagnosticComputer(Project project)
var cacheService = _project.Solution.Workspace.Services.GetService<IProjectCacheService>();
using (var cache = cacheService.EnableCaching(_project.Id))
{
return await AnalyzeAsync(analyzerMap, analyzers, reportSuppressedDiagnostics, logAnalyzerExecutionTime, cancellationToken).ConfigureAwait(false);
return await AnalyzeAsync(analyzerMap, analyzers, options, reportSuppressedDiagnostics, logAnalyzerExecutionTime, cancellationToken).ConfigureAwait(false);
}
}
private async Task<DiagnosticAnalysisResultMap<string, DiagnosticAnalysisResultBuilder>> AnalyzeAsync(
BidirectionalMap<string, DiagnosticAnalyzer> analyzerMap,
ImmutableArray<DiagnosticAnalyzer> analyzers,
OptionSet options,
bool reportSuppressedDiagnostics,
bool logAnalyzerExecutionTime,
CancellationToken cancellationToken)
......@@ -68,7 +71,7 @@ public DiagnosticComputer(Project project)
// TODO: can we support analyzerExceptionFilter in remote host?
// right now, host doesn't support watson, we might try to use new NonFatal watson API?
var analyzerOptions = new CompilationWithAnalyzersOptions(
options: new WorkspaceAnalyzerOptions(_project.AnalyzerOptions, _project.Solution.Workspace),
options: new WorkspaceAnalyzerOptions(_project.AnalyzerOptions, _project.Solution.Workspace, MergeOptions(_project.Solution.Options, options)),
onAnalyzerException: OnAnalyzerException,
analyzerExceptionFilter: null,
concurrentAnalysis: useConcurrent,
......@@ -140,5 +143,16 @@ private ImmutableArray<DiagnosticAnalyzer> GetAnalyzers(BidirectionalMap<string,
return new BidirectionalMap<string, DiagnosticAnalyzer>(
hostAnalyzers.Concat(project.AnalyzerReferences).SelectMany(r => r.GetAnalyzers(project.Language)).Select(a => KeyValuePair.Create(a.GetAnalyzerId(), a)));
}
private OptionSet MergeOptions(OptionSet workspaceOptions, OptionSet userOptions)
{
var newOptions = workspaceOptions;
foreach (var key in userOptions.GetChangedOptions(workspaceOptions))
{
newOptions = newOptions.WithChangedOption(key, userOptions.GetOption(key));
}
return newOptions;
}
}
}
......@@ -53,26 +53,6 @@ public async Task<Solution> GetSolutionAsync(Checksum solutionChecksum, Cancella
}
}
public async Task<Solution> GetSolutionAsync(Checksum solutionChecksum, OptionSet optionSet, CancellationToken cancellationToken)
{
// get solution
var baseSolution = await GetSolutionAsync(solutionChecksum, cancellationToken).ConfigureAwait(false);
if (optionSet == null)
{
return baseSolution;
}
// since options belong to workspace, we can't share solution
// create temporary workspace
var tempWorkspace = new TemporaryWorkspace(baseSolution);
// set merged options
tempWorkspace.Options = MergeOptions(tempWorkspace.Options, optionSet);
// return new solution
return tempWorkspace.CurrentSolution;
}
public async Task UpdatePrimaryWorkspaceAsync(Checksum solutionChecksum, CancellationToken cancellationToken)
{
var currentSolution = s_primaryWorkspace.CurrentSolution;
......@@ -91,17 +71,6 @@ public async Task UpdatePrimaryWorkspaceAsync(Checksum solutionChecksum, Cancell
}
}
private OptionSet MergeOptions(OptionSet workspaceOptions, OptionSet userOptions)
{
var newOptions = workspaceOptions;
foreach (var key in userOptions.GetChangedOptions(workspaceOptions))
{
newOptions = newOptions.WithChangedOption(key, userOptions.GetOption(key));
}
return newOptions;
}
private async Task<Solution> CreateSolution_NoLockAsync(Checksum solutionChecksum, Solution baseSolution, CancellationToken cancellationToken)
{
var updater = new SolutionCreator(_assetService, baseSolution, cancellationToken);
......
......@@ -27,16 +27,15 @@ public async Task CalculateDiagnosticsAsync(DiagnosticArguments arguments, strin
{
try
{
var optionSet = await RoslynServices.AssetService.GetAssetAsync<OptionSet>(arguments.OptionSetChecksum, CancellationToken).ConfigureAwait(false);
// entry point for diagnostic service
var solution = await GetSolutionWithSpecificOptionsAsync(optionSet).ConfigureAwait(false);
var solution = await GetSolutionAsync().ConfigureAwait(false);
var optionSet = await RoslynServices.AssetService.GetAssetAsync<OptionSet>(arguments.OptionSetChecksum, CancellationToken).ConfigureAwait(false);
var projectId = arguments.ProjectId;
var analyzers = RoslynServices.AssetService.GetGlobalAssetsOfType<AnalyzerReference>(CancellationToken);
var result = await (new DiagnosticComputer(solution.GetProject(projectId))).GetDiagnosticsAsync(
analyzers, arguments.AnalyzerIds, arguments.ReportSuppressedDiagnostics, arguments.LogAnalyzerExecutionTime, CancellationToken).ConfigureAwait(false);
analyzers, optionSet, arguments.AnalyzerIds, arguments.ReportSuppressedDiagnostics, arguments.LogAnalyzerExecutionTime, CancellationToken).ConfigureAwait(false);
await SerializeDiagnosticResultAsync(streamName, result).ConfigureAwait(false);
}
......
......@@ -93,12 +93,6 @@ protected Task<Solution> GetSolutionAsync()
return RoslynServices.SolutionService.GetSolutionAsync(_solutionChecksumOpt, CancellationToken);
}
protected Task<Solution> GetSolutionWithSpecificOptionsAsync(OptionSet options)
{
Contract.ThrowIfNull(_solutionChecksumOpt);
return RoslynServices.SolutionService.GetSolutionAsync(_solutionChecksumOpt, options, CancellationToken);
}
protected virtual void Dispose(bool disposing)
{
// do nothing here
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册