未验证 提交 0edd8ff5 编写于 作者: M Manish Vasani 提交者: GitHub

Merge pull request #42388 from mavasani/OptionsFix

Fix SerializableOptionSet to preserve option changes for unrelated la…
......@@ -76,6 +76,10 @@ internal sealed partial class SerializableOptionSet : OptionSet
{
}
/// <summary>
/// Returns an option set with all the serializable option values prefetched for given <paramref name="languages"/>,
/// while also retaining all the explicitly changed option values in this option set for any language.
/// </summary>
public SerializableOptionSet WithLanguages(ImmutableHashSet<string> languages)
{
if (_languages.SetEquals(languages))
......@@ -83,7 +87,22 @@ public SerializableOptionSet WithLanguages(ImmutableHashSet<string> languages)
return this;
}
return _workspaceOptionSet.OptionService.GetSerializableOptionsSnapshot(languages);
// First create a base option set for the given languages.
var newOptionSet = _workspaceOptionSet.OptionService.GetSerializableOptionsSnapshot(languages);
// Then apply all the changed options from the current option set to the new option set.
foreach (var changedOption in this.GetChangedOptions())
{
var valueInNewOptionSet = newOptionSet.GetOption(changedOption);
var changedValueInThisOptionSet = this.GetOption(changedOption);
if (!Equals(changedValueInThisOptionSet, valueInNewOptionSet))
{
newOptionSet = (SerializableOptionSet)newOptionSet.WithChangedOption(changedOption, changedValueInThisOptionSet);
}
}
return newOptionSet;
}
[PerformanceSensitive("https://github.com/dotnet/roslyn/issues/30819", AllowLocks = false)]
......@@ -120,8 +139,7 @@ public override OptionSet WithChangedOption(OptionKey optionKey, object? value)
}
var changedOptionKeys = _changedOptionKeys.Add(optionKey);
var languages = optionKey.Language != null ? _languages.Add(optionKey.Language) : _languages;
return new SerializableOptionSet(languages, workspaceOptionSet, _serializableOptions, serializableOptionValues, changedOptionKeys);
return new SerializableOptionSet(_languages, workspaceOptionSet, _serializableOptions, serializableOptionValues, changedOptionKeys);
}
/// <summary>
......
......@@ -15,9 +15,11 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
......@@ -2430,5 +2432,54 @@ public void AddingAndRemovingProjectsUpdatesFilePathMap()
LanguageNames.VisualBasic,
projectReferences: new[] { new ProjectReference(dependsOnVbNormalProject.Id) }));
}
[Fact, Trait(Traits.Feature, Traits.Features.Workspace)]
public void TestOptionChangesForLanguagesNotInSolution()
{
// Create an empty solution with no projects.
var s0 = CreateSolution();
var optionService = s0.Workspace.Services.GetRequiredService<IOptionService>();
// Apply an option change to a C# option.
var option = GenerationOptions.PlaceSystemNamespaceFirst;
var defaultValue = option.DefaultValue;
var changedValue = !defaultValue;
var options = s0.Options.WithChangedOption(option, LanguageNames.CSharp, changedValue);
// Verify option change is preserved even if the solution has no project with that language.
var s1 = s0.WithOptions(options);
VerifyOptionSet(s1.Options);
// Verify option value is preserved on adding a project for a different language.
var s2 = s1.AddProject("P1", "A1", LanguageNames.VisualBasic).Solution;
VerifyOptionSet(s2.Options);
// Verify option value is preserved on roundtriping the option set (serialize and deserialize).
var s3 = s2.AddProject("P2", "A2", LanguageNames.CSharp).Solution;
var roundTripOptionSet = SerializeAndDeserialize((SerializableOptionSet)s3.Options, optionService);
VerifyOptionSet(roundTripOptionSet);
// Verify option value is preserved on removing a project.
var s4 = s3.RemoveProject(s3.Projects.Single(p => p.Name == "P2").Id);
VerifyOptionSet(s4.Options);
return;
void VerifyOptionSet(OptionSet optionSet)
{
Assert.Equal(changedValue, optionSet.GetOption(option, LanguageNames.CSharp));
Assert.Equal(defaultValue, optionSet.GetOption(option, LanguageNames.VisualBasic));
}
static SerializableOptionSet SerializeAndDeserialize(SerializableOptionSet optionSet, IOptionService optionService)
{
using var stream = new MemoryStream();
using var writer = new ObjectWriter(stream);
optionSet.Serialize(writer, CancellationToken.None);
stream.Position = 0;
using var reader = ObjectReader.TryGetReader(stream);
return SerializableOptionSet.Deserialize(reader, optionService, CancellationToken.None);
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册