EyeSpy 1.0.5

dotnet add package EyeSpy --version 1.0.5
                    
NuGet\Install-Package EyeSpy -Version 1.0.5
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EyeSpy" Version="1.0.5" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EyeSpy" Version="1.0.5" />
                    
Directory.Packages.props
<PackageReference Include="EyeSpy" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EyeSpy --version 1.0.5
                    
#r "nuget: EyeSpy, 1.0.5"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EyeSpy@1.0.5
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EyeSpy&version=1.0.5
                    
Install as a Cake Addin
#tool nuget:?package=EyeSpy&version=1.0.5
                    
Install as a Cake Tool

EyeSpy: A static code analysis library for C#

This is a small set of custom Roslyn analyzers to enforce coding standards for C# projects. These analyzers provide compile-time errors to help maintain code quality and consistency.

Diagnostic Analyzers

Here is a list of the analyzers implemented in this library.


SPY01: Disallow multiple top-level classes in the same file

Each C# file should contain only one top-level class declaration. Placing multiple classes in a single file can lead to maintainability issues and violates widely accepted conventions.

Example:

public class FirstClass { }

public class SecondClass { } // ❌ Move SecondClass to a separate file

Keeping one class per file improves traceability and simplifies version control diffs—especially in large teams or open-source projects.


SPY02: Disallow "ID" as an identifier name suffix

Use Id instead of ID to comply with .NET naming conventions. This enhances readability and aligns with idiomatic C# standards.

Examples:

public int UserID { get; set; }        // ❌ Should be UserId
private string customerID;             // ❌ Should be customerId
void ProcessOrder(int orderID) { }     // ❌ Should be orderId

This rule is cosmetic but contributes to cleaner, more uniform code—especially beneficial in APIs, domain models, and shared libraries.


SPY03: Async method names must have Async suffix

Async methods must end with the Async suffix. This is a standard convention that clearly signals asynchronous behavior to developers.

Examples:

public async Task ProcessData() { }      // ❌ Should be ProcessDataAsync
public async Task<string> GetUser() { }  // ❌ Should be GetUserAsync

This convention helps prevent confusion when synchronous and asynchronous methods coexist.


SPY04: Namespace hierarchy must align to folder structure

A file’s namespace should reflect its folder structure to support intuitive project organization and navigation.

Examples:

Assume the file path is:

C:\Projects\MyApp\Controllers\Api\UserController.cs

Valid namespaces:

namespace MyApp.Controllers.Api    // ✅
namespace MyApp.Controllers        // ✅
namespace MyApp                    // ✅

Invalid examples:

namespace Controllers.Api          // ❌ Missing project root
namespace Foo.Bar                  // ❌ Entirely mismatched
namespace MyApp.Services           // ❌ Diverges from folder structure

This alignment improves onboarding, searchability, and long-term maintainability. While tools like VS Code and Visual Studio support similar rules (e.g., IDE0130), this rule allows for more flexibility in shallow namespace declarations.


SPY05: Async calls must be awaited

Un-awaited async calls are a common source of bugs. Always await async methods to ensure proper exception handling and task completion.

Example:

public async Task ProcessDataAsync()
{
    WorkAsync();               // ❌ Should be: await WorkAsync();
    var result = WorkAsync();  // ❌ Should be: var result = await WorkAsync();
}

This rule reduces the likelihood of dropped tasks and makes the async control flow explicit and reliable.


Installation

  1. Add as NuGet Package Reference: Add the analyzer project as a package reference to your target project:

    <PackageReference Include="EyeSpy" Version="1.0.5">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
    </PackageReference>
    
  2. Add as Project Reference: Reference the analyzer project directly:

    <ProjectReference Include="path/to/EyeSpy.csproj">
      <OutputItemType>Analyzer</OutputItemType>
    </ProjectReference>
    
  3. Add as Analyzer Reference: Reference the compiled analyzer assembly:

    <Analyzer Include="path/to/EyeSpy.dll" />
    

Configuration

Disabling Specific Analyzers

You can disable individual analyzers using the diagnostic ID:

In .editorconfig:

[*.cs]
dotnet_diagnostic.SPY01.severity = none  # Disable multiple classes check
dotnet_diagnostic.SPY02.severity = suggestion  # Change to suggestion

In project file:

<PropertyGroup>
  <NoWarn>$(NoWarn);SPY01;SPY02</NoWarn>
</PropertyGroup>

Using pragma directives:

#pragma warning disable SPY01
public class FirstClass { }
public class SecondClass { } // No error
#pragma warning restore SPY01

Suppressing Warnings

Use SuppressMessage attribute for specific suppressions:

[SuppressMessage("Naming", "SPY02:Avoid 'ID' suffix; use 'Id'", Justification = "Legacy compatibility")]
public string LegacyUserID { get; set; }

Requirements

  • .NET Standard 2.0 or higher
  • Microsoft.CodeAnalysis.CSharp 4.14.0
  • Microsoft.CodeAnalysis.Analyzers 4.14.0

Development

To extend or modify these analyzers:

  1. Clone the repository
  2. Open in VS Code or your preferred IDE
  3. Add new analyzer classes following the existing patterns
  4. Update diagnostic codes (use SPYXX format)
  5. Add corresponding tests
  6. Update this README with new analyzer documentation

Testing

Test your analyzers using the Microsoft.CodeAnalysis.Testing framework or by adding them to the TestDiagnostics project to verify the expected diagnostics are triggered.

License

This project is licensed under the MIT License.

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.5 579 7/21/2025