Skip to content

Commit

Permalink
ban the use of diagnostic (#1171)
Browse files Browse the repository at this point in the history
* ban the use of diagnostic

* Update src/Neo.SmartContract.Analyzer/Readme.md

---------

Co-authored-by: Shargon <[email protected]>
  • Loading branch information
Jim8y and shargon authored Sep 19, 2024
1 parent 11a01b2 commit a0be8f3
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 24 deletions.
49 changes: 25 additions & 24 deletions src/Neo.SmartContract.Analyzer/AnalyzerReleases.Unshipped.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
### New Rules

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
NC4002 | Type | Error | FloatUsageAnalyzer
NC4003 | Type | Error | DecimalUsageAnalyzer
NC4004 | Type | Error | DoubleUsageAnalyzer
NC4005 | Method | Error | SystemMathUsageAnalyzer
NC4006 | Method | Error | BigIntegerUsageAnalyzer
NC4007 | Method | Error | StringMethodUsageAnalyzer
NC4008 | Usage | Error | BigIntegerCreationAnalyzer
NC4009 | Usage | Info | InitialValueAnalyzer
NC4010 | Usage | Warning | RefKeywordUsageAnalyzer
NC4011 | Usage | Error | LinqUsageAnalyzer
NC4012 | Method | Error | CharMethodsUsageAnalyzer
NC4013 | Type | Error | CollectionTypesUsageAnalyzer
NC4014 | Usage | Warning | VolatileKeywordUsageAnalyzer
NC4015 | Usage | Error | KeywordUsageAnalyzer
NC4017 | Usage | Error | BanCastMethodAnalyzer
NC4018 | Naming | Error | SmartContractMethodNamingAnalyzer
NC4019 | Usage | Error | NotifyEventNameAnalyzer
NC4020 | Naming | Warning | SmartContractMethodNamingAnalyzerUnderline
NC4021 | Usage | Warning | SupportedStandardsAnalyzer
NC4022 | Usage | Warning | BigIntegerUsingUsageAnalyzer
NC4023 | Usage | Error | StaticFieldInitializationAnalyzer
NC4024 | Usage | Error | MultipleCatchBlockAnalyzer
| Rule ID | Category | Severity | Notes |

Check warning on line 3 in src/Neo.SmartContract.Analyzer/AnalyzerReleases.Unshipped.md

View workflow job for this annotation

GitHub Actions / Test

Analyzer release file 'AnalyzerReleases.Unshipped.md' has a missing or invalid release header '| Rule ID | Category | Severity | Notes |' (https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md)
|---------|----------|----------|--------------------------------------------|
| NC4002 | Type | Error | FloatUsageAnalyzer |
| NC4003 | Type | Error | DecimalUsageAnalyzer |
| NC4004 | Type | Error | DoubleUsageAnalyzer |
| NC4005 | Method | Error | SystemMathUsageAnalyzer |
| NC4006 | Method | Error | BigIntegerUsageAnalyzer |
| NC4007 | Method | Error | StringMethodUsageAnalyzer |
| NC4008 | Usage | Error | BigIntegerCreationAnalyzer |
| NC4009 | Usage | Info | InitialValueAnalyzer |
| NC4010 | Usage | Warning | RefKeywordUsageAnalyzer |
| NC4011 | Usage | Error | LinqUsageAnalyzer |
| NC4012 | Method | Error | CharMethodsUsageAnalyzer |
| NC4013 | Type | Error | CollectionTypesUsageAnalyzer |
| NC4014 | Usage | Warning | VolatileKeywordUsageAnalyzer |
| NC4015 | Usage | Error | KeywordUsageAnalyzer |
| NC4017 | Usage | Error | BanCastMethodAnalyzer |
| NC4018 | Naming | Error | SmartContractMethodNamingAnalyzer |
| NC4019 | Usage | Error | NotifyEventNameAnalyzer |
| NC4020 | Naming | Warning | SmartContractMethodNamingAnalyzerUnderline |
| NC4021 | Usage | Warning | SupportedStandardsAnalyzer |
| NC4022 | Usage | Warning | BigIntegerUsingUsageAnalyzer |
| NC4023 | Usage | Error | StaticFieldInitializationAnalyzer |
| NC4024 | Usage | Error | MultipleCatchBlockAnalyzer |
| NC4025 | Usage | Error | SystemDiagnosticsUsageAnalyzer |
1 change: 1 addition & 0 deletions src/Neo.SmartContract.Analyzer/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ This repository contains a set of Roslyn analyzers and code fix providers for Ne
- [BigIntegerUsingUsageAnalyzer.cs](NeoContractAnalyzer/BigIntegerUsingUsageAnalyzer.cs): This analyzer warns about incorrect usage of BigInteger in using statements.
- [StaticFieldInitializationAnalyzer.cs](NeoContractAnalyzer/StaticFieldInitializationAnalyzer.cs): This analyzer checks for proper initialization of static fields in smart contracts.
- [MultipleCatchBlockAnalyzer.cs](NeoContractAnalyzer/MultipleCatchBlockAnalyzer.cs): This analyzer checks for multiple catch blocks in try statements.
- [SystemDiagnosticsUsageAnalyzer.cs](NeoContractAnalyzer/SystemDiagnosticsUsageAnalyzer.cs): This analyzer detects and reports usage of System.Diagnostics namespace, which is not supported in Neo smart contracts.

## How to Use

Expand Down
71 changes: 71 additions & 0 deletions src/Neo.SmartContract.Analyzer/SystemDiagnosticsUsageAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Immutable;

namespace Neo.SmartContract.Analyzer
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class SystemDiagnosticsUsageAnalyzer : DiagnosticAnalyzer
{
public const string DiagnosticId = "NC4025";

private static readonly DiagnosticDescriptor Rule = new(
DiagnosticId,
"Usage of System.Diagnostics is not allowed in Neo smart contracts",
"Neo smart contracts do not support System.Diagnostics: {0}",
"Namespace",
DiagnosticSeverity.Error,
isEnabledByDefault: true);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } =
[Rule];

public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.UsingDirective, SyntaxKind.IdentifierName);
}

private void AnalyzeNode(SyntaxNodeAnalysisContext context)
{
switch (context.Node)
{
case UsingDirectiveSyntax usingDirective:
AnalyzeUsingDirective(context, usingDirective);
break;
case IdentifierNameSyntax identifierName:
AnalyzeIdentifierName(context, identifierName);
break;
}
}

private void AnalyzeUsingDirective(SyntaxNodeAnalysisContext context, UsingDirectiveSyntax usingDirective)
{
var name = usingDirective.Name?.ToString();
if (name == "System.Diagnostics" || name?.StartsWith("System.Diagnostics.") == true)
{
var diagnostic = Diagnostic.Create(Rule, usingDirective.GetLocation(), name);
context.ReportDiagnostic(diagnostic);
}
}

private void AnalyzeIdentifierName(SyntaxNodeAnalysisContext context, IdentifierNameSyntax identifierName)
{
var symbolInfo = context.SemanticModel.GetSymbolInfo(identifierName);
var symbol = symbolInfo.Symbol;

if (symbol != null && symbol.ContainingNamespace != null)
{
var namespaceName = symbol.ContainingNamespace.ToDisplayString();
if (namespaceName == "System.Diagnostics" || namespaceName.StartsWith("System.Diagnostics."))
{
var diagnostic = Diagnostic.Create(Rule, identifierName.GetLocation(), namespaceName);
context.ReportDiagnostic(diagnostic);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using VerifyCS = Microsoft.CodeAnalysis.CSharp.Testing.XUnit.AnalyzerVerifier<
Neo.SmartContract.Analyzer.SystemDiagnosticsUsageAnalyzer>;

namespace Neo.SmartContract.Analyzer.UnitTests
{
[TestClass]
public class SystemDiagnosticsUsageAnalyzerUnitTests
{
[TestMethod]
public async Task UsingSystemDiagnostics_ShouldReportDiagnostic()
{
var test = """
using System.Diagnostics;

class TestClass
{
public void TestMethod()
{
// Some code
}
}
""";

var expected = VerifyCS.Diagnostic(SystemDiagnosticsUsageAnalyzer.DiagnosticId)
.WithLocation(1, 1)
.WithArguments("System.Diagnostics");

await VerifyCS.VerifyAnalyzerAsync(test, expected);
}

[TestMethod]
public async Task UsingSystemDiagnosticsSubNamespace_ShouldReportDiagnostic()
{
var test = """
using System.Diagnostics.Tracing;

class TestClass
{
public void TestMethod()
{
// Some code
}
}
""";

var expected = new[]
{
VerifyCS.Diagnostic(SystemDiagnosticsUsageAnalyzer.DiagnosticId)
.WithSpan(1, 1, 1, 34).WithArguments("System.Diagnostics.Tracing"),
VerifyCS.Diagnostic(SystemDiagnosticsUsageAnalyzer.DiagnosticId)
.WithSpan(1, 26, 1, 33).WithArguments("System.Diagnostics")
};

await VerifyCS.VerifyAnalyzerAsync(test, expected);
}

[TestMethod]
public async Task UsingSystemDiagnosticsClass_ShouldReportDiagnostic()
{
var test = """
using System;

class TestClass
{
public void TestMethod()
{
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
}
}
""";

var expected = new[]
{
VerifyCS.Diagnostic(SystemDiagnosticsUsageAnalyzer.DiagnosticId)
.WithSpan(7, 28, 7, 37).WithArguments("System.Diagnostics"),
VerifyCS.Diagnostic(SystemDiagnosticsUsageAnalyzer.DiagnosticId)
.WithSpan(7, 73, 7, 82).WithArguments("System.Diagnostics")
};

await VerifyCS.VerifyAnalyzerAsync(test, expected);
}

[TestMethod]
public async Task UsingOtherNamespace_ShouldNotReportDiagnostic()
{
var test = """
using System;
using System.Collections.Generic;

class TestClass
{
public void TestMethod()
{
List<int> list = new List<int>();
}
}
""";

await VerifyCS.VerifyAnalyzerAsync(test);
}

[TestMethod]
public async Task UsingConditionalAttribute_ShouldReportDiagnostic()
{
var test = """
using System.Diagnostics;

class TestClass
{
[Conditional("ALPHA")]
public void TestMethod()
{
// Some code
}
}
""";

var expected = new[]
{
VerifyCS.Diagnostic(SystemDiagnosticsUsageAnalyzer.DiagnosticId)
.WithSpan(1, 1, 1, 26).WithArguments("System.Diagnostics"),
VerifyCS.Diagnostic(SystemDiagnosticsUsageAnalyzer.DiagnosticId)
.WithSpan(5, 6, 5, 17).WithArguments("System.Diagnostics")
};

await VerifyCS.VerifyAnalyzerAsync(test, expected);
}

[TestMethod]
public async Task UsingFullyQualifiedConditionalAttribute_ShouldReportDiagnostic()
{
var test = """
class TestClass
{
[System.Diagnostics.Conditional("ALPHA")]
public void TestMethod()
{
// Some code
}
}
""";

var expected = VerifyCS.Diagnostic(SystemDiagnosticsUsageAnalyzer.DiagnosticId)
.WithSpan(3, 25, 3, 36)
.WithArguments("System.Diagnostics");

await VerifyCS.VerifyAnalyzerAsync(test, expected);
}
}
}

0 comments on commit a0be8f3

Please sign in to comment.