提交 0663b32e 编写于 作者: H Heejae Chang

fixed 2 bugs reported on primary workspace

1. filter out projects that is not supported in remote host when calculating checksum
2. wrong validation on contract

unit test added
上级 45458389
......@@ -58,6 +58,22 @@ public async Task TestRemoteHostSynchronize()
}
}
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public async Task TestUnknownProject()
{
var workspace = new AdhocWorkspace(TestHostServices.CreateHostServices());
var solution = workspace.CurrentSolution.AddProject("unknown", "unknown", NoCompilationConstants.LanguageName).Solution;
var client = (InProcRemoteHostClient)(await InProcRemoteHostClient.CreateAsync(workspace, runCacheCleanup: false, cancellationToken: CancellationToken.None));
await UpdatePrimaryWorkspace(client, solution);
VerifyAssetStorage(client, solution);
Assert.Equal(
await solution.State.GetChecksumAsync(CancellationToken.None),
await PrimaryWorkspace.Workspace.CurrentSolution.State.GetChecksumAsync(CancellationToken.None));
}
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public async Task TestRemoteHostSynchronizeIncrementalUpdate()
{
......
// 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;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
......@@ -137,6 +138,27 @@ public async Task TestUpdatePrimaryWorkspace()
{
var code = @"class Test { void Method() { } }";
await VerifySolutionUpdate(code, s => s.WithDocumentText(s.Projects.First().DocumentIds.First(), SourceText.From(code + " ")));
}
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public async Task TestUpdateProjectInfo()
{
var code = @"class Test { void Method() { } }";
await VerifySolutionUpdate(code, s => s.Projects.First().WithAssemblyName("test2").Solution);
}
[Fact, Trait(Traits.Feature, Traits.Features.RemoteHost)]
public async Task TestUpdateDocumentInfo()
{
var code = @"class Test { void Method() { } }";
await VerifySolutionUpdate(code, s => s.WithDocumentFolders(s.Projects.First().Documents.First().Id, new[] { "test" }));
}
private static async Task VerifySolutionUpdate(string code, Func<Solution, Solution> newSolutionGetter)
{
using (var workspace = await TestWorkspace.CreateCSharpAsync(code))
{
var map = new Dictionary<Checksum, object>();
......@@ -153,8 +175,8 @@ public async Task TestUpdatePrimaryWorkspace()
Assert.Equal(solutionChecksum, await first.State.GetChecksumAsync(CancellationToken.None));
Assert.True(object.ReferenceEquals(PrimaryWorkspace.Workspace.PrimaryBranchId, first.BranchId));
// change content
var newSolution = solution.WithDocumentText(solution.Projects.First().DocumentIds.First(), SourceText.From(code + " "));
// get new solution
var newSolution = newSolutionGetter(solution);
var newSolutionChecksum = await newSolution.State.GetChecksumAsync(CancellationToken.None);
newSolution.AppendAssetMap(map);
......
......@@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Remote;
using Microsoft.CodeAnalysis.Serialization;
using Xunit;
......@@ -44,7 +45,11 @@ public static void AppendAssetMap(this Solution solution, Dictionary<Checksum, o
private static void AppendAssetMap(Project project, Dictionary<Checksum, object> map)
{
ProjectStateChecksums projectChecksums;
Assert.True(project.State.TryGetStateChecksums(out projectChecksums));
if (!project.State.TryGetStateChecksums(out projectChecksums))
{
Assert.False(RemoteSupportedLanguages.Support(project.Language));
return;
}
projectChecksums.Find(project.State, Flatten(projectChecksums), map, CancellationToken.None);
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.CodeAnalysis.Remote
{
internal static class RemoteSupportedLanguages
{
public static bool Support(this string language)
{
return language == LanguageNames.CSharp ||
language == LanguageNames.VisualBasic;
}
}
}
......@@ -3,8 +3,9 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Serialization;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Remote;
using Microsoft.CodeAnalysis.Serialization;
namespace Microsoft.CodeAnalysis
{
......@@ -31,7 +32,9 @@ private async Task<SolutionStateChecksums> ComputeChecksumsAsync(CancellationTok
using (Logger.LogBlock(FunctionId.SolutionState_ComputeChecksumsAsync, FilePath, cancellationToken))
{
// get states by id order to have deterministic checksum
var projectChecksumTasks = ProjectIds.Select(id => ProjectStates[id].GetChecksumAsync(cancellationToken));
var projectChecksumTasks = ProjectIds.Select(id => ProjectStates[id])
.Where(s => RemoteSupportedLanguages.Support(s.Language))
.Select(s => s.GetChecksumAsync(cancellationToken));
var serializer = new Serializer(_solutionServices.Workspace);
var infoChecksum = serializer.CreateChecksum(SolutionInfo.Attributes, cancellationToken);
......
......@@ -3,7 +3,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Remote;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Serialization
......@@ -29,6 +29,7 @@ public SolutionStateChecksums(params object[] children) : base(nameof(SolutionSt
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
// verify input
Contract.ThrowIfFalse(state.TryGetStateChecksums(out var stateChecksum));
Contract.ThrowIfFalse(this == stateChecksum);
......@@ -51,8 +52,14 @@ public SolutionStateChecksums(params object[] children) : base(nameof(SolutionSt
foreach (var kv in state.ProjectStates)
{
var projectState = kv.Value;
// solution state checksum can't be created without project state checksums created first
Contract.ThrowIfFalse(projectState.TryGetStateChecksums(out var projectStateChecksums));
// check unsupported projects
if (!projectState.TryGetStateChecksums(out var projectStateChecksums))
{
Contract.ThrowIfTrue(RemoteSupportedLanguages.Support(projectState.Language));
continue;
}
projectStateChecksums.Find(projectState, searchingChecksumsLeft, result, cancellationToken);
if (searchingChecksumsLeft.Count == 0)
......
......@@ -384,6 +384,7 @@
<Compile Include="PatternMatching\PatternMatcher.TextChunk.cs" />
<Compile Include="PatternMatching\PatternMatches.cs" />
<Compile Include="PatternMatching\PatternMatchKind.cs" />
<Compile Include="Remote\RemoteSupportedLanguages.cs" />
<Compile Include="Shared\Extensions\SolutionExtensions.cs" />
<Compile Include="SymbolKey\SymbolKey.AnonymousFunctionOrDelegateSymbolKey.cs" />
<Compile Include="Tags\WellKnownTags.cs" />
......
......@@ -207,9 +207,9 @@ private async Task<Project> UpdateProjectInfoAsync(Project project, Checksum inf
var newProjectInfo = await _assetService.GetAssetAsync<ProjectInfo.ProjectAttributes>(infoChecksum, _cancellationToken).ConfigureAwait(false);
// there is no API to change these once project is created
Contract.ThrowIfFalse(project.State.ProjectInfo.Attributes.Id != newProjectInfo.Id);
Contract.ThrowIfFalse(project.State.ProjectInfo.Attributes.Language != newProjectInfo.Language);
Contract.ThrowIfFalse(project.State.ProjectInfo.Attributes.IsSubmission != newProjectInfo.IsSubmission);
Contract.ThrowIfFalse(project.State.ProjectInfo.Attributes.Id == newProjectInfo.Id);
Contract.ThrowIfFalse(project.State.ProjectInfo.Attributes.Language == newProjectInfo.Language);
Contract.ThrowIfFalse(project.State.ProjectInfo.Attributes.IsSubmission == newProjectInfo.IsSubmission);
if (project.State.ProjectInfo.Attributes.Name != newProjectInfo.Name)
{
......@@ -321,10 +321,10 @@ private async Task<Document> UpdateDocumentInfoAsync(Document document, Checksum
var newDocumentInfo = await _assetService.GetAssetAsync<DocumentInfo.DocumentAttributes>(infoChecksum, _cancellationToken).ConfigureAwait(false);
// there is no api to change these once document is created
Contract.ThrowIfFalse(document.State.Info.Attributes.Id != newDocumentInfo.Id);
Contract.ThrowIfFalse(document.State.Info.Attributes.Name != newDocumentInfo.Name);
Contract.ThrowIfFalse(document.State.Info.Attributes.FilePath != newDocumentInfo.FilePath);
Contract.ThrowIfFalse(document.State.Info.Attributes.IsGenerated != newDocumentInfo.IsGenerated);
Contract.ThrowIfFalse(document.State.Info.Attributes.Id == newDocumentInfo.Id);
Contract.ThrowIfFalse(document.State.Info.Attributes.Name == newDocumentInfo.Name);
Contract.ThrowIfFalse(document.State.Info.Attributes.FilePath == newDocumentInfo.FilePath);
Contract.ThrowIfFalse(document.State.Info.Attributes.IsGenerated == newDocumentInfo.IsGenerated);
if (document.State.Info.Attributes.Folders != newDocumentInfo.Folders)
{
......@@ -415,13 +415,15 @@ private async Task<ProjectInfo> CreateProjectInfoAsync(Checksum projectChecksum)
var projectSnapshot = await _assetService.GetAssetAsync<ProjectStateChecksums>(projectChecksum, _cancellationToken).ConfigureAwait(false);
var projectInfo = await _assetService.GetAssetAsync<ProjectInfo.ProjectAttributes>(projectSnapshot.Info, _cancellationToken).ConfigureAwait(false);
if (!_baseSolution.Workspace.Services.IsSupported(projectInfo.Language))
if (!RemoteSupportedLanguages.Support(projectInfo.Language))
{
// only add project our workspace supports.
// workspace doesn't allow creating project with unknown languages
return null;
}
Contract.ThrowIfFalse(_baseSolution.Workspace.Services.IsSupported(projectInfo.Language));
var compilationOptions = await _assetService.GetAssetAsync<CompilationOptions>(projectSnapshot.CompilationOptions, _cancellationToken).ConfigureAwait(false);
var parseOptions = await _assetService.GetAssetAsync<ParseOptions>(projectSnapshot.ParseOptions, _cancellationToken).ConfigureAwait(false);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册