提交 36bfae18 编写于 作者: M Manish Vasani

Address PR feedback and also handle few more cases identified during dogfooding:

1. Bail out for explicit interface implementations for properties, we only did so for methods.
2. Bail out for types with StructLayoutAttribute
3. Conservatively handle member references inside DebuggerDisplayAttribute argument by doing a simple string contains check.
上级 ae2428eb
...@@ -457,6 +457,21 @@ class C : I ...@@ -457,6 +457,21 @@ class C : I
}"); }");
} }
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)]
public async Task PropertyIsUnused_ExplicitInterfaceImplementation()
{
await TestMissingInRegularAndScriptAsync(
@"interface I
{
int P { get; set; }
}
class C : I
{
int I.[|P|] { get { return 0; } set { } }
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)]
public async Task FieldIsUnused_Const() public async Task FieldIsUnused_Const()
{ {
...@@ -1707,6 +1722,125 @@ class C2 ...@@ -1707,6 +1722,125 @@ class C2
}"); }");
} }
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)]
public async Task StructLayoutAttribute_ExplicitLayout()
{
await TestMissingInRegularAndScriptAsync(
@"using System.Runtime.InteropServices;
[StructLayoutAttribute(LayoutKind.Explicit)]
class C
{
[FieldOffset(0)]
private int [|i|];
[FieldOffset(4)]
private int i2;
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)]
public async Task StructLayoutAttribute_SequentialLayout()
{
await TestMissingInRegularAndScriptAsync(
@"using System.Runtime.InteropServices;
[StructLayoutAttribute(LayoutKind.Sequential)]
struct S
{
private int [|i|];
private int i2;
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)]
public async Task DebuggerDisplayAttribute_OnType_ReferencesField()
{
await TestMissingInRegularAndScriptAsync(
@"[System.Diagnostics.DebuggerDisplayAttribute(""{s}"")]
class C
{
private string [|s|];
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)]
public async Task DebuggerDisplayAttribute_OnType_ReferencesMethod()
{
await TestMissingInRegularAndScriptAsync(
@"[System.Diagnostics.DebuggerDisplayAttribute(""{GetString()}"")]
class C
{
private string [|GetString|]() => """";
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)]
public async Task DebuggerDisplayAttribute_OnType_ReferencesProperty()
{
await TestMissingInRegularAndScriptAsync(
@"[System.Diagnostics.DebuggerDisplayAttribute(""{MyString}"")]
class C
{
private string [|MyString|] => """";
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)]
public async Task DebuggerDisplayAttribute_OnField_ReferencesField()
{
await TestMissingInRegularAndScriptAsync(
@"class C
{
private string [|s|];
[System.Diagnostics.DebuggerDisplayAttribute(""{s}"")]
public int M;
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)]
public async Task DebuggerDisplayAttribute_OnProperty_ReferencesMethod()
{
await TestMissingInRegularAndScriptAsync(
@"class C
{
private string [|GetString|]() => """";
[System.Diagnostics.DebuggerDisplayAttribute(""{GetString()}"")]
public int M => 0;
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)]
public async Task DebuggerDisplayAttribute_OnProperty_ReferencesProperty()
{
await TestMissingInRegularAndScriptAsync(
@"class C
{
private string [|MyString|] { get { return """"; } }
[System.Diagnostics.DebuggerDisplayAttribute(""{MyString}"")]
public int M { get { return 0; } }
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)]
public async Task DebuggerDisplayAttribute_OnNestedTypeMember_ReferencesField()
{
await TestMissingInRegularAndScriptAsync(
@"class C
{
private static string [|s|];
class Nested
{
[System.Diagnostics.DebuggerDisplayAttribute(""{C.s}"")]
public int M;
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)]
public async Task FixAllFields_Document() public async Task FixAllFields_Document()
{ {
......
// 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.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeQuality
{
internal abstract class AbstractCodeQualityDiagnosticAnalyzer : DiagnosticAnalyzer, IBuiltInAnalyzer
{
private readonly GeneratedCodeAnalysisFlags _generatedCodeAnalysisFlags;
private readonly bool _enableConcurrentExecution;
protected AbstractCodeQualityDiagnosticAnalyzer(
ImmutableArray<DiagnosticDescriptor> descriptors,
GeneratedCodeAnalysisFlags generatedCodeAnalysisFlags,
bool enableConcurrentExecution)
{
SupportedDiagnostics = descriptors;
_generatedCodeAnalysisFlags = generatedCodeAnalysisFlags;
_enableConcurrentExecution = enableConcurrentExecution;
}
public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; }
public sealed override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(_generatedCodeAnalysisFlags);
if (_enableConcurrentExecution)
{
context.EnableConcurrentExecution();
}
InitializeWorker(context);
}
protected abstract void InitializeWorker(AnalysisContext context);
public abstract DiagnosticAnalyzerCategory GetAnalyzerCategory();
public abstract bool OpenFileOnly(Workspace workspace);
protected static DiagnosticDescriptor CreateDescriptor(
string id,
LocalizableString title,
LocalizableString messageFormat,
bool isUnneccessary,
bool isEnabledByDefault = true,
bool isConfigurable = true,
params string[] customTags)
{
var customTagsBuilder = ArrayBuilder<string>.GetInstance();
customTagsBuilder.AddRange(customTags.Concat(WellKnownDiagnosticTags.Telemetry));
if (!isConfigurable)
{
customTagsBuilder.Add(WellKnownDiagnosticTags.NotConfigurable);
}
if (isUnneccessary)
{
customTagsBuilder.Add(WellKnownDiagnosticTags.Unnecessary);
}
return new DiagnosticDescriptor(
id, title, messageFormat,
DiagnosticCategory.CodeQuality,
DiagnosticSeverity.Info,
isEnabledByDefault,
customTags: customTagsBuilder.ToArrayAndFree());
}
}
}
...@@ -5,7 +5,7 @@ namespace Microsoft.CodeAnalysis.Diagnostics ...@@ -5,7 +5,7 @@ namespace Microsoft.CodeAnalysis.Diagnostics
internal static class DiagnosticCategory internal static class DiagnosticCategory
{ {
public static readonly string Style = FeaturesResources.Style; public static readonly string Style = FeaturesResources.Style;
public static readonly string CodeQuality = FeaturesResources.CodeQuality; public static readonly string CodeQuality = FeaturesResources.Code_Quality;
public static readonly string EditAndContinue = FeaturesResources.Edit_and_Continue2; public static readonly string EditAndContinue = FeaturesResources.Edit_and_Continue2;
public static readonly string Compiler = FeaturesResources.Compiler1; public static readonly string Compiler = FeaturesResources.Compiler1;
} }
......
...@@ -809,11 +809,11 @@ internal class FeaturesResources { ...@@ -809,11 +809,11 @@ internal class FeaturesResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to CodeQuality. /// Looks up a localized string similar to Code Quality.
/// </summary> /// </summary>
internal static string CodeQuality { internal static string Code_Quality {
get { get {
return ResourceManager.GetString("CodeQuality", resourceCulture); return ResourceManager.GetString("Code_Quality", resourceCulture);
} }
} }
...@@ -2626,6 +2626,24 @@ internal class FeaturesResources { ...@@ -2626,6 +2626,24 @@ internal class FeaturesResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Private member &apos;{0}&apos; can be removed as the value assigned to it is never read..
/// </summary>
internal static string Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read {
get {
return ResourceManager.GetString("Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Private member &apos;{0}&apos; is unused..
/// </summary>
internal static string Private_member_0_is_unused {
get {
return ResourceManager.GetString("Private_member_0_is_unused", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Project. /// Looks up a localized string similar to Project.
/// </summary> /// </summary>
...@@ -3310,25 +3328,6 @@ internal class FeaturesResources { ...@@ -3310,25 +3328,6 @@ internal class FeaturesResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Type &apos;{0}&apos; has a private member &apos;{1}&apos; that can be removed as the value assigned to it is never read..
/// </summary>
internal static string Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read {
get {
return ResourceManager.GetString("Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_" +
"never_read", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Type &apos;{0}&apos; has an unused private member &apos;{1}&apos; which can be removed..
/// </summary>
internal static string Type_0_has_an_unused_private_member_1_which_can_be_removed {
get {
return ResourceManager.GetString("Type_0_has_an_unused_private_member_1_which_can_be_removed", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to type constraint. /// Looks up a localized string similar to type constraint.
/// </summary> /// </summary>
......
...@@ -1418,8 +1418,8 @@ This version used in: {2}</value> ...@@ -1418,8 +1418,8 @@ This version used in: {2}</value>
<data name="Remove_unused_member" xml:space="preserve"> <data name="Remove_unused_member" xml:space="preserve">
<value>Remove unused member</value> <value>Remove unused member</value>
</data> </data>
<data name="Type_0_has_an_unused_private_member_1_which_can_be_removed" xml:space="preserve"> <data name="Private_member_0_is_unused" xml:space="preserve">
<value>Type '{0}' has an unused private member '{1}' which can be removed.</value> <value>Private member '{0}' is unused.</value>
</data> </data>
<data name="Remove_unused_private_members" xml:space="preserve"> <data name="Remove_unused_private_members" xml:space="preserve">
<value>Remove unused private members</value> <value>Remove unused private members</value>
...@@ -1427,10 +1427,10 @@ This version used in: {2}</value> ...@@ -1427,10 +1427,10 @@ This version used in: {2}</value>
<data name="Remove_unread_private_members" xml:space="preserve"> <data name="Remove_unread_private_members" xml:space="preserve">
<value>Remove unread private members</value> <value>Remove unread private members</value>
</data> </data>
<data name="Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read" xml:space="preserve"> <data name="Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read" xml:space="preserve">
<value>Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</value> <value>Private member '{0}' can be removed as the value assigned to it is never read.</value>
</data> </data>
<data name="CodeQuality" xml:space="preserve"> <data name="Code_Quality" xml:space="preserve">
<value>CodeQuality</value> <value>Code Quality</value>
</data> </data>
</root> </root>
\ No newline at end of file
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Microsoft.CodeAnalysis.CodeQuality;
using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.PooledObjects;
...@@ -13,7 +14,7 @@ ...@@ -13,7 +14,7 @@
namespace Microsoft.CodeAnalysis.RemoveUnusedMembers namespace Microsoft.CodeAnalysis.RemoveUnusedMembers
{ {
internal abstract class AbstractRemoveUnusedMembersDiagnosticAnalyzer<TDocumentationCommentTriviaSyntax, TIdentifierNameSyntax> internal abstract class AbstractRemoveUnusedMembersDiagnosticAnalyzer<TDocumentationCommentTriviaSyntax, TIdentifierNameSyntax>
: DiagnosticAnalyzer, IBuiltInAnalyzer : AbstractCodeQualityDiagnosticAnalyzer
where TDocumentationCommentTriviaSyntax: SyntaxNode where TDocumentationCommentTriviaSyntax: SyntaxNode
where TIdentifierNameSyntax : SyntaxNode where TIdentifierNameSyntax : SyntaxNode
{ {
...@@ -21,44 +22,41 @@ internal abstract class AbstractRemoveUnusedMembersDiagnosticAnalyzer<TDocumenta ...@@ -21,44 +22,41 @@ internal abstract class AbstractRemoveUnusedMembersDiagnosticAnalyzer<TDocumenta
private static readonly DiagnosticDescriptor s_removeUnusedMembersRule = CreateDescriptor( private static readonly DiagnosticDescriptor s_removeUnusedMembersRule = CreateDescriptor(
IDEDiagnosticIds.RemoveUnusedMembersDiagnosticId, IDEDiagnosticIds.RemoveUnusedMembersDiagnosticId,
new LocalizableResourceString(nameof(FeaturesResources.Remove_unused_private_members), FeaturesResources.ResourceManager, typeof(FeaturesResources)), new LocalizableResourceString(nameof(FeaturesResources.Remove_unused_private_members), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Type_0_has_an_unused_private_member_1_which_can_be_removed), FeaturesResources.ResourceManager, typeof(FeaturesResources))); new LocalizableResourceString(nameof(FeaturesResources.Private_member_0_is_unused), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
isUnneccessary: true);
// IDE0052: "Remove unread members" (Value is written and/or symbol is referenced, but the assigned value is never read) // IDE0052: "Remove unread members" (Value is written and/or symbol is referenced, but the assigned value is never read)
private static readonly DiagnosticDescriptor s_removeUnreadMembersRule = CreateDescriptor( private static readonly DiagnosticDescriptor s_removeUnreadMembersRule = CreateDescriptor(
IDEDiagnosticIds.RemoveUnreadMembersDiagnosticId, IDEDiagnosticIds.RemoveUnreadMembersDiagnosticId,
new LocalizableResourceString(nameof(FeaturesResources.Remove_unread_private_members), FeaturesResources.ResourceManager, typeof(FeaturesResources)), new LocalizableResourceString(nameof(FeaturesResources.Remove_unread_private_members), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
new LocalizableResourceString(nameof(FeaturesResources.Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read), FeaturesResources.ResourceManager, typeof(FeaturesResources))); new LocalizableResourceString(nameof(FeaturesResources.Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read), FeaturesResources.ResourceManager, typeof(FeaturesResources)),
isUnneccessary: true);
private static DiagnosticDescriptor CreateDescriptor(string id, LocalizableResourceString title, LocalizableResourceString messageFormat) protected AbstractRemoveUnusedMembersDiagnosticAnalyzer()
=> new DiagnosticDescriptor(id, title, messageFormat, DiagnosticCategory.CodeQuality, : base(ImmutableArray.Create(s_removeUnusedMembersRule, s_removeUnreadMembersRule),
DiagnosticSeverity.Info, isEnabledByDefault: true, customTags: DiagnosticCustomTags.Unnecessary); GeneratedCodeAnalysisFlags.Analyze, // We want to analyze references in generated code, but not report unused members in generated code.
enableConcurrentExecution: true)
public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(s_removeUnusedMembersRule, s_removeUnreadMembersRule); {
}
public bool OpenFileOnly(Workspace workspace) => false; public override bool OpenFileOnly(Workspace workspace) => false;
// We need to analyze the whole document even for edits within a method body, // We need to analyze the whole document even for edits within a method body,
// because we might add or remove references to members in executable code. // because we might add or remove references to members in executable code.
// For example, if we had an unused field with no references, then editing any single method body // For example, if we had an unused field with no references, then editing any single method body
// to reference this field should clear the unused field diagnostic. // to reference this field should clear the unused field diagnostic.
// Hence, we need to re-analyze the declarations in the whole file for any edits within the document. // Hence, we need to re-analyze the declarations in the whole file for any edits within the document.
public DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticDocumentAnalysis; public override DiagnosticAnalyzerCategory GetAnalyzerCategory() => DiagnosticAnalyzerCategory.SemanticDocumentAnalysis;
public sealed override void Initialize(AnalysisContext context)
{
// We want to analyze references in generated code, but not report unused members in generated code.
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze);
context.EnableConcurrentExecution();
context.RegisterCompilationStartAction(compilationStartContext protected sealed override void InitializeWorker(AnalysisContext context)
=> context.RegisterCompilationStartAction(compilationStartContext
=> CompilationAnalyzer.CreateAndRegisterActions(compilationStartContext)); => CompilationAnalyzer.CreateAndRegisterActions(compilationStartContext));
}
private sealed class CompilationAnalyzer private sealed class CompilationAnalyzer
{ {
private readonly object _gate; private readonly object _gate;
private readonly Dictionary<ISymbol, ValueUsageInfo> _symbolValueUsageStateMap; private readonly Dictionary<ISymbol, ValueUsageInfo> _symbolValueUsageStateMap;
private readonly INamedTypeSymbol _taskType, _genericTaskType; private readonly INamedTypeSymbol _taskType, _genericTaskType, _debuggerDisplayAttributeType, _structLayoutAttributeType;
private CompilationAnalyzer(Compilation compilation) private CompilationAnalyzer(Compilation compilation)
{ {
...@@ -69,6 +67,8 @@ private CompilationAnalyzer(Compilation compilation) ...@@ -69,6 +67,8 @@ private CompilationAnalyzer(Compilation compilation)
_taskType = compilation.TaskType(); _taskType = compilation.TaskType();
_genericTaskType = compilation.TaskOfTType(); _genericTaskType = compilation.TaskOfTType();
_debuggerDisplayAttributeType = compilation.DebuggerDisplayAttributeType();
_structLayoutAttributeType = compilation.StructLayoutAttributeType();
} }
public static void CreateAndRegisterActions(CompilationStartAnalysisContext compilationStartContext) public static void CreateAndRegisterActions(CompilationStartAnalysisContext compilationStartContext)
...@@ -92,6 +92,13 @@ private void RegisterActions(CompilationStartAnalysisContext compilationStartCon ...@@ -92,6 +92,13 @@ private void RegisterActions(CompilationStartAnalysisContext compilationStartCon
compilationStartContext.RegisterSymbolStartAction(symbolStartContext => compilationStartContext.RegisterSymbolStartAction(symbolStartContext =>
{ {
if (symbolStartContext.Symbol.GetAttributes().Any(a => a.AttributeClass == _structLayoutAttributeType))
{
// Bail out for types with 'StructLayoutAttribute' as the ordering of the members is critical,
// and removal of unused members might break semantics.
return;
}
var hasInvalidOperation = false; var hasInvalidOperation = false;
symbolStartContext.RegisterOperationAction(AnalyzeMemberReferenceOperation, OperationKind.FieldReference, OperationKind.MethodReference, OperationKind.PropertyReference, OperationKind.EventReference); symbolStartContext.RegisterOperationAction(AnalyzeMemberReferenceOperation, OperationKind.FieldReference, OperationKind.MethodReference, OperationKind.PropertyReference, OperationKind.EventReference);
symbolStartContext.RegisterOperationAction(AnalyzeFieldInitializer, OperationKind.FieldInitializer); symbolStartContext.RegisterOperationAction(AnalyzeFieldInitializer, OperationKind.FieldInitializer);
...@@ -248,6 +255,7 @@ private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext, bool hasInvalid ...@@ -248,6 +255,7 @@ private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext, bool hasInvalid
// Report diagnostics for unused candidate members. // Report diagnostics for unused candidate members.
var first = true; var first = true;
PooledHashSet<ISymbol> symbolsReferencedInDocComments = null; PooledHashSet<ISymbol> symbolsReferencedInDocComments = null;
ArrayBuilder<string> debuggerDisplayAttributeArguments = null;
try try
{ {
var namedType = (INamedTypeSymbol)symbolEndContext.Symbol; var namedType = (INamedTypeSymbol)symbolEndContext.Symbol;
...@@ -273,9 +281,24 @@ private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext, bool hasInvalid ...@@ -273,9 +281,24 @@ private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext, bool hasInvalid
// Compute the set of candidate symbols referenced in all the documentation comments within the named type declarations. // Compute the set of candidate symbols referenced in all the documentation comments within the named type declarations.
// This set is computed once and used for all the iterations of the loop. // This set is computed once and used for all the iterations of the loop.
symbolsReferencedInDocComments = GetCandidateSymbolsReferencedInDocComments(namedType, symbolEndContext.Compilation, symbolEndContext.CancellationToken); symbolsReferencedInDocComments = GetCandidateSymbolsReferencedInDocComments(namedType, symbolEndContext.Compilation, symbolEndContext.CancellationToken);
// Compute the set of string arguments to DebuggerDisplay attributes applied to any symbol within the named type declaration.
// These strings may have an embedded reference to the symbol.
// This set is computed once and used for all the iterations of the loop.
debuggerDisplayAttributeArguments = GetDebuggerDisplayAttributeArguments(namedType);
first = false; first = false;
} }
// Simple heuristic for members referenced in DebuggerDisplayAttribute's string argument:
// bail out if any of the DebuggerDisplay string arguments contains the member name.
// In future, we can consider improving this heuristic to parse the embedded expression
// and resolve symbol references.
if (debuggerDisplayAttributeArguments.Any(arg => arg.Contains(member.Name)))
{
continue;
}
// Report IDE0051 or IDE0052 based on whether the underlying member has any Write/WritableRef/NonReadWriteRef references or not. // Report IDE0051 or IDE0052 based on whether the underlying member has any Write/WritableRef/NonReadWriteRef references or not.
var rule = !valueUsageInfo.ContainsWriteOrWritableRef() && !valueUsageInfo.ContainsNonReadWriteRef() && !symbolsReferencedInDocComments.Contains(member) var rule = !valueUsageInfo.ContainsWriteOrWritableRef() && !valueUsageInfo.ContainsNonReadWriteRef() && !symbolsReferencedInDocComments.Contains(member)
? s_removeUnusedMembersRule ? s_removeUnusedMembersRule
...@@ -288,8 +311,7 @@ private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext, bool hasInvalid ...@@ -288,8 +311,7 @@ private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext, bool hasInvalid
member.Locations[0], member.Locations[0],
additionalLocations: null, additionalLocations: null,
properties: null, properties: null,
member.ContainingType.Name, $"{member.ContainingType.Name}.{member.Name}");
member.Name);
symbolEndContext.ReportDiagnostic(diagnostic); symbolEndContext.ReportDiagnostic(diagnostic);
} }
} }
...@@ -297,6 +319,7 @@ private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext, bool hasInvalid ...@@ -297,6 +319,7 @@ private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext, bool hasInvalid
finally finally
{ {
symbolsReferencedInDocComments?.Free(); symbolsReferencedInDocComments?.Free();
debuggerDisplayAttributeArguments?.Free();
} }
return; return;
...@@ -337,6 +360,51 @@ PooledHashSet<ISymbol> GetCandidateSymbolsReferencedInDocComments(INamedTypeSymb ...@@ -337,6 +360,51 @@ PooledHashSet<ISymbol> GetCandidateSymbolsReferencedInDocComments(INamedTypeSymb
return builder; return builder;
} }
ArrayBuilder<string> GetDebuggerDisplayAttributeArguments(INamedTypeSymbol namedTypeSymbol)
{
var builder = ArrayBuilder<string>.GetInstance();
AddDebuggerDisplayAttributeArguments(namedTypeSymbol, builder);
return builder;
}
void AddDebuggerDisplayAttributeArguments(INamedTypeSymbol namedTypeSymbol, ArrayBuilder<string> builder)
{
AddDebuggerDisplayAttributeArgumentsCore(namedTypeSymbol, builder);
foreach (var member in namedTypeSymbol.GetMembers())
{
switch (member)
{
case INamedTypeSymbol nestedType:
AddDebuggerDisplayAttributeArguments(nestedType, builder);
break;
case IPropertySymbol property:
case IFieldSymbol field:
AddDebuggerDisplayAttributeArgumentsCore(member, builder);
break;
}
}
}
void AddDebuggerDisplayAttributeArgumentsCore(ISymbol symbol, ArrayBuilder<string> builder)
{
foreach (var attribute in symbol.GetAttributes())
{
if (attribute.AttributeClass == _debuggerDisplayAttributeType &&
attribute.ConstructorArguments.Length == 1 &&
attribute.ConstructorArguments[0].Kind == TypedConstantKind.Primitive &&
attribute.ConstructorArguments[0].Type.SpecialType == SpecialType.System_String)
{
var value = attribute.ConstructorArguments[0].Value as string;
if (value != null)
{
builder.Add(value);
}
}
}
}
private bool IsCandidateSymbol(ISymbol memberSymbol) private bool IsCandidateSymbol(ISymbol memberSymbol)
{ {
Debug.Assert(memberSymbol == memberSymbol.OriginalDefinition); Debug.Assert(memberSymbol == memberSymbol.OriginalDefinition);
...@@ -379,6 +447,9 @@ private bool IsCandidateSymbol(ISymbol memberSymbol) ...@@ -379,6 +447,9 @@ private bool IsCandidateSymbol(ISymbol memberSymbol)
case SymbolKind.Field: case SymbolKind.Field:
return ((IFieldSymbol)memberSymbol).AssociatedSymbol == null; return ((IFieldSymbol)memberSymbol).AssociatedSymbol == null;
case SymbolKind.Property:
return ((IPropertySymbol)memberSymbol).ExplicitInterfaceImplementations.IsEmpty;
default: default:
return true; return true;
} }
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
<target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target> <target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="CodeQuality"> <trans-unit id="Code_Quality">
<source>CodeQuality</source> <source>Code Quality</source>
<target state="new">CodeQuality</target> <target state="new">Code Quality</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Convert_to_linq"> <trans-unit id="Convert_to_linq">
...@@ -72,6 +72,16 @@ ...@@ -72,6 +72,16 @@
<target state="translated">Formátuje se dokument.</target> <target state="translated">Formátuje se dokument.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Private member '{0}' can be removed as the value assigned to it is never read.</source>
<target state="new">Private member '{0}' can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Private_member_0_is_unused">
<source>Private member '{0}' is unused.</source>
<target state="new">Private member '{0}' is unused.</target>
<note />
</trans-unit>
<trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated"> <trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated">
<source>Related method signatures found in metadata will not be updated.</source> <source>Related method signatures found in metadata will not be updated.</source>
<target state="translated">Podpisy souvisejících metod nalezené v metadatech se nebudou aktualizovat.</target> <target state="translated">Podpisy souvisejících metod nalezené v metadatech se nebudou aktualizovat.</target>
...@@ -92,16 +102,6 @@ ...@@ -92,16 +102,6 @@
<target state="new">Remove unused private members</target> <target state="new">Remove unused private members</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</source>
<target state="new">Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Type_0_has_an_unused_private_member_1_which_can_be_removed">
<source>Type '{0}' has an unused private member '{1}' which can be removed.</source>
<target state="new">Type '{0}' has an unused private member '{1}' which can be removed.</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_lambda_expressions"> <trans-unit id="Use_block_body_for_lambda_expressions">
<source>Use block body for lambda expressions</source> <source>Use block body for lambda expressions</source>
<target state="new">Use block body for lambda expressions</target> <target state="new">Use block body for lambda expressions</target>
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
<target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target> <target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="CodeQuality"> <trans-unit id="Code_Quality">
<source>CodeQuality</source> <source>Code Quality</source>
<target state="new">CodeQuality</target> <target state="new">Code Quality</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Convert_to_linq"> <trans-unit id="Convert_to_linq">
...@@ -72,6 +72,16 @@ ...@@ -72,6 +72,16 @@
<target state="translated">Dokument wird formatiert</target> <target state="translated">Dokument wird formatiert</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Private member '{0}' can be removed as the value assigned to it is never read.</source>
<target state="new">Private member '{0}' can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Private_member_0_is_unused">
<source>Private member '{0}' is unused.</source>
<target state="new">Private member '{0}' is unused.</target>
<note />
</trans-unit>
<trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated"> <trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated">
<source>Related method signatures found in metadata will not be updated.</source> <source>Related method signatures found in metadata will not be updated.</source>
<target state="translated">In Metadaten gefundene ähnliche Methodensignaturen werden nicht aktualisiert.</target> <target state="translated">In Metadaten gefundene ähnliche Methodensignaturen werden nicht aktualisiert.</target>
...@@ -92,16 +102,6 @@ ...@@ -92,16 +102,6 @@
<target state="new">Remove unused private members</target> <target state="new">Remove unused private members</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</source>
<target state="new">Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Type_0_has_an_unused_private_member_1_which_can_be_removed">
<source>Type '{0}' has an unused private member '{1}' which can be removed.</source>
<target state="new">Type '{0}' has an unused private member '{1}' which can be removed.</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_lambda_expressions"> <trans-unit id="Use_block_body_for_lambda_expressions">
<source>Use block body for lambda expressions</source> <source>Use block body for lambda expressions</source>
<target state="new">Use block body for lambda expressions</target> <target state="new">Use block body for lambda expressions</target>
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
<target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target> <target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="CodeQuality"> <trans-unit id="Code_Quality">
<source>CodeQuality</source> <source>Code Quality</source>
<target state="new">CodeQuality</target> <target state="new">Code Quality</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Convert_to_linq"> <trans-unit id="Convert_to_linq">
...@@ -72,6 +72,16 @@ ...@@ -72,6 +72,16 @@
<target state="translated">Aplicando formato al documento</target> <target state="translated">Aplicando formato al documento</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Private member '{0}' can be removed as the value assigned to it is never read.</source>
<target state="new">Private member '{0}' can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Private_member_0_is_unused">
<source>Private member '{0}' is unused.</source>
<target state="new">Private member '{0}' is unused.</target>
<note />
</trans-unit>
<trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated"> <trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated">
<source>Related method signatures found in metadata will not be updated.</source> <source>Related method signatures found in metadata will not be updated.</source>
<target state="translated">Las signaturas de método relacionadas encontradas en los metadatos no se actualizarán.</target> <target state="translated">Las signaturas de método relacionadas encontradas en los metadatos no se actualizarán.</target>
...@@ -92,16 +102,6 @@ ...@@ -92,16 +102,6 @@
<target state="new">Remove unused private members</target> <target state="new">Remove unused private members</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</source>
<target state="new">Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Type_0_has_an_unused_private_member_1_which_can_be_removed">
<source>Type '{0}' has an unused private member '{1}' which can be removed.</source>
<target state="new">Type '{0}' has an unused private member '{1}' which can be removed.</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_lambda_expressions"> <trans-unit id="Use_block_body_for_lambda_expressions">
<source>Use block body for lambda expressions</source> <source>Use block body for lambda expressions</source>
<target state="new">Use block body for lambda expressions</target> <target state="new">Use block body for lambda expressions</target>
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
<target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target> <target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="CodeQuality"> <trans-unit id="Code_Quality">
<source>CodeQuality</source> <source>Code Quality</source>
<target state="new">CodeQuality</target> <target state="new">Code Quality</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Convert_to_linq"> <trans-unit id="Convert_to_linq">
...@@ -72,6 +72,16 @@ ...@@ -72,6 +72,16 @@
<target state="translated">Mise en forme du document</target> <target state="translated">Mise en forme du document</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Private member '{0}' can be removed as the value assigned to it is never read.</source>
<target state="new">Private member '{0}' can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Private_member_0_is_unused">
<source>Private member '{0}' is unused.</source>
<target state="new">Private member '{0}' is unused.</target>
<note />
</trans-unit>
<trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated"> <trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated">
<source>Related method signatures found in metadata will not be updated.</source> <source>Related method signatures found in metadata will not be updated.</source>
<target state="translated">Les signatures de méthode associées trouvées dans les métadonnées ne seront pas mises à jour.</target> <target state="translated">Les signatures de méthode associées trouvées dans les métadonnées ne seront pas mises à jour.</target>
...@@ -92,16 +102,6 @@ ...@@ -92,16 +102,6 @@
<target state="new">Remove unused private members</target> <target state="new">Remove unused private members</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</source>
<target state="new">Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Type_0_has_an_unused_private_member_1_which_can_be_removed">
<source>Type '{0}' has an unused private member '{1}' which can be removed.</source>
<target state="new">Type '{0}' has an unused private member '{1}' which can be removed.</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_lambda_expressions"> <trans-unit id="Use_block_body_for_lambda_expressions">
<source>Use block body for lambda expressions</source> <source>Use block body for lambda expressions</source>
<target state="new">Use block body for lambda expressions</target> <target state="new">Use block body for lambda expressions</target>
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
<target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target> <target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="CodeQuality"> <trans-unit id="Code_Quality">
<source>CodeQuality</source> <source>Code Quality</source>
<target state="new">CodeQuality</target> <target state="new">Code Quality</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Convert_to_linq"> <trans-unit id="Convert_to_linq">
...@@ -72,6 +72,16 @@ ...@@ -72,6 +72,16 @@
<target state="translated">Formattazione del documento</target> <target state="translated">Formattazione del documento</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Private member '{0}' can be removed as the value assigned to it is never read.</source>
<target state="new">Private member '{0}' can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Private_member_0_is_unused">
<source>Private member '{0}' is unused.</source>
<target state="new">Private member '{0}' is unused.</target>
<note />
</trans-unit>
<trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated"> <trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated">
<source>Related method signatures found in metadata will not be updated.</source> <source>Related method signatures found in metadata will not be updated.</source>
<target state="translated">Le firme del metodo correlate trovate nei metadati non verranno aggiornate.</target> <target state="translated">Le firme del metodo correlate trovate nei metadati non verranno aggiornate.</target>
...@@ -92,16 +102,6 @@ ...@@ -92,16 +102,6 @@
<target state="new">Remove unused private members</target> <target state="new">Remove unused private members</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</source>
<target state="new">Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Type_0_has_an_unused_private_member_1_which_can_be_removed">
<source>Type '{0}' has an unused private member '{1}' which can be removed.</source>
<target state="new">Type '{0}' has an unused private member '{1}' which can be removed.</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_lambda_expressions"> <trans-unit id="Use_block_body_for_lambda_expressions">
<source>Use block body for lambda expressions</source> <source>Use block body for lambda expressions</source>
<target state="new">Use block body for lambda expressions</target> <target state="new">Use block body for lambda expressions</target>
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
<target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target> <target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="CodeQuality"> <trans-unit id="Code_Quality">
<source>CodeQuality</source> <source>Code Quality</source>
<target state="new">CodeQuality</target> <target state="new">Code Quality</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Convert_to_linq"> <trans-unit id="Convert_to_linq">
...@@ -72,6 +72,16 @@ ...@@ -72,6 +72,16 @@
<target state="translated">ドキュメントの書式設定</target> <target state="translated">ドキュメントの書式設定</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Private member '{0}' can be removed as the value assigned to it is never read.</source>
<target state="new">Private member '{0}' can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Private_member_0_is_unused">
<source>Private member '{0}' is unused.</source>
<target state="new">Private member '{0}' is unused.</target>
<note />
</trans-unit>
<trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated"> <trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated">
<source>Related method signatures found in metadata will not be updated.</source> <source>Related method signatures found in metadata will not be updated.</source>
<target state="translated">メタデータ内に検出される関連するメソッド シグネチャは更新されません。</target> <target state="translated">メタデータ内に検出される関連するメソッド シグネチャは更新されません。</target>
...@@ -92,16 +102,6 @@ ...@@ -92,16 +102,6 @@
<target state="new">Remove unused private members</target> <target state="new">Remove unused private members</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</source>
<target state="new">Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Type_0_has_an_unused_private_member_1_which_can_be_removed">
<source>Type '{0}' has an unused private member '{1}' which can be removed.</source>
<target state="new">Type '{0}' has an unused private member '{1}' which can be removed.</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_lambda_expressions"> <trans-unit id="Use_block_body_for_lambda_expressions">
<source>Use block body for lambda expressions</source> <source>Use block body for lambda expressions</source>
<target state="new">Use block body for lambda expressions</target> <target state="new">Use block body for lambda expressions</target>
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
<target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target> <target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="CodeQuality"> <trans-unit id="Code_Quality">
<source>CodeQuality</source> <source>Code Quality</source>
<target state="new">CodeQuality</target> <target state="new">Code Quality</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Convert_to_linq"> <trans-unit id="Convert_to_linq">
...@@ -72,6 +72,16 @@ ...@@ -72,6 +72,16 @@
<target state="translated">문서 서식 지정</target> <target state="translated">문서 서식 지정</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Private member '{0}' can be removed as the value assigned to it is never read.</source>
<target state="new">Private member '{0}' can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Private_member_0_is_unused">
<source>Private member '{0}' is unused.</source>
<target state="new">Private member '{0}' is unused.</target>
<note />
</trans-unit>
<trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated"> <trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated">
<source>Related method signatures found in metadata will not be updated.</source> <source>Related method signatures found in metadata will not be updated.</source>
<target state="translated">메타데이터에서 찾은 관련 메서드 시그니처가 업데이트되지 않습니다.</target> <target state="translated">메타데이터에서 찾은 관련 메서드 시그니처가 업데이트되지 않습니다.</target>
...@@ -92,16 +102,6 @@ ...@@ -92,16 +102,6 @@
<target state="new">Remove unused private members</target> <target state="new">Remove unused private members</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</source>
<target state="new">Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Type_0_has_an_unused_private_member_1_which_can_be_removed">
<source>Type '{0}' has an unused private member '{1}' which can be removed.</source>
<target state="new">Type '{0}' has an unused private member '{1}' which can be removed.</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_lambda_expressions"> <trans-unit id="Use_block_body_for_lambda_expressions">
<source>Use block body for lambda expressions</source> <source>Use block body for lambda expressions</source>
<target state="new">Use block body for lambda expressions</target> <target state="new">Use block body for lambda expressions</target>
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
<target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target> <target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="CodeQuality"> <trans-unit id="Code_Quality">
<source>CodeQuality</source> <source>Code Quality</source>
<target state="new">CodeQuality</target> <target state="new">Code Quality</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Convert_to_linq"> <trans-unit id="Convert_to_linq">
...@@ -72,6 +72,16 @@ ...@@ -72,6 +72,16 @@
<target state="translated">Formatowanie dokumentu</target> <target state="translated">Formatowanie dokumentu</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Private member '{0}' can be removed as the value assigned to it is never read.</source>
<target state="new">Private member '{0}' can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Private_member_0_is_unused">
<source>Private member '{0}' is unused.</source>
<target state="new">Private member '{0}' is unused.</target>
<note />
</trans-unit>
<trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated"> <trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated">
<source>Related method signatures found in metadata will not be updated.</source> <source>Related method signatures found in metadata will not be updated.</source>
<target state="translated">Sygnatury powiązanych metod znalezione w metadanych nie zostaną zaktualizowane.</target> <target state="translated">Sygnatury powiązanych metod znalezione w metadanych nie zostaną zaktualizowane.</target>
...@@ -92,16 +102,6 @@ ...@@ -92,16 +102,6 @@
<target state="new">Remove unused private members</target> <target state="new">Remove unused private members</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</source>
<target state="new">Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Type_0_has_an_unused_private_member_1_which_can_be_removed">
<source>Type '{0}' has an unused private member '{1}' which can be removed.</source>
<target state="new">Type '{0}' has an unused private member '{1}' which can be removed.</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_lambda_expressions"> <trans-unit id="Use_block_body_for_lambda_expressions">
<source>Use block body for lambda expressions</source> <source>Use block body for lambda expressions</source>
<target state="new">Use block body for lambda expressions</target> <target state="new">Use block body for lambda expressions</target>
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
<target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target> <target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="CodeQuality"> <trans-unit id="Code_Quality">
<source>CodeQuality</source> <source>Code Quality</source>
<target state="new">CodeQuality</target> <target state="new">Code Quality</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Convert_to_linq"> <trans-unit id="Convert_to_linq">
...@@ -72,6 +72,16 @@ ...@@ -72,6 +72,16 @@
<target state="translated">Formatando documento</target> <target state="translated">Formatando documento</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Private member '{0}' can be removed as the value assigned to it is never read.</source>
<target state="new">Private member '{0}' can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Private_member_0_is_unused">
<source>Private member '{0}' is unused.</source>
<target state="new">Private member '{0}' is unused.</target>
<note />
</trans-unit>
<trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated"> <trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated">
<source>Related method signatures found in metadata will not be updated.</source> <source>Related method signatures found in metadata will not be updated.</source>
<target state="translated">As assinaturas de método relacionadas encontradas nos metadados não serão atualizadas.</target> <target state="translated">As assinaturas de método relacionadas encontradas nos metadados não serão atualizadas.</target>
...@@ -92,16 +102,6 @@ ...@@ -92,16 +102,6 @@
<target state="new">Remove unused private members</target> <target state="new">Remove unused private members</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</source>
<target state="new">Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Type_0_has_an_unused_private_member_1_which_can_be_removed">
<source>Type '{0}' has an unused private member '{1}' which can be removed.</source>
<target state="new">Type '{0}' has an unused private member '{1}' which can be removed.</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_lambda_expressions"> <trans-unit id="Use_block_body_for_lambda_expressions">
<source>Use block body for lambda expressions</source> <source>Use block body for lambda expressions</source>
<target state="new">Use block body for lambda expressions</target> <target state="new">Use block body for lambda expressions</target>
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
<target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target> <target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="CodeQuality"> <trans-unit id="Code_Quality">
<source>CodeQuality</source> <source>Code Quality</source>
<target state="new">CodeQuality</target> <target state="new">Code Quality</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Convert_to_linq"> <trans-unit id="Convert_to_linq">
...@@ -72,6 +72,16 @@ ...@@ -72,6 +72,16 @@
<target state="translated">Форматирование документа</target> <target state="translated">Форматирование документа</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Private member '{0}' can be removed as the value assigned to it is never read.</source>
<target state="new">Private member '{0}' can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Private_member_0_is_unused">
<source>Private member '{0}' is unused.</source>
<target state="new">Private member '{0}' is unused.</target>
<note />
</trans-unit>
<trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated"> <trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated">
<source>Related method signatures found in metadata will not be updated.</source> <source>Related method signatures found in metadata will not be updated.</source>
<target state="translated">Связанные сигнатуры методов, найденные в метаданных, не будут обновлены.</target> <target state="translated">Связанные сигнатуры методов, найденные в метаданных, не будут обновлены.</target>
...@@ -92,16 +102,6 @@ ...@@ -92,16 +102,6 @@
<target state="new">Remove unused private members</target> <target state="new">Remove unused private members</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</source>
<target state="new">Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Type_0_has_an_unused_private_member_1_which_can_be_removed">
<source>Type '{0}' has an unused private member '{1}' which can be removed.</source>
<target state="new">Type '{0}' has an unused private member '{1}' which can be removed.</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_lambda_expressions"> <trans-unit id="Use_block_body_for_lambda_expressions">
<source>Use block body for lambda expressions</source> <source>Use block body for lambda expressions</source>
<target state="new">Use block body for lambda expressions</target> <target state="new">Use block body for lambda expressions</target>
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
<target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target> <target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="CodeQuality"> <trans-unit id="Code_Quality">
<source>CodeQuality</source> <source>Code Quality</source>
<target state="new">CodeQuality</target> <target state="new">Code Quality</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Convert_to_linq"> <trans-unit id="Convert_to_linq">
...@@ -72,6 +72,16 @@ ...@@ -72,6 +72,16 @@
<target state="translated">Belge biçimlendiriliyor</target> <target state="translated">Belge biçimlendiriliyor</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Private member '{0}' can be removed as the value assigned to it is never read.</source>
<target state="new">Private member '{0}' can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Private_member_0_is_unused">
<source>Private member '{0}' is unused.</source>
<target state="new">Private member '{0}' is unused.</target>
<note />
</trans-unit>
<trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated"> <trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated">
<source>Related method signatures found in metadata will not be updated.</source> <source>Related method signatures found in metadata will not be updated.</source>
<target state="translated">Meta verilerde bulunan ilgili metot imzaları güncelleştirilmez.</target> <target state="translated">Meta verilerde bulunan ilgili metot imzaları güncelleştirilmez.</target>
...@@ -92,16 +102,6 @@ ...@@ -92,16 +102,6 @@
<target state="new">Remove unused private members</target> <target state="new">Remove unused private members</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</source>
<target state="new">Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Type_0_has_an_unused_private_member_1_which_can_be_removed">
<source>Type '{0}' has an unused private member '{1}' which can be removed.</source>
<target state="new">Type '{0}' has an unused private member '{1}' which can be removed.</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_lambda_expressions"> <trans-unit id="Use_block_body_for_lambda_expressions">
<source>Use block body for lambda expressions</source> <source>Use block body for lambda expressions</source>
<target state="new">Use block body for lambda expressions</target> <target state="new">Use block body for lambda expressions</target>
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
<target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target> <target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="CodeQuality"> <trans-unit id="Code_Quality">
<source>CodeQuality</source> <source>Code Quality</source>
<target state="new">CodeQuality</target> <target state="new">Code Quality</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Convert_to_linq"> <trans-unit id="Convert_to_linq">
...@@ -72,6 +72,16 @@ ...@@ -72,6 +72,16 @@
<target state="translated">设置文档格式</target> <target state="translated">设置文档格式</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Private member '{0}' can be removed as the value assigned to it is never read.</source>
<target state="new">Private member '{0}' can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Private_member_0_is_unused">
<source>Private member '{0}' is unused.</source>
<target state="new">Private member '{0}' is unused.</target>
<note />
</trans-unit>
<trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated"> <trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated">
<source>Related method signatures found in metadata will not be updated.</source> <source>Related method signatures found in metadata will not be updated.</source>
<target state="translated">不更新在元数据中发现的相关方法签名。</target> <target state="translated">不更新在元数据中发现的相关方法签名。</target>
...@@ -92,16 +102,6 @@ ...@@ -92,16 +102,6 @@
<target state="new">Remove unused private members</target> <target state="new">Remove unused private members</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</source>
<target state="new">Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Type_0_has_an_unused_private_member_1_which_can_be_removed">
<source>Type '{0}' has an unused private member '{1}' which can be removed.</source>
<target state="new">Type '{0}' has an unused private member '{1}' which can be removed.</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_lambda_expressions"> <trans-unit id="Use_block_body_for_lambda_expressions">
<source>Use block body for lambda expressions</source> <source>Use block body for lambda expressions</source>
<target state="new">Use block body for lambda expressions</target> <target state="new">Use block body for lambda expressions</target>
......
...@@ -27,9 +27,9 @@ ...@@ -27,9 +27,9 @@
<target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target> <target state="new">Adding a method with an explicit interface specifier will prevent the debug session from continuing.</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="CodeQuality"> <trans-unit id="Code_Quality">
<source>CodeQuality</source> <source>Code Quality</source>
<target state="new">CodeQuality</target> <target state="new">Code Quality</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Convert_to_linq"> <trans-unit id="Convert_to_linq">
...@@ -72,6 +72,16 @@ ...@@ -72,6 +72,16 @@
<target state="translated">正在將文件格式化</target> <target state="translated">正在將文件格式化</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Private_member_0_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Private member '{0}' can be removed as the value assigned to it is never read.</source>
<target state="new">Private member '{0}' can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Private_member_0_is_unused">
<source>Private member '{0}' is unused.</source>
<target state="new">Private member '{0}' is unused.</target>
<note />
</trans-unit>
<trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated"> <trans-unit id="Related_method_signatures_found_in_metadata_will_not_be_updated">
<source>Related method signatures found in metadata will not be updated.</source> <source>Related method signatures found in metadata will not be updated.</source>
<target state="translated">將不會更新中繼資料中所找到的相關方法簽章。</target> <target state="translated">將不會更新中繼資料中所找到的相關方法簽章。</target>
...@@ -92,16 +102,6 @@ ...@@ -92,16 +102,6 @@
<target state="new">Remove unused private members</target> <target state="new">Remove unused private members</target>
<note /> <note />
</trans-unit> </trans-unit>
<trans-unit id="Type_0_has_a_private_member_1_that_can_be_removed_as_the_value_assigned_to_it_is_never_read">
<source>Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</source>
<target state="new">Type '{0}' has a private member '{1}' that can be removed as the value assigned to it is never read.</target>
<note />
</trans-unit>
<trans-unit id="Type_0_has_an_unused_private_member_1_which_can_be_removed">
<source>Type '{0}' has an unused private member '{1}' which can be removed.</source>
<target state="new">Type '{0}' has an unused private member '{1}' which can be removed.</target>
<note />
</trans-unit>
<trans-unit id="Use_block_body_for_lambda_expressions"> <trans-unit id="Use_block_body_for_lambda_expressions">
<source>Use block body for lambda expressions</source> <source>Use block body for lambda expressions</source>
<target state="new">Use block body for lambda expressions</target> <target state="new">Use block body for lambda expressions</target>
......
...@@ -58,6 +58,12 @@ public static INamedTypeSymbol AttributeType(this Compilation compilation) ...@@ -58,6 +58,12 @@ public static INamedTypeSymbol AttributeType(this Compilation compilation)
public static INamedTypeSymbol ExceptionType(this Compilation compilation) public static INamedTypeSymbol ExceptionType(this Compilation compilation)
=> compilation.GetTypeByMetadataName(typeof(Exception).FullName); => compilation.GetTypeByMetadataName(typeof(Exception).FullName);
public static INamedTypeSymbol DebuggerDisplayAttributeType(this Compilation compilation)
=> compilation.GetTypeByMetadataName(typeof(System.Diagnostics.DebuggerDisplayAttribute).FullName);
public static INamedTypeSymbol StructLayoutAttributeType(this Compilation compilation)
=> compilation.GetTypeByMetadataName(typeof(System.Runtime.InteropServices.StructLayoutAttribute).FullName);
public static INamedTypeSymbol DesignerCategoryAttributeType(this Compilation compilation) public static INamedTypeSymbol DesignerCategoryAttributeType(this Compilation compilation)
=> compilation.GetTypeByMetadataName("System.ComponentModel.DesignerCategoryAttribute"); => compilation.GetTypeByMetadataName("System.ComponentModel.DesignerCategoryAttribute");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册