提交 52037991 编写于 作者: M Manish Vasani

Merge latest changes and resolve conflicts

......@@ -11,7 +11,7 @@
-->
<PropertyGroup>
<VersionPrefix>2.11.0</VersionPrefix>
<PreReleaseVersionLabel>beta1</PreReleaseVersionLabel>
<PreReleaseVersionLabel>beta2</PreReleaseVersionLabel>
<SemanticVersioningV1>true</SemanticVersioningV1>
<!--
......
......@@ -433,7 +433,7 @@ public async Task MethodIsUnused_Abstract()
await TestDiagnosticMissingAsync(
@"class C
{
private abstract void [|M|]();
protected abstract void [|M|]();
}");
}
......@@ -477,6 +477,26 @@ class C : I
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)]
[WorkItem(30965, "https://github.com/dotnet/roslyn/issues/30965")]
public async Task EventIsUnused_ExplicitInterfaceImplementation()
{
await TestDiagnosticMissingAsync(
@"interface I
{
event System.Action E;
}
class C : I
{
event System.Action [|I.E|]
{
add { }
remove { }
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)]
[WorkItem(30894, "https://github.com/dotnet/roslyn/issues/30894")]
public async Task WriteOnlyProperty_NotWritten()
......
......@@ -415,6 +415,22 @@ void AddDebuggerDisplayAttributeArgumentsCore(ISymbol symbol, ArrayBuilder<strin
}
}
/// <summary>
/// Returns true if the given symbol meets the following criteria to be
/// a candidate for dead code analysis:
/// 1. It is marked as "private".
/// 2. It is not an implicitly declared symbol.
/// 3. It is either a method, field, property or an event.
/// 4. If method, then one of the following must be true:
/// a. It is a constructor with non-zero parameters OR
/// b. It is a method with <see cref="MethodKind.Ordinary"/>,
/// such that it is not an accessor, not an entry point method,
/// not an extern method and is not an explicit interface method implementation.
/// 5. If field, then it must not be a backing field for an auto property.
/// Backing fields have a non-null <see cref="IFieldSymbol.AssociatedSymbol"/>.
/// 6. If property, then it must not be an explicit interface property implementation.
/// 7. If event, then it must not be an explicit interface event implementation.
/// </summary>
private bool IsCandidateSymbol(ISymbol memberSymbol)
{
Debug.Assert(memberSymbol == memberSymbol.OriginalDefinition);
......@@ -422,36 +438,28 @@ private bool IsCandidateSymbol(ISymbol memberSymbol)
if (memberSymbol.DeclaredAccessibility == Accessibility.Private &&
!memberSymbol.IsImplicitlyDeclared)
{
// Do not track accessors, as we will track the associated symbol.
switch (memberSymbol.Kind)
{
case SymbolKind.Method:
// Skip following methods:
// 1. Entry point (Main) method
// 2. Abstract/Virtual/Override methods
// 3. Extern methods
// 4. Interface implementation methods
// 5. Constructors with no parameters.
// 6. Static constructors.
// 7. Destructors.
var methodSymbol = (IMethodSymbol)memberSymbol;
switch (methodSymbol.MethodKind)
{
case MethodKind.Constructor:
// It is fine to have an unused private constructor
// without parameters.
// This is commonly used for static holder types
// that want to block instantiation of the type.
return methodSymbol.Parameters.Length > 0;
case MethodKind.StaticConstructor:
case MethodKind.Destructor:
return false;
default:
case MethodKind.Ordinary:
// Do not flag accessors, as we will track the associated symbol.
return methodSymbol.AssociatedSymbol == null &&
!IsEntryPoint(methodSymbol) &&
!methodSymbol.IsAbstract &&
!methodSymbol.IsVirtual &&
!methodSymbol.IsOverride &&
!methodSymbol.IsExtern &&
methodSymbol.ExplicitInterfaceImplementations.IsEmpty;
default:
return false;
}
case SymbolKind.Field:
......@@ -460,8 +468,8 @@ private bool IsCandidateSymbol(ISymbol memberSymbol)
case SymbolKind.Property:
return ((IPropertySymbol)memberSymbol).ExplicitInterfaceImplementations.IsEmpty;
default:
return true;
case SymbolKind.Event:
return ((IEventSymbol)memberSymbol).ExplicitInterfaceImplementations.IsEmpty;
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册