未验证 提交 9d7dcad1 编写于 作者: M msftbot[bot] 提交者: GitHub

Merge pull request #44151 from CyrusNajmabadi/serialization

Specialized serialization for options and naming preferences.
......@@ -4,12 +4,18 @@
using System;
using System.Xml.Linq;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeStyle
{
/// <inheritdoc cref="CodeStyleOption2{T}"/>
public class CodeStyleOption<T> : ICodeStyleOption, IEquatable<CodeStyleOption<T>>
{
static CodeStyleOption()
{
ObjectBinder.RegisterTypeReader(typeof(CodeStyleOption<T>), ReadFrom);
}
private readonly CodeStyleOption2<T> _codeStyleOptionImpl;
public static CodeStyleOption<T> Default => new CodeStyleOption<T>(default, NotificationOption.Silent);
......@@ -27,6 +33,7 @@ public T Value
set => _codeStyleOptionImpl.Value = value;
}
bool IObjectWritable.ShouldReuseInSerialization => _codeStyleOptionImpl.ShouldReuseInSerialization;
object ICodeStyleOption.Value => this.Value;
NotificationOption2 ICodeStyleOption.Notification => _codeStyleOptionImpl.Notification;
ICodeStyleOption ICodeStyleOption.WithValue(object value) => new CodeStyleOption<T>((T)value, Notification);
......@@ -48,6 +55,12 @@ public NotificationOption Notification
public static CodeStyleOption<T> FromXElement(XElement element)
=> new CodeStyleOption<T>(CodeStyleOption2<T>.FromXElement(element));
void IObjectWritable.WriteTo(ObjectWriter writer)
=> _codeStyleOptionImpl.WriteTo(writer);
internal static CodeStyleOption<object> ReadFrom(ObjectReader reader)
=> new CodeStyleOption<object>(CodeStyleOption2<T>.ReadFrom(reader));
public bool Equals(CodeStyleOption<T> other)
=> _codeStyleOptionImpl.Equals(other?._codeStyleOptionImpl);
......
......@@ -11,7 +11,6 @@
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Xml.Linq;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles;
using Roslyn.Utilities;
......@@ -206,12 +205,12 @@ public void Serialize(ObjectWriter writer, CancellationToken cancellationToken)
}
kind = OptionValueKind.CodeStyleOption;
valueToWrite = codeStyleOption.ToXElement().ToString();
valueToWrite = codeStyleOption;
break;
case NamingStylePreferences stylePreferences:
kind = OptionValueKind.NamingStylePreferences;
valueToWrite = stylePreferences.CreateXElement().ToString();
valueToWrite = stylePreferences;
break;
case string str:
......@@ -253,6 +252,11 @@ public void Serialize(ObjectWriter writer, CancellationToken cancellationToken)
RoslynDebug.Assert(value != null);
writer.WriteInt32((int)value);
}
else if (kind == OptionValueKind.CodeStyleOption || kind == OptionValueKind.NamingStylePreferences)
{
RoslynDebug.Assert(value != null);
((IObjectWritable)value).WriteTo(writer);
}
else
{
writer.WriteValue(value);
......@@ -308,7 +312,13 @@ public static SerializableOptionSet Deserialize(ObjectReader reader, IOptionServ
{
var optionKey = DeserializeOptionKey(reader, lookup);
var kind = (OptionValueKind)reader.ReadInt32();
var readValue = kind == OptionValueKind.Enum ? reader.ReadInt32() : reader.ReadValue();
var readValue = kind switch
{
OptionValueKind.Enum => reader.ReadInt32(),
OptionValueKind.CodeStyleOption => CodeStyleOption2<object>.ReadFrom(reader),
OptionValueKind.NamingStylePreferences => NamingStylePreferences.ReadFrom(reader),
_ => reader.ReadValue(),
};
if (optionKey == default ||
!serializableOptions.Contains(optionKey.Option))
......@@ -327,7 +337,7 @@ public static SerializableOptionSet Deserialize(ObjectReader reader, IOptionServ
continue;
}
var parsedCodeStyleOption = CodeStyleOption2<object>.FromXElement(XElement.Parse((string)readValue));
var parsedCodeStyleOption = (CodeStyleOption2<object>)readValue;
var value = parsedCodeStyleOption.Value;
var type = optionKey.Option.Type.GenericTypeArguments[0];
var convertedValue = type.IsEnum ? Enum.ToObject(type, value) : Convert.ChangeType(value, type);
......@@ -335,7 +345,7 @@ public static SerializableOptionSet Deserialize(ObjectReader reader, IOptionServ
break;
case OptionValueKind.NamingStylePreferences:
optionValue = NamingStylePreferences.FromXElement(XElement.Parse((string)readValue));
optionValue = (NamingStylePreferences)readValue;
break;
case OptionValueKind.Enum:
......
......@@ -6,10 +6,11 @@
using System.Collections.Generic;
using System.Xml.Linq;
using Microsoft.CodeAnalysis.Diagnostics;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeStyle
{
internal interface ICodeStyleOption
internal interface ICodeStyleOption : IObjectWritable
{
XElement ToXElement();
object Value { get; }
......@@ -38,6 +39,11 @@ internal interface ICodeStyleOption
/// </summary>
internal partial class CodeStyleOption2<T> : ICodeStyleOption, IEquatable<CodeStyleOption2<T>>
{
static CodeStyleOption2()
{
ObjectBinder.RegisterTypeReader(typeof(CodeStyleOption2<T>), ReadFrom);
}
public static CodeStyleOption2<T> Default => new CodeStyleOption2<T>(default, NotificationOption2.Silent);
private const int SerializationVersion = 1;
......@@ -153,6 +159,28 @@ public static CodeStyleOption2<T> FromXElement(XElement element)
});
}
public bool ShouldReuseInSerialization => false;
public void WriteTo(ObjectWriter writer)
{
writer.WriteValue(GetValueForSerialization());
writer.WriteInt32((int)(Notification.Severity.ToDiagnosticSeverity() ?? DiagnosticSeverity.Hidden));
}
public static CodeStyleOption2<object> ReadFrom(ObjectReader reader)
{
return new CodeStyleOption2<object>(
reader.ReadValue(),
(DiagnosticSeverity)reader.ReadInt32() switch
{
DiagnosticSeverity.Hidden => NotificationOption2.Silent,
DiagnosticSeverity.Info => NotificationOption2.Suggestion,
DiagnosticSeverity.Warning => NotificationOption2.Warning,
DiagnosticSeverity.Error => NotificationOption2.Error,
var v => throw ExceptionUtilities.UnexpectedValue(v),
});
}
private static Func<string, T> GetParser(string type)
=> type switch
{
......
......@@ -189,6 +189,7 @@
<Compile Include="$(MSBuildThisFileDirectory)EmbeddedLanguages\VirtualChars\VirtualCharSequence.Enumerator.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\CompilationExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\ListExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\ObjectWriterExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Services\Precedence\IPrecedenceService.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Services\Precedence\PrecedenceKind.cs" />
<Compile Include="$(MSBuildThisFileDirectory)CodeStyle\UnusedParametersPreference.cs" />
......
// 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.Immutable;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Shared.Extensions
{
internal static class ObjectWriterExtensions
{
public static void WriteArray<T>(this ObjectWriter writer, ImmutableArray<T> values, Action<ObjectWriter, T> write)
{
writer.WriteInt32(values.Length);
foreach (var val in values)
write(writer, val);
}
}
internal static class ObjectReaderExtensions
{
public static ImmutableArray<T> ReadArray<T>(this ObjectReader reader, Func<ObjectReader, T> read)
{
var length = reader.ReadInt32();
using var _ = ArrayBuilder<T>.GetInstance(length, out var builder);
for (var i = 0; i < length; i++)
builder.Add(read(reader));
return builder.ToImmutable();
}
}
}
......@@ -16,7 +16,7 @@
namespace Microsoft.CodeAnalysis.NamingStyles
{
internal partial struct NamingStyle : IEquatable<NamingStyle>
internal partial struct NamingStyle : IEquatable<NamingStyle>, IObjectWritable
{
public Guid ID { get; }
public string Name { get; }
......@@ -493,5 +493,28 @@ internal static NamingStyle FromXElement(XElement namingStyleElement)
suffix: namingStyleElement.Attribute(nameof(Suffix)).Value,
wordSeparator: namingStyleElement.Attribute(nameof(WordSeparator)).Value,
capitalizationScheme: (Capitalization)Enum.Parse(typeof(Capitalization), namingStyleElement.Attribute(nameof(CapitalizationScheme)).Value));
public bool ShouldReuseInSerialization => false;
public void WriteTo(ObjectWriter writer)
{
writer.WriteGuid(ID);
writer.WriteString(Name);
writer.WriteString(Prefix ?? string.Empty);
writer.WriteString(Suffix ?? string.Empty);
writer.WriteString(WordSeparator ?? string.Empty);
writer.WriteInt32((int)CapitalizationScheme);
}
public static NamingStyle ReadFrom(ObjectReader reader)
{
return new NamingStyle(
reader.ReadGuid(),
reader.ReadString(),
reader.ReadString(),
reader.ReadString(),
reader.ReadString(),
(Capitalization)reader.ReadInt32());
}
}
}
......@@ -8,6 +8,7 @@
using System.Linq;
using System.Xml.Linq;
using Microsoft.CodeAnalysis.NamingStyles;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles
......@@ -18,8 +19,13 @@ namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles
/// 2. Name Style
/// 3. Naming Rule (points to Symbol Specification IDs)
/// </summary>
internal sealed class NamingStylePreferences : IEquatable<NamingStylePreferences>
internal sealed class NamingStylePreferences : IEquatable<NamingStylePreferences>, IObjectWritable
{
static NamingStylePreferences()
{
ObjectBinder.RegisterTypeReader(typeof(NamingStylePreferences), ReadFrom);
}
private const int s_serializationVersion = 5;
public readonly ImmutableArray<SymbolSpecification> SymbolSpecifications;
......@@ -77,6 +83,23 @@ internal static NamingStylePreferences FromXElement(XElement element)
.Select(SerializableNamingRule.FromXElement).ToImmutableArray());
}
public bool ShouldReuseInSerialization => false;
public void WriteTo(ObjectWriter writer)
{
writer.WriteArray(SymbolSpecifications, (w, v) => v.WriteTo(w));
writer.WriteArray(NamingStyles, (w, v) => v.WriteTo(w));
writer.WriteArray(NamingRules, (w, v) => v.WriteTo(w));
}
public static NamingStylePreferences ReadFrom(ObjectReader reader)
{
return new NamingStylePreferences(
reader.ReadArray(r => SymbolSpecification.ReadFrom(r)),
reader.ReadArray(r => NamingStyle.ReadFrom(r)),
reader.ReadArray(r => SerializableNamingRule.ReadFrom(r)));
}
public override bool Equals(object obj)
=> Equals(obj as NamingStylePreferences);
......
......@@ -8,7 +8,7 @@
namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles
{
internal sealed class SerializableNamingRule : IEquatable<SerializableNamingRule>
internal sealed class SerializableNamingRule : IEquatable<SerializableNamingRule>, IObjectWritable
{
public Guid SymbolSpecificationID;
public Guid NamingStyleID;
......@@ -42,6 +42,25 @@ internal static SerializableNamingRule FromXElement(XElement namingRuleElement)
};
}
public bool ShouldReuseInSerialization => false;
public void WriteTo(ObjectWriter writer)
{
writer.WriteGuid(SymbolSpecificationID);
writer.WriteGuid(NamingStyleID);
writer.WriteInt32((int)(EnforcementLevel.ToDiagnosticSeverity() ?? DiagnosticSeverity.Hidden));
}
public static SerializableNamingRule ReadFrom(ObjectReader reader)
{
return new SerializableNamingRule
{
SymbolSpecificationID = reader.ReadGuid(),
NamingStyleID = reader.ReadGuid(),
EnforcementLevel = ((DiagnosticSeverity)reader.ReadInt32()).ToReportDiagnostic(),
};
}
public override bool Equals(object obj)
{
return Equals(obj as SerializableNamingRule);
......
......@@ -19,7 +19,7 @@
namespace Microsoft.CodeAnalysis.Diagnostics.Analyzers.NamingStyles
{
internal sealed class SymbolSpecification : IEquatable<SymbolSpecification>
internal sealed class SymbolSpecification : IEquatable<SymbolSpecification>, IObjectWritable
{
private static readonly SymbolSpecification DefaultSymbolSpecificationTemplate = CreateDefaultSymbolSpecification();
......@@ -218,6 +218,27 @@ internal XElement CreateXElement()
CreateModifiersXElement());
}
public bool ShouldReuseInSerialization => false;
public void WriteTo(ObjectWriter writer)
{
writer.WriteGuid(ID);
writer.WriteString(Name);
writer.WriteArray(ApplicableSymbolKindList, (w, v) => v.WriteTo(w));
writer.WriteArray(ApplicableAccessibilityList, (w, v) => w.WriteInt32((int)v));
writer.WriteArray(RequiredModifierList, (w, v) => v.WriteTo(w));
}
public static SymbolSpecification ReadFrom(ObjectReader reader)
{
return new SymbolSpecification(
reader.ReadGuid(),
reader.ReadString(),
reader.ReadArray(r => SymbolKindOrTypeKind.ReadFrom(r)),
reader.ReadArray(r => (Accessibility)r.ReadInt32()),
reader.ReadArray(r => ModifierKind.ReadFrom(r)));
}
private XElement CreateSymbolKindsXElement()
{
var symbolKindsElement = new XElement(nameof(ApplicableSymbolKindList));
......@@ -309,7 +330,7 @@ private interface ISymbolMatcher
bool MatchesSymbol(ISymbol symbol);
}
public struct SymbolKindOrTypeKind : IEquatable<SymbolKindOrTypeKind>, ISymbolMatcher
public struct SymbolKindOrTypeKind : IEquatable<SymbolKindOrTypeKind>, ISymbolMatcher, IObjectWritable
{
public SymbolKind? SymbolKind { get; }
public TypeKind? TypeKind { get; }
......@@ -348,6 +369,43 @@ internal XElement CreateXElement()
MethodKind.HasValue ? new XElement(nameof(MethodKind), MethodKind) :
throw ExceptionUtilities.Unreachable;
public bool ShouldReuseInSerialization => false;
public void WriteTo(ObjectWriter writer)
{
if (SymbolKind != null)
{
writer.WriteInt32(1);
writer.WriteInt32((int)SymbolKind);
}
else if (TypeKind != null)
{
writer.WriteInt32(2);
writer.WriteInt32((int)TypeKind);
}
else if (MethodKind != null)
{
writer.WriteInt32(3);
writer.WriteInt32((int)MethodKind);
}
else
{
writer.WriteInt32(0);
}
}
public static SymbolKindOrTypeKind ReadFrom(ObjectReader reader)
{
return reader.ReadInt32() switch
{
0 => default,
1 => new SymbolKindOrTypeKind((SymbolKind)reader.ReadInt32()),
2 => new SymbolKindOrTypeKind((TypeKind)reader.ReadInt32()),
3 => new SymbolKindOrTypeKind((MethodKind)reader.ReadInt32()),
var v => throw ExceptionUtilities.UnexpectedValue(v),
};
}
internal static SymbolKindOrTypeKind AddSymbolKindFromXElement(XElement symbolKindElement)
=> new SymbolKindOrTypeKind((SymbolKind)Enum.Parse(typeof(SymbolKind), symbolKindElement.Value));
......@@ -370,7 +428,7 @@ public override int GetHashCode()
}
}
public struct ModifierKind : ISymbolMatcher, IEquatable<ModifierKind>
public struct ModifierKind : ISymbolMatcher, IEquatable<ModifierKind>, IObjectWritable
{
public ModifierKindEnum ModifierKindWrapper;
......@@ -458,6 +516,14 @@ internal XElement CreateXElement()
internal static ModifierKind FromXElement(XElement modifierElement)
=> new ModifierKind((ModifierKindEnum)Enum.Parse(typeof(ModifierKindEnum), modifierElement.Value));
public bool ShouldReuseInSerialization => false;
public void WriteTo(ObjectWriter writer)
=> writer.WriteInt32((int)ModifierKindWrapper);
public static ModifierKind ReadFrom(ObjectReader reader)
=> new ModifierKind((ModifierKindEnum)reader.ReadInt32());
public override bool Equals(object obj)
=> obj is ModifierKind kind && Equals(kind);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册