claude-skills/engineering-team/skills/code-reviewer/assets/sample_csharp_smells.cs
Claude 7dc7fae1fe
feat(code-reviewer): raise quality score 54.8/D → 72.5/B- with assets, expected outputs, README
Addresses the Phase 3 quality_scorer roadmap items from the plugin audit:
adds the bundled fixtures, sample outputs, and quick-reference README that
the scorer expects, without diverging from the project's minimal-frontmatter
SKILL.md convention.

assets/:
- sample_csharp_smells.cs: a C# fixture with every pattern the skill
  detects (async void, blocking on Task, swallowed Exception, undisposed
  IDisposable, new HttpClient(), missing await, null-forgiving, hardcoded
  connection string, unsafe, dynamic, #pragma warning disable,
  [SuppressMessage], SQL concatenation), each smell labelled inline
- sample_csharp_clean.cs: the same code refactored per the standards in
  references/coding_standards.md — verifies the analyzer produces 0 HIGH
  smells on idiomatic code

expected_outputs/:
- sample_csharp_smells_quality.json: committed analyzer output for the
  smells fixture (F/45, 3 HIGH smells)
- sample_csharp_clean_quality.json: committed analyzer output for the
  clean fixture (A/98, 0 HIGH smells)

These act as a regression harness: diff the live output against the
committed JSON to detect any behaviour change in the analyzer.

scripts/code_quality_checker.py:
- Add _strip_csharp_comments() that removes // line and /* */ block
  comments before running C#-specific regex detectors. Fixes false
  positives where comment prose ("// FIX: await instead of .Result")
  matched a detection pattern.

SKILL.md:
- New ## Examples section pointing at the fixtures + showing how to
  reproduce the expected output with diff
- TOC updated to list "C# / .NET Review Notes" and "Examples"

README.md (new):
- Quick-reference card with how-to, 3 worked examples (one per script),
  pointer to fixtures, pointer to references

Phase re-scores after this change:
- Structure: 86.4/GOOD → 91.3/EXCELLENT (+4.9)
- Quality:   54.8/D    → 72.5/B-       (+17.7)
- Scripts:   3/3 PASS (unchanged)
- Security:  0/0       (unchanged)
2026-05-23 02:24:39 +00:00

78 lines
2.7 KiB
C#

// Sample C# file demonstrating every C#-specific pattern the code-reviewer
// skill detects. Each smell is labelled inline. This file is NOT meant to
// compile cleanly — it is a fixture for code_quality_checker.py and
// pr_analyzer.py.
//
// Run:
// python scripts/code_quality_checker.py assets/sample_csharp_smells.cs
//
// Expected output: see expected_outputs/sample_csharp_smells_quality.json
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Diagnostics.CodeAnalysis;
namespace Sample
{
public class UserService
{
// [hardcoded_secrets] hardcoded connection string with password
public string ConnectionString = "Server=prod;Database=app;Password=hunter2;";
// [csharp_async_void] async void on a non-event-handler signature
public async void HandleClick(object sender, EventArgs e)
{
// [csharp_blocking_async] .Result blocks on Task in a sync context
var data = FetchAsync().Result;
// [console_log] Debug.WriteLine output statement
Debug.WriteLine(data);
}
public async Task<string> FetchAsync()
{
// [csharp_new_httpclient] new HttpClient() in method body
// [csharp_undisposed_idisposable] HttpClient not in `using`
var client = new HttpClient();
try
{
// [csharp_missing_await] FireAndForgetAsync() returns Task, never awaited
FireAndForgetAsync();
// [csharp_null_forgiving] `user!.Name` forces null-forgiving
var name = user!.Name;
return await client.GetStringAsync("https://api.example/data");
}
catch (Exception)
{
// [csharp_swallowed_exception] empty catch (Exception)
}
return null!;
}
// [loose_type] C# `dynamic` overuse
public dynamic Untyped = null;
// [csharp_unsafe_block] `unsafe` modifier on a method
public unsafe void Pointers()
{
int x = 0;
int* p = &x;
}
// [analyzer_disable] #pragma warning disable
#pragma warning disable CS0168
// [analyzer_disable] [SuppressMessage] attribute
[SuppressMessage("Style", "IDE0060")]
public string GetName(SqlConnection conn, int id)
{
// [csharp_undisposed_idisposable] SqlCommand without `using`
// [sql_concatenation] string concatenation builds SQL with user input
var cmd = new SqlCommand("SELECT name FROM users WHERE id = " + id, conn);
return cmd.ExecuteScalar().ToString();
}
}
}