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

Enable DeadCodeAnalysis rules and address design/review feedback.

Primarily addresses https://github.com/dotnet/roslyn/issues/29519#issuecomment-420067012

```
1. Enable the rules be default
2. Remove all the workaround/hacks for disabling the rules for product and enabling for tests.
3. Address offline feedback from @sharwell about avoiding deriving the tests from `TestBase`.
4. Separate out the pending non-design related work items from first comment into separate issues.
```

For 4., I have repurposed https://github.com/dotnet/roslyn/issues/29519 to track the pending issues with checkboxes in the first issue comment.
上级 57094884
......@@ -49,11 +49,11 @@ Friend Module ParserTestUtilities
End Function
Public Function ParseAndVerify(code As XCData, ParamArray expectedDiagnostics() As DiagnosticDescription) As SyntaxTree
Return ParseAndVerify(TestBase.NormalizeNewLines(code), VisualBasicParseOptions.Default, expectedDiagnostics, errorCodesOnly:=False)
Return ParseAndVerify(TestHelpers.NormalizeNewLines(code), VisualBasicParseOptions.Default, expectedDiagnostics, errorCodesOnly:=False)
End Function
Public Function ParseAndVerify(code As XCData, options As VisualBasicParseOptions, ParamArray expectedDiagnostics() As DiagnosticDescription) As SyntaxTree
Return ParseAndVerify(TestBase.NormalizeNewLines(code), options, expectedDiagnostics, errorCodesOnly:=False)
Return ParseAndVerify(TestHelpers.NormalizeNewLines(code), options, expectedDiagnostics, errorCodesOnly:=False)
End Function
Public Function ParseAndVerify(source As String, ParamArray expectedDiagnostics() As DiagnosticDescription) As SyntaxTree
......
......@@ -1849,7 +1849,7 @@ End Structure
Optional latestReferences As Boolean = False,
Optional addXmlReferences As Boolean = False,
Optional diagnostics() As DiagnosticDescription = Nothing)
TestExpressionTrees(sourceFile, TestBase.NormalizeNewLines(result), checked, optimize, latestReferences, addXmlReferences, diagnostics)
TestExpressionTrees(sourceFile, TestHelpers.NormalizeNewLines(result), checked, optimize, latestReferences, addXmlReferences, diagnostics)
End Sub
Private Class ExpressionTreeTest
......
......@@ -43,7 +43,7 @@ private static void AnalyzeNode(SyntaxNodeAnalysisContext context)
var symbol = context.SemanticModel.GetSymbolInfo(node).Symbol;
if (symbol != null && symbol.Kind == SymbolKind.Field)
{
var diagnostic = CodeAnalysis.Diagnostic.Create(Descriptor, node.GetLocation());
var diagnostic = Diagnostic.Create(Descriptor, node.GetLocation());
context.ReportDiagnostic(diagnostic);
}
}
......
......@@ -47,7 +47,7 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var classDecl = (ClassDeclarationSyntax)context.Node;
var location = _reportDiagnosticsWithoutLocation ? Location.None : classDecl.Identifier.GetLocation();
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(Decsciptor, location));
context.ReportDiagnostic(Diagnostic.Create(Decsciptor, location));
}
}
......
......@@ -47,8 +47,8 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var classDecl = (ClassDeclarationSyntax)context.Node;
var location = classDecl.Identifier.GetLocation();
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(Decsciptor1, location));
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(Decsciptor2, location));
context.ReportDiagnostic(Diagnostic.Create(Decsciptor1, location));
context.ReportDiagnostic(Diagnostic.Create(Decsciptor2, location));
}
}
......
......@@ -468,7 +468,7 @@ public override void Initialize(AnalysisContext context)
public void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var classDecl = (ClassDeclarationSyntax)context.Node;
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(Decsciptor, classDecl.Identifier.GetLocation()));
context.ReportDiagnostic(Diagnostic.Create(Decsciptor, classDecl.Identifier.GetLocation()));
}
}
......@@ -530,7 +530,7 @@ public override void Initialize(AnalysisContext context)
public void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var classDecl = (ClassDeclarationSyntax)context.Node;
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()));
context.ReportDiagnostic(Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()));
}
}
......@@ -595,7 +595,7 @@ public override void Initialize(AnalysisContext context)
public void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var classDecl = (ClassDeclarationSyntax)context.Node;
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()));
context.ReportDiagnostic(Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()));
}
}
......@@ -647,7 +647,7 @@ public override void Initialize(AnalysisContext context)
public void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
var classDecl = (ClassDeclarationSyntax)context.Node;
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(Decsciptor, classDecl.GetLocation()));
context.ReportDiagnostic(Diagnostic.Create(Decsciptor, classDecl.GetLocation()));
}
}
......@@ -760,39 +760,39 @@ public void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
case SyntaxKind.ClassDeclaration:
var classDecl = (ClassDeclarationSyntax)context.Node;
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(Descriptor, classDecl.Identifier.GetLocation()));
context.ReportDiagnostic(Diagnostic.Create(Descriptor, classDecl.Identifier.GetLocation()));
break;
case SyntaxKind.NamespaceDeclaration:
var ns = (NamespaceDeclarationSyntax)context.Node;
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(Descriptor, ns.Name.GetLocation()));
context.ReportDiagnostic(Diagnostic.Create(Descriptor, ns.Name.GetLocation()));
break;
case SyntaxKind.MethodDeclaration:
var method = (MethodDeclarationSyntax)context.Node;
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(Descriptor, method.Identifier.GetLocation()));
context.ReportDiagnostic(Diagnostic.Create(Descriptor, method.Identifier.GetLocation()));
break;
case SyntaxKind.PropertyDeclaration:
var property = (PropertyDeclarationSyntax)context.Node;
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(Descriptor, property.Identifier.GetLocation()));
context.ReportDiagnostic(Diagnostic.Create(Descriptor, property.Identifier.GetLocation()));
break;
case SyntaxKind.FieldDeclaration:
var field = (FieldDeclarationSyntax)context.Node;
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(Descriptor, field.Declaration.Variables.First().Identifier.GetLocation()));
context.ReportDiagnostic(Diagnostic.Create(Descriptor, field.Declaration.Variables.First().Identifier.GetLocation()));
break;
case SyntaxKind.EventDeclaration:
var e = (EventDeclarationSyntax)context.Node;
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(Descriptor, e.Identifier.GetLocation()));
context.ReportDiagnostic(Diagnostic.Create(Descriptor, e.Identifier.GetLocation()));
break;
case SyntaxKind.EnumDeclaration:
// Report diagnostic on each descendant comment trivia
foreach (var trivia in context.Node.DescendantTrivia().Where(t => t.Kind() == SyntaxKind.SingleLineCommentTrivia || t.Kind() == SyntaxKind.MultiLineCommentTrivia))
{
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(Descriptor, trivia.GetLocation()));
context.ReportDiagnostic(Diagnostic.Create(Descriptor, trivia.GetLocation()));
}
break;
}
......@@ -1571,7 +1571,7 @@ public override void Initialize(AnalysisContext context)
public void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(Descriptor, Location.None));
context.ReportDiagnostic(Diagnostic.Create(Descriptor, Location.None));
}
}
......
......@@ -5,17 +5,16 @@
using Microsoft.CodeAnalysis.CSharp.RemoveUnusedMembers;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.RemoveUnusedMembers;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
using static Roslyn.Test.Utilities.TestHelpers;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.RemoveUnusedMembers
{
public class RemoveUnusedMembersTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
=> (new CSharpRemoveUnusedMembersDiagnosticAnalyzer(forceEnableRules: true),
new CSharpRemoveUnusedMembersCodeFixProvider());
=> (new CSharpRemoveUnusedMembersDiagnosticAnalyzer(), new CSharpRemoveUnusedMembersCodeFixProvider());
[Theory, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)]
[InlineData("public")]
......
......@@ -26,7 +26,7 @@
namespace Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions
{
[UseExportProvider]
public abstract class AbstractCodeActionOrUserDiagnosticTest : TestBase
public abstract class AbstractCodeActionOrUserDiagnosticTest
{
public struct TestParameters
{
......
......@@ -629,7 +629,7 @@ End Class]]>
Private Sub AnalyzeNode(context As SyntaxNodeAnalysisContext)
Dim classDecl = DirectCast(context.Node, ClassStatementSyntax)
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()))
context.ReportDiagnostic(Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()))
End Sub
End Class
......@@ -703,7 +703,7 @@ End Class]]>
Private Sub AnalyzeNode(context As SyntaxNodeAnalysisContext)
Dim classDecl = DirectCast(context.Node, ClassStatementSyntax)
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()))
context.ReportDiagnostic(Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()))
End Sub
End Class
......@@ -747,7 +747,7 @@ End Class]]>
Public Sub AnalyzeNode(context As SyntaxNodeAnalysisContext)
Dim classDecl = DirectCast(context.Node, ClassStatementSyntax)
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()))
context.ReportDiagnostic(Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()))
End Sub
End Class
......@@ -811,7 +811,7 @@ End Class]]>
Public Sub AnalyzeNode(context As SyntaxNodeAnalysisContext)
Dim classDecl = DirectCast(context.Node, ClassStatementSyntax)
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()))
context.ReportDiagnostic(Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()))
End Sub
End Class
......@@ -931,32 +931,32 @@ End Class]]>
Select Case context.Node.Kind()
Case SyntaxKind.ClassStatement
Dim classDecl = DirectCast(context.Node, ClassStatementSyntax)
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()))
context.ReportDiagnostic(Diagnostic.Create(_descriptor, classDecl.Identifier.GetLocation()))
Exit Select
Case SyntaxKind.NamespaceStatement
Dim ns = DirectCast(context.Node, NamespaceStatementSyntax)
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(_descriptor, ns.Name.GetLocation()))
context.ReportDiagnostic(Diagnostic.Create(_descriptor, ns.Name.GetLocation()))
Exit Select
Case SyntaxKind.SubStatement, SyntaxKind.FunctionStatement
Dim method = DirectCast(context.Node, MethodStatementSyntax)
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(_descriptor, method.Identifier.GetLocation()))
context.ReportDiagnostic(Diagnostic.Create(_descriptor, method.Identifier.GetLocation()))
Exit Select
Case SyntaxKind.PropertyStatement
Dim p = DirectCast(context.Node, PropertyStatementSyntax)
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(_descriptor, p.Identifier.GetLocation()))
context.ReportDiagnostic(Diagnostic.Create(_descriptor, p.Identifier.GetLocation()))
Exit Select
Case SyntaxKind.FieldDeclaration
Dim f = DirectCast(context.Node, FieldDeclarationSyntax)
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(_descriptor, f.Declarators.First().Names.First.GetLocation()))
context.ReportDiagnostic(Diagnostic.Create(_descriptor, f.Declarators.First().Names.First.GetLocation()))
Exit Select
Case SyntaxKind.EventStatement
Dim e = DirectCast(context.Node, EventStatementSyntax)
context.ReportDiagnostic(CodeAnalysis.Diagnostic.Create(_descriptor, e.Identifier.GetLocation()))
context.ReportDiagnostic(Diagnostic.Create(_descriptor, e.Identifier.GetLocation()))
Exit Select
End Select
End Sub
......
......@@ -3,16 +3,17 @@
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics
Imports Microsoft.CodeAnalysis.RemoveUnusedMembers
Imports Microsoft.CodeAnalysis.VisualBasic.RemoveUnusedMembers
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.RemoveUnusedMembers
Public Class RemoveUnusedMembersTests
Inherits AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As (DiagnosticAnalyzer, CodeFixProvider)
Return (New VisualBasicRemoveUnusedMembersDiagnosticAnalyzer(forceEnableRules:=True),
New VisualBasicRemoveUnusedMembersCodeFixProvider())
Return (New VisualBasicRemoveUnusedMembersDiagnosticAnalyzer(), New VisualBasicRemoveUnusedMembersCodeFixProvider())
End Function
Private Shared Function Diagnostic(id As String) As DiagnosticDescription
Return TestHelpers.Diagnostic(id)
End Function
<Theory, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)>
......
......@@ -10,15 +10,5 @@ namespace Microsoft.CodeAnalysis.CSharp.RemoveUnusedMembers
internal class CSharpRemoveUnusedMembersDiagnosticAnalyzer
: AbstractRemoveUnusedMembersDiagnosticAnalyzer<DocumentationCommentTriviaSyntax, IdentifierNameSyntax>
{
public CSharpRemoveUnusedMembersDiagnosticAnalyzer()
: base(forceEnableRules: false)
{
}
// For testing purposes only.
internal CSharpRemoveUnusedMembersDiagnosticAnalyzer(bool forceEnableRules)
: base(forceEnableRules)
{
}
}
}
// 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;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
......@@ -19,42 +18,30 @@ internal abstract class AbstractRemoveUnusedMembersDiagnosticAnalyzer<TDocumenta
where TDocumentationCommentTriviaSyntax: SyntaxNode
where TIdentifierNameSyntax : SyntaxNode
{
protected AbstractRemoveUnusedMembersDiagnosticAnalyzer(bool forceEnableRules)
: base(CreateDescriptors(forceEnableRules))
// IDE0051: "Remove unused members" (Symbol is declared but never referenced)
private static readonly LocalizableResourceString s_removeUnusedMembersTitle = new LocalizableResourceString(nameof(FeaturesResources.Remove_unused_private_members), FeaturesResources.ResourceManager, typeof(FeaturesResources));
private static readonly LocalizableResourceString s_removeUnusedMembersMessage = new LocalizableResourceString(nameof(FeaturesResources.Type_0_has_an_unused_private_member_1_which_can_be_removed), FeaturesResources.ResourceManager, typeof(FeaturesResources));
private static readonly DiagnosticDescriptor s_removeUnusedMembersRule = CreateDescriptor(
IDEDiagnosticIds.RemoveUnusedMembersDiagnosticId, s_removeUnusedMembersTitle, s_removeUnusedMembersMessage, configurable: true, enabledByDefault: true);
private static readonly DiagnosticDescriptor s_removeUnusedMembersWithFadingRule = CreateUnnecessaryDescriptor(
IDEDiagnosticIds.RemoveUnusedMembersDiagnosticId, s_removeUnusedMembersTitle, s_removeUnusedMembersMessage, configurable: true, enabledByDefault: true);
// IDE0052: "Remove unread members" (Value is written and/or symbol is referenced, but the assigned value is never read)
private static readonly LocalizableResourceString s_removeUnreadMembersTitle = new LocalizableResourceString(nameof(FeaturesResources.Remove_unread_private_members), FeaturesResources.ResourceManager, typeof(FeaturesResources));
private static readonly LocalizableResourceString s_removeUnreadMembersMessage = 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));
private static readonly DiagnosticDescriptor s_removeUnreadMembersRule = CreateDescriptor(
IDEDiagnosticIds.RemoveUnreadMembersDiagnosticId, s_removeUnreadMembersTitle, s_removeUnreadMembersMessage, configurable: true, enabledByDefault: true);
private static readonly DiagnosticDescriptor s_removeUnreadMembersWithFadingRule = CreateUnnecessaryDescriptor(
IDEDiagnosticIds.RemoveUnreadMembersDiagnosticId, s_removeUnreadMembersTitle, s_removeUnreadMembersMessage, configurable: true, enabledByDefault: true);
protected AbstractRemoveUnusedMembersDiagnosticAnalyzer()
: base (ImmutableArray.Create(s_removeUnusedMembersRule,
s_removeUnusedMembersWithFadingRule,
s_removeUnreadMembersRule,
s_removeUnreadMembersWithFadingRule))
{
}
private static ImmutableArray<DiagnosticDescriptor> CreateDescriptors(bool forceEnableRules)
{
// TODO: Enable these rules by default once we have designed the Tools|Option location and UI for such code quality rules.
// https://github.com/dotnet/roslyn/issues/29519
// IDE0051: "Remove unused members" (Symbol is declared but never referenced)
var removeUnusedMembersTitle = new LocalizableResourceString(nameof(FeaturesResources.Remove_unused_private_members), FeaturesResources.ResourceManager, typeof(FeaturesResources));
var removeUnusedMembersMessage = new LocalizableResourceString(nameof(FeaturesResources.Type_0_has_an_unused_private_member_1_which_can_be_removed), FeaturesResources.ResourceManager, typeof(FeaturesResources));
var removeUnusedMembersRule = CreateDescriptor(
IDEDiagnosticIds.RemoveUnusedMembersDiagnosticId, removeUnusedMembersTitle, removeUnusedMembersMessage, configurable: true, enabledByDefault: forceEnableRules);
var removeUnusedMembersRuleWithFadingRule = CreateUnnecessaryDescriptor(
IDEDiagnosticIds.RemoveUnusedMembersDiagnosticId, removeUnusedMembersTitle, removeUnusedMembersMessage, configurable: true, enabledByDefault: forceEnableRules);
// IDE0052: "Remove unread members" (Value is written and/or symbol is referenced, but the assigned value is never read)
var removeUnreadMembersTitle = new LocalizableResourceString(nameof(FeaturesResources.Remove_unread_private_members), FeaturesResources.ResourceManager, typeof(FeaturesResources));
var removeUnreadMembersMessage = 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));
var removeUnreadMembersRule = CreateDescriptor(
IDEDiagnosticIds.RemoveUnreadMembersDiagnosticId, removeUnreadMembersTitle, removeUnreadMembersMessage, configurable: true, enabledByDefault: forceEnableRules);
var removeUnreadMembersRuleUnnecessaryWithFadingRule = CreateUnnecessaryDescriptor(
IDEDiagnosticIds.RemoveUnreadMembersDiagnosticId, removeUnreadMembersTitle, removeUnreadMembersMessage, configurable: true, enabledByDefault: forceEnableRules);
return ImmutableArray.Create(removeUnusedMembersRule, removeUnusedMembersRuleWithFadingRule,
removeUnreadMembersRule, removeUnreadMembersRuleUnnecessaryWithFadingRule);
}
// See CreateDescriptors method above for the indices.
// We should be able to cleanup the implementation to avoid hard coded indices
// once https://github.com/dotnet/roslyn/issues/29519 is implemented.
private DiagnosticDescriptor RemoveUnusedMemberRule => SupportedDiagnostics[1];
private DiagnosticDescriptor RemoveUnreadMemberRule => SupportedDiagnostics[3];
public override bool OpenFileOnly(Workspace workspace) => false;
// We need to analyze the whole document even for edits within a method body,
......@@ -70,20 +57,17 @@ protected override void InitializeWorker(AnalysisContext context)
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze);
context.RegisterCompilationStartAction(compilationStartContext
=> CompilationAnalyzer.CreateAndRegisterActions(compilationStartContext, RemoveUnusedMemberRule, RemoveUnreadMemberRule));
=> CompilationAnalyzer.CreateAndRegisterActions(compilationStartContext));
}
private sealed class CompilationAnalyzer
{
private readonly DiagnosticDescriptor _removeUnusedMembersRule, _removeUnreadMembersRule;
private readonly object _gate;
private readonly Dictionary<ISymbol, ValueUsageInfo> _symbolValueUsageStateMap;
private readonly INamedTypeSymbol _taskType, _genericTaskType;
private CompilationAnalyzer(Compilation compilation, DiagnosticDescriptor removeUnusedMembersRule, DiagnosticDescriptor removeUnreadMembersRule)
private CompilationAnalyzer(Compilation compilation)
{
_removeUnusedMembersRule = removeUnusedMembersRule;
_removeUnreadMembersRule = removeUnreadMembersRule;
_gate = new object();
// State map for candidate member symbols, with the value indicating how each symbol is used in executable code.
......@@ -93,9 +77,9 @@ private CompilationAnalyzer(Compilation compilation, DiagnosticDescriptor remove
_genericTaskType = compilation.TaskOfTType();
}
public static void CreateAndRegisterActions(CompilationStartAnalysisContext compilationStartContext, DiagnosticDescriptor removeUnusedMembersRule, DiagnosticDescriptor removeUnreadMembersRule)
public static void CreateAndRegisterActions(CompilationStartAnalysisContext compilationStartContext)
{
var compilationAnalyzer = new CompilationAnalyzer(compilationStartContext.Compilation, removeUnusedMembersRule, removeUnreadMembersRule);
var compilationAnalyzer = new CompilationAnalyzer(compilationStartContext.Compilation);
compilationAnalyzer.RegisterActions(compilationStartContext);
}
......@@ -283,8 +267,8 @@ private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext, bool hasInvalid
// 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)
? _removeUnusedMembersRule
: _removeUnreadMembersRule;
? s_removeUnusedMembersWithFadingRule
: s_removeUnreadMembersWithFadingRule;
var effectiveSeverity = rule.GetEffectiveSeverity(symbolEndContext.Compilation.Options);
// Most of the members should have a single location, except for partial methods.
......
......@@ -9,14 +9,5 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnusedMembers
<DiagnosticAnalyzer(LanguageNames.VisualBasic)>
Friend NotInheritable Class VisualBasicRemoveUnusedMembersDiagnosticAnalyzer
Inherits AbstractRemoveUnusedMembersDiagnosticAnalyzer(Of DocumentationCommentTriviaSyntax, IdentifierNameSyntax)
Public Sub New()
MyBase.New(forceEnableRules:=False)
End Sub
' For testing purposes only.
Friend Sub New(forceEnableRules As Boolean)
MyBase.New(forceEnableRules)
End Sub
End Class
End Namespace
......@@ -330,17 +330,13 @@ private static MetadataReference GetOrCreateMetadataReference(ref MetadataRefere
Func<SyntaxNode, bool> syntaxNodePredicate = null,
bool argumentOrderDoesNotMatter = false)
{
Debug.Assert(code is ErrorCode || code is ERRID || code is int || code is string);
return new DiagnosticDescription(
code as string ?? (object)(int)code,
false,
return TestHelpers.Diagnostic(
code,
squiggledText,
arguments,
startLocation,
syntaxNodePredicate,
argumentOrderDoesNotMatter,
code.GetType());
argumentOrderDoesNotMatter);
}
internal static DiagnosticDescription Diagnostic(
......@@ -351,25 +347,15 @@ private static MetadataReference GetOrCreateMetadataReference(ref MetadataRefere
Func<SyntaxNode, bool> syntaxNodePredicate = null,
bool argumentOrderDoesNotMatter = false)
{
return Diagnostic(
return TestHelpers.Diagnostic(
code,
NormalizeNewLines(squiggledText),
squiggledText,
arguments,
startLocation,
syntaxNodePredicate,
argumentOrderDoesNotMatter);
}
public static string NormalizeNewLines(XCData data)
{
if (ExecutionConditionUtil.IsWindows)
{
return data.Value.Replace("\n", "\r\n");
}
return data.Value;
}
#endregion
}
}
......@@ -7,7 +7,10 @@
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
namespace Roslyn.Test.Utilities
{
......@@ -76,5 +79,59 @@ public static string AsXmlCommentText(string text)
return result;
}
#region Diagnostics
internal static DiagnosticDescription Diagnostic(
object code,
string squiggledText = null,
object[] arguments = null,
LinePosition? startLocation = null,
Func<SyntaxNode, bool> syntaxNodePredicate = null,
bool argumentOrderDoesNotMatter = false)
{
Debug.Assert(code is Microsoft.CodeAnalysis.CSharp.ErrorCode ||
code is Microsoft.CodeAnalysis.VisualBasic.ERRID ||
code is int ||
code is string);
return new DiagnosticDescription(
code as string ?? (object)(int)code,
false,
squiggledText,
arguments,
startLocation,
syntaxNodePredicate,
argumentOrderDoesNotMatter,
code.GetType());
}
internal static DiagnosticDescription Diagnostic(
object code,
XCData squiggledText,
object[] arguments = null,
LinePosition? startLocation = null,
Func<SyntaxNode, bool> syntaxNodePredicate = null,
bool argumentOrderDoesNotMatter = false)
{
return Diagnostic(
code,
NormalizeNewLines(squiggledText),
arguments,
startLocation,
syntaxNodePredicate,
argumentOrderDoesNotMatter);
}
public static string NormalizeNewLines(XCData data)
{
if (ExecutionConditionUtil.IsWindows)
{
return data.Value.Replace("\n", "\r\n");
}
return data.Value;
}
#endregion
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册