Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BannedApiAnalyzers: Support banning base types #7052

Merged
merged 2 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Analyzers;
using System.Collections.Immutable;
using System.Collections.Generic;
using System.Linq;

namespace Microsoft.CodeAnalysis.CSharp.Analyzers
{
Expand All @@ -11,8 +14,12 @@ public sealed class CSharpSymbolIsBannedInAnalyzersAnalyzer : SymbolIsBannedInAn
{
protected override SyntaxKind XmlCrefSyntaxKind => SyntaxKind.XmlCrefAttribute;

protected override ImmutableArray<SyntaxKind> BaseTypeSyntaxKinds => ImmutableArray.Create(SyntaxKind.BaseList);

protected override SymbolDisplayFormat SymbolDisplayFormat => SymbolDisplayFormat.CSharpShortErrorMessageFormat;

protected override SyntaxNode GetReferenceSyntaxNodeFromXmlCref(SyntaxNode syntaxNode) => ((XmlCrefAttributeSyntax)syntaxNode).Cref;

protected override IEnumerable<SyntaxNode> GetTypeSyntaxNodesFromBaseType(SyntaxNode syntaxNode) => ((BaseListSyntax)syntaxNode).Types.Select(t => (SyntaxNode)t.Type);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.

Imports System.Collections.Immutable
Imports Microsoft.CodeAnalysis.Analyzers
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Expand All @@ -15,6 +16,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Analyzers
End Get
End Property

Protected Overrides ReadOnly Property BaseTypeSyntaxKinds As ImmutableArray(Of SyntaxKind)
Get
Return ImmutableArray.Create(SyntaxKind.InheritsStatement, SyntaxKind.ImplementsStatement)
End Get
End Property

Protected Overrides ReadOnly Property SymbolDisplayFormat As SymbolDisplayFormat
Get
Return SymbolDisplayFormat.VisualBasicShortErrorMessageFormat
Expand All @@ -25,5 +32,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Analyzers
Return CType(syntaxNode, XmlCrefAttributeSyntax).Reference
End Function

Protected Overrides Function GetTypeSyntaxNodesFromBaseType(syntaxNode As SyntaxNode) As IEnumerable(Of SyntaxNode)
If syntaxNode.IsKind(SyntaxKind.InheritsStatement) Then
Return CType(syntaxNode, InheritsStatementSyntax).Types
ElseIf syntaxNode.IsKind(SyntaxKind.ImplementsStatement) Then
Return CType(syntaxNode, ImplementsStatementSyntax).Types
Else
Return ImmutableArray(Of SyntaxNode).Empty
End If
End Function

End Class
End Namespace
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.BannedApiAnalyzers;
using System.Collections.Immutable;
using System.Linq;
using System.Collections.Generic;

namespace Microsoft.CodeAnalysis.CSharp.BannedApiAnalyzers
{
Expand All @@ -11,8 +14,12 @@ public sealed class CSharpSymbolIsBannedAnalyzer : SymbolIsBannedAnalyzer<Syntax
{
protected override SyntaxKind XmlCrefSyntaxKind => SyntaxKind.XmlCrefAttribute;

protected override ImmutableArray<SyntaxKind> BaseTypeSyntaxKinds => ImmutableArray.Create(SyntaxKind.BaseList);

protected override SymbolDisplayFormat SymbolDisplayFormat => SymbolDisplayFormat.CSharpShortErrorMessageFormat;

protected override SyntaxNode GetReferenceSyntaxNodeFromXmlCref(SyntaxNode syntaxNode) => ((XmlCrefAttributeSyntax)syntaxNode).Cref;

protected override IEnumerable<SyntaxNode> GetTypeSyntaxNodesFromBaseType(SyntaxNode syntaxNode) => ((BaseListSyntax)syntaxNode).Types.Select(t => (SyntaxNode)t.Type);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public abstract class SymbolIsBannedAnalyzerBase<TSyntaxKind> : DiagnosticAnalyz

protected abstract SyntaxNode GetReferenceSyntaxNodeFromXmlCref(SyntaxNode syntaxNode);

protected abstract ImmutableArray<TSyntaxKind> BaseTypeSyntaxKinds { get; }

protected abstract IEnumerable<SyntaxNode> GetTypeSyntaxNodesFromBaseType(SyntaxNode syntaxNode);

protected abstract SymbolDisplayFormat SymbolDisplayFormat { get; }

public override void Initialize(AnalysisContext context)
Expand Down Expand Up @@ -149,6 +153,10 @@ private void OnCompilationStart(CompilationStartAnalysisContext compilationConte
context => VerifyDocumentationSyntax(context.ReportDiagnostic, GetReferenceSyntaxNodeFromXmlCref(context.Node), context),
XmlCrefSyntaxKind);

compilationContext.RegisterSyntaxNodeAction(
context => VerifyBaseTypesSyntax(context.ReportDiagnostic, GetTypeSyntaxNodesFromBaseType(context.Node), context),
BaseTypeSyntaxKinds);

return;

bool IsBannedSymbol([NotNullWhen(true)] ISymbol? symbol, [NotNullWhen(true)] out BanFileEntry? entry)
Expand Down Expand Up @@ -376,6 +384,19 @@ void VerifyDocumentationSyntax(Action<Diagnostic> reportDiagnostic, SyntaxNode s
VerifySymbol(reportDiagnostic, symbol, syntaxNode);
}
}

void VerifyBaseTypesSyntax(Action<Diagnostic> reportDiagnostic, IEnumerable<SyntaxNode> typeSyntaxNodes, SyntaxNodeAnalysisContext context)
{
foreach (var typeSyntaxNode in typeSyntaxNodes)
{
var symbol = context.SemanticModel.GetSymbolInfo(typeSyntaxNode, context.CancellationToken).Symbol;

if (symbol is ITypeSymbol typeSymbol)
{
VerifyType(reportDiagnostic, typeSymbol, typeSyntaxNode);
}
}
}
}

protected sealed class BanFileEntry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,62 @@ End Class
await VerifyBasicAnalyzerAsync(visualBasicSource, bannedText, GetBasicResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "Banned", ""));
}

[Fact]
public async Task DiagnosticReportedForInterfaceImplementationAsync()
{
var bannedText = "T:N.IBanned//comment here";

var csharpSource = @"
namespace N
{
interface IBanned { }
class C : {|#0:IBanned|}
{
}
}";

await VerifyCSharpAnalyzerAsync(csharpSource, bannedText, GetCSharpResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "IBanned", ""));

var visualBasicSource = @"
Namespace N
Interface IBanned : End Interface
Class C
Implements {|#0:IBanned|}
End Class
End Namespace";

await VerifyBasicAnalyzerAsync(visualBasicSource, bannedText, GetBasicResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "IBanned", ""));

}

[Fact]
public async Task DiagnosticReportedForClassInheritanceAsync()
{
var bannedText = "T:N.Banned//comment here";

var csharpSource = @"
namespace N
{
class Banned { }
class C : {|#0:Banned|}
{
}
}";

await VerifyCSharpAnalyzerAsync(csharpSource, bannedText, GetCSharpResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "Banned", ""));

var visualBasicSource = @"
Namespace N
Class Banned : End Class
Class C
Inherits {|#0:Banned|}
End Class
End Namespace";

await VerifyBasicAnalyzerAsync(visualBasicSource, bannedText, GetBasicResultAt(0, SymbolIsBannedAnalyzer.SymbolIsBannedRule, "Banned", ""));

}

[Fact]
public async Task DiagnosticReportedForBannedApiLineWithWhitespaceThenCommentAtTheEndAsync()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.

Imports System.Collections.Immutable
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports Microsoft.CodeAnalysis.BannedApiAnalyzers
Expand All @@ -15,6 +16,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.BannedApiAnalyzers
End Get
End Property

Protected Overrides ReadOnly Property BaseTypeSyntaxKinds As ImmutableArray(Of SyntaxKind)
Get
Return ImmutableArray.Create(SyntaxKind.InheritsStatement, SyntaxKind.ImplementsStatement)
End Get
End Property

Protected Overrides ReadOnly Property SymbolDisplayFormat As SymbolDisplayFormat
Get
Return SymbolDisplayFormat.VisualBasicShortErrorMessageFormat
Expand All @@ -25,5 +32,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.BannedApiAnalyzers
Return CType(syntaxNode, XmlCrefAttributeSyntax).Reference
End Function

Protected Overrides Function GetTypeSyntaxNodesFromBaseType(syntaxNode As SyntaxNode) As IEnumerable(Of SyntaxNode)
If syntaxNode.IsKind(SyntaxKind.InheritsStatement) Then
Return CType(syntaxNode, InheritsStatementSyntax).Types
ElseIf syntaxNode.IsKind(SyntaxKind.ImplementsStatement) Then
Return CType(syntaxNode, ImplementsStatementSyntax).Types
Else
Return ImmutableArray(Of SyntaxNode).Empty
End If
End Function

End Class
End Namespace
4 changes: 2 additions & 2 deletions src/Test.Utilities/CSharpCodeFixVerifier`2+Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Testing;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Testing.Verifiers;
using Microsoft.CodeAnalysis.Testing;

namespace Test.Utilities
{
public static partial class CSharpCodeFixVerifier<TAnalyzer, TCodeFix>
where TAnalyzer : DiagnosticAnalyzer, new()
where TCodeFix : CodeFixProvider, new()
{
public class Test : CSharpCodeFixTest<TAnalyzer, TCodeFix, XUnitVerifier>
public class Test : CSharpCodeFixTest<TAnalyzer, TCodeFix, DefaultVerifier>
{
static Test()
{
Expand Down