Skip to content

Commit

Permalink
analyze the catch statement (#1158)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jim8y authored Sep 6, 2024
1 parent 6039fc5 commit 88689a5
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ NC4020 | Naming | Warning | SmartContractMethodNamingAnalyzerUnderline
NC4021 | Usage | Warning | SupportedStandardsAnalyzer
NC4022 | Usage | Warning | BigIntegerUsingUsageAnalyzer
NC4023 | Usage | Error | StaticFieldInitializationAnalyzer
NC4024 | Usage | Error | MultipleCatchBlockAnalyzer
48 changes: 48 additions & 0 deletions src/Neo.SmartContract.Analyzer/MultipleCatchBlockAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
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 MultipleCatchBlockAnalyzer : DiagnosticAnalyzer
{
public const string DiagnosticId = "NC4024";

private static readonly LocalizableString Title = "Multiple catch blocks are not allowed in Neo smart contracts";
private static readonly LocalizableString MessageFormat = "Neo smart contracts only support a single catch block: {0}";
private static readonly LocalizableString Description = "Neo smart contracts are limited to one catch block per try statement.";
private const string Category = "Usage";

private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(
DiagnosticId,
Title,
MessageFormat,
Category,
DiagnosticSeverity.Error,
isEnabledByDefault: true,
description: Description);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);

public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSyntaxNodeAction(AnalyzeTryStatement, SyntaxKind.TryStatement);
}

private static void AnalyzeTryStatement(SyntaxNodeAnalysisContext context)
{
var tryStatement = (TryStatementSyntax)context.Node;

if (tryStatement.Catches.Count > 1)
{
var diagnostic = Diagnostic.Create(Rule, tryStatement.GetLocation(), tryStatement.Catches.Count);
context.ReportDiagnostic(diagnostic);
}
}
}
}
3 changes: 2 additions & 1 deletion src/Neo.SmartContract.Analyzer/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ This repository contains a set of Roslyn analyzers and code fix providers for Ne
- [SupportedStandardsAnalyzer.cs](NeoContractAnalyzer/SupportedStandardsAnalyzer.cs): This analyzer checks for correct implementation of supported standards in smart contracts.
- [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.

## How to Use

Expand All @@ -41,4 +42,4 @@ Contributions to improve existing analyzers or add new ones are welcome. Please

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Verifier = Microsoft.CodeAnalysis.CSharp.Testing.XUnit.AnalyzerVerifier<Neo.SmartContract.Analyzer.MultipleCatchBlockAnalyzer>;

namespace Neo.SmartContract.Analyzer.UnitTests
{
[TestClass]
public class MultipleCatchBlockAnalyzerUnitTest
{
[TestMethod]
public async Task MultipleCatchBlockAnalyzer_DetectMultipleCatchBlocks()
{
const string sourceCode = """
using System;

public class TestClass
{
public void TestMethod()
{
try
{
// Some code that might throw an exception
}
catch (FormatException ex)
{
// Handle general exception
}
catch (Exception ex)
{
// Handle specific exception
}
}
}
""";

var expected = Verifier.Diagnostic(MultipleCatchBlockAnalyzer.DiagnosticId)
.WithSpan(7, 9, 18, 10)
.WithArguments("2");

await Verifier.VerifyAnalyzerAsync(sourceCode, expected);
}
}
}

0 comments on commit 88689a5

Please sign in to comment.