提交 a4a56e62 编写于 作者: D Drew Noakes

Prevent IDE0060 for serialization constructor

Extract test from AbstractRemoveUnusedMembersDiagnosticAnalyzer for use
in AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer via a new
SerializationConstructorCheck utility struct.

Fixes #32133
上级 3c319289
......@@ -979,6 +979,39 @@ public C(int [|p|])
}}");
}
[WorkItem(32133, "https://github.com/dotnet/roslyn/issues/32133")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedParameters)]
public async Task Parameter_SerializationConstructor()
{
await TestDiagnosticMissingAsync(
@"
using System;
using System.Runtime.Serialization;
internal sealed class NonSerializable
{
public NonSerializable(string value) => Value = value;
public string Value { get; set; }
}
[Serializable]
internal sealed class CustomSerializingType : ISerializable
{
private readonly NonSerializable _nonSerializable;
public CustomSerializingType(SerializationInfo info, StreamingContext [|context|])
{
_nonSerializable = new NonSerializable(info.GetString(""KEY""));
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue(""KEY"", _nonSerializable.Value);
}
}");
}
[ConditionalFact(typeof(IsEnglishLocal)), Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedParameters)]
public async Task Parameter_DiagnosticMessages()
{
......
......@@ -11,6 +11,7 @@
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
namespace Microsoft.CodeAnalysis.RemoveUnusedMembers
{
......@@ -64,7 +65,8 @@ private sealed class CompilationAnalyzer
private readonly object _gate;
private readonly Dictionary<ISymbol, ValueUsageInfo> _symbolValueUsageStateMap;
private readonly INamedTypeSymbol _taskType, _genericTaskType, _debuggerDisplayAttributeType, _structLayoutAttributeType;
private readonly INamedTypeSymbol _eventArgsType, _iSerializableType, _serializationInfoType, _streamingContextType;
private readonly INamedTypeSymbol _eventArgsType;
private readonly SerializationConstructorCheck _serializationConstructorCheck;
private readonly ImmutableHashSet<INamedTypeSymbol> _attributeSetForMethodsToIgnore;
private readonly AbstractRemoveUnusedMembersDiagnosticAnalyzer<TDocumentationCommentTriviaSyntax, TIdentifierNameSyntax> _analyzer;
......@@ -83,9 +85,7 @@ private sealed class CompilationAnalyzer
_debuggerDisplayAttributeType = compilation.DebuggerDisplayAttributeType();
_structLayoutAttributeType = compilation.StructLayoutAttributeType();
_eventArgsType = compilation.EventArgsType();
_iSerializableType = compilation.ISerializableType();
_serializationInfoType = compilation.SerializationInfoType();
_streamingContextType = compilation.StreamingContextType();
_serializationConstructorCheck = new SerializationConstructorCheck(compilation);
_attributeSetForMethodsToIgnore = ImmutableHashSet.CreateRange(GetAttributesForMethodsToIgnore(compilation));
}
......@@ -563,7 +563,7 @@ private bool IsCandidateSymbol(ISymbol memberSymbol)
// ISerializable constructor is invoked by the runtime for deserialization
// and it is a common pattern to have a private serialization constructor
// that is not explicitly referenced in code.
if (IsISerializableConstructor(methodSymbol))
if (_serializationConstructorCheck.IsISerializableConstructor(methodSymbol))
{
return false;
}
......@@ -680,13 +680,6 @@ bool IsSpecialMethodWithMatchingProperty(string prefix)
return false;
}
}
private bool IsISerializableConstructor(IMethodSymbol methodSymbol)
=> _iSerializableType != null &&
methodSymbol.Parameters.Length == 2 &&
methodSymbol.Parameters[0].Type.Equals(_serializationInfoType) &&
methodSymbol.Parameters[1].Type.Equals(_streamingContextType) &&
methodSymbol.ContainingType.AllInterfaces.Contains(_iSerializableType);
}
}
}
......@@ -10,6 +10,7 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.RemoveUnusedParametersAndValues
......@@ -22,6 +23,7 @@ private sealed partial class SymbolStartAnalyzer
private readonly INamedTypeSymbol _eventArgsTypeOpt;
private readonly ImmutableHashSet<INamedTypeSymbol> _attributeSetForMethodsToIgnore;
private readonly SerializationConstructorCheck _serializationConstructorCheck;
private readonly ConcurrentDictionary<IMethodSymbol, bool> _methodsUsedAsDelegates;
/// <summary>
......@@ -34,12 +36,14 @@ private sealed partial class SymbolStartAnalyzer
public SymbolStartAnalyzer(
AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer compilationAnalyzer,
INamedTypeSymbol eventArgsTypeOpt,
ImmutableHashSet<INamedTypeSymbol> attributeSetForMethodsToIgnore)
ImmutableHashSet<INamedTypeSymbol> attributeSetForMethodsToIgnore,
Compilation compilation)
{
_compilationAnalyzer = compilationAnalyzer;
_eventArgsTypeOpt = eventArgsTypeOpt;
_attributeSetForMethodsToIgnore = attributeSetForMethodsToIgnore;
_serializationConstructorCheck = new SerializationConstructorCheck(compilation);
_unusedParameters = new ConcurrentDictionary<IParameterSymbol, bool>();
_methodsUsedAsDelegates = new ConcurrentDictionary<IMethodSymbol, bool>();
}
......@@ -56,7 +60,7 @@ private sealed partial class SymbolStartAnalyzer
// to ensure there is no shared state (such as identified unused parameters within the type),
// as that would lead to duplicate diagnostics being reported from symbol end action callbacks
// for unrelated named types.
var symbolAnalyzer = new SymbolStartAnalyzer(analyzer, eventsArgType, attributeSetForMethodsToIgnore);
var symbolAnalyzer = new SymbolStartAnalyzer(analyzer, eventsArgType, attributeSetForMethodsToIgnore, context.Compilation);
symbolAnalyzer.OnSymbolStart(symbolStartContext);
}, SymbolKind.NamedType);
}
......@@ -191,7 +195,8 @@ private bool IsUnusedParameterCandidate(IParameterSymbol parameter)
!method.ExplicitOrImplicitInterfaceImplementations().IsEmpty ||
method.IsAccessor() ||
method.IsAnonymousFunction() ||
_compilationAnalyzer.MethodHasHandlesClause(method))
_compilationAnalyzer.MethodHasHandlesClause(method) ||
_serializationConstructorCheck.IsISerializableConstructor(method))
{
return false;
}
......
// 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 Microsoft.CodeAnalysis.Shared.Extensions;
namespace Microsoft.CodeAnalysis.Shared.Utilities
{
internal readonly struct SerializationConstructorCheck
{
private readonly INamedTypeSymbol _iSerializableType, _serializationInfoType, _streamingContextType;
public SerializationConstructorCheck(Compilation compilation)
{
_iSerializableType = compilation.ISerializableType();
_serializationInfoType = compilation.SerializationInfoType();
_streamingContextType = compilation.StreamingContextType();
}
// True if the method is a constructor adhereing to the pattern used for custom
// deserialisation by types that implement System.Runtime.Serialization.ISerializable
public bool IsISerializableConstructor(IMethodSymbol methodSymbol)
=> _iSerializableType != null &&
methodSymbol.MethodKind == MethodKind.Constructor &&
methodSymbol.Parameters.Length == 2 &&
methodSymbol.Parameters[0].Type.Equals(_serializationInfoType) &&
methodSymbol.Parameters[1].Type.Equals(_streamingContextType) &&
methodSymbol.ContainingType.AllInterfaces.Contains(_iSerializableType);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册