agentleFS
DataDogDataDog/dd-trace-dotnet/.claude/skills/add-lint-rule/SKILL.md

add-lint-rule

Skill572 starsChanged 19 days agoApache-2.0View on GitHub

Add or change lint rules and static analysis in dd-trace-dotnet. Use when adding a lint rule, Roslyn analyzer, diagnostic, BannedSymbols entry, StyleCop/editorconfig severity, CppCheck suppression, or Clang-Tidy check, or when the user asks how to enforce a coding convention at compile time.

2 other projects use a version of this.

Adopted by

Most recently taken up by

  • Other versions2 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 2

    1. jolars/panache★ 246same name
    2. UnknownPlatypus/djangofmt★ 103same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repository6 other files it gives its agents.

The file

We split this skill into the rules it gives an agent

11 rules. About 0 are common, 5 are distinctive, and 6 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈5

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    If the rule is not worth Error, do not add it.

    line 29
  2. Distinctive:

    Read reference.md for file layout, ID allocation, and copy-paste templates.

    line 31
  3. Distinctive:

    If the same idea is both “style” and “maybe faster”, it is style.

    line 46
  4. Distinctive:

    Do not classify a rule as Performance, mention allocations/CPU in the diagnostic message, or sell the PR as a perf win unless at least one …

    line 51
  5. Very specific:

    If the case is not strong enough for Error, do not add the rule.

    line 70
  6. Very specific:

    Do not enable EnableNETAnalyzers / EnforceCodeStyleInBuild globally.

    line 88
  7. Distinctive:

    Do not introduce Roslyn, clang-format CI, or a new analyzer framework.

    line 103
  8. Very specific:

    Default posture: fix the code or add a narrow suppression.

    line 110
  9. Very specific:

    If cleanup is large, use stacked PRs to fix hits, then enable the rule as Error.

    line 137
  10. Distinctive:

    Follow reference.md: analyzer, tests, optional code fix.

    line 147
  11. Very specific:

    Do not add Nuke targets, Azure stages, GitHub workflows, CodeQL config, or static-analysis.datadog.yml entries.

    line 156

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Add Lint Rules / Static Analysis

This repo has no dotnet format or clang-format --check CI job. Managed enforcement is compile-time Roslyn (TreatWarningsAsErrors=true). Do not add a new pipeline stage for a C# rule.

Scope: enforcement of rules and scripts applies only to "core" production code for now (Datadog.Trace and other tracer/src libraries; native tracer/loader/profiler product code). Do not apply new analyzers, Banned APIs, CppCheck/Clang-Tidy tightenings, or helper scripts to tests, helpers, samples, or test-applications unless the user explicitly asks to expand scope.

Still add unit tests for the analyzer itself under Datadog.Trace.Tools.Analyzers.Tests — that is testing the rule, not enforcing it on test code.

New rules are introduced as Error. Info diagnostics are legacy: they are IDE-only, they are ignored, and they must not be used for new rules. If the rule is not worth Error, do not add it.

Read reference.md for file layout, ID allocation, and copy-paste templates. Stay in this file until the rule is classified.

1. Classify the rule first

Pick one primary category. Do not mix them in the diagnostic title, category, or PR description.

CategoryWhat it isSeverity (new rules)Typical mechanism
Correctness / safetyWrong code, security, config-key misuse, infinite-loop hazardErrorCustom Roslyn analyzer
Product conventionMust use a helper, logging shape, duck-type null checkErrorAnalyzer or BannedSymbols.txt
StyleNaming, usings, headers, layout, “looks nicer”Error, or do not add. Prefer existing StyleCop / .editorconfigStyleCop, editorconfig, or analyzer
PerformanceProven hot-path winError only if the win is clear. Otherwise do not addAnalyzer or Banned API, with an evidence-backed message

If the same idea is both “style” and “maybe faster”, it is style. Do not rebrand it as performance to justify blocking PRs.

2. Do not over-claim performance

Do not classify a rule as Performance, mention allocations/CPU in the diagnostic message, or sell the PR as a perf win unless at least one of these is true:

  • The replacement mechanistically avoids a known allocation or extra work on a tracer hot path (span create/tag, instrumentation callback, logging, config read). Example already in-tree: Environment.Version allocates a Version on every get; BannedSymbols.txt says so.
  • You have a benchmark or a tight proof (the API’s implementation obviously allocates; the helper is documented as the zero-alloc path).

Not enough:

  • “Sealing types can improve performance” as a reason to add a rule (DDSEAL001 is a legacy Info diagnostic; do not copy it).
  • Micro-optimizations outside bootstrap/hot paths in AGENTS.md.
  • Style preferences (braces, var, usings, is not null) dressed up as perf.
  • “Might help the JIT / inlining / virtual dispatch” without a measured case.

If the case is not strong enough for Error, do not add the rule. Never use a speculative perf claim to justify shipping it.

3. Choose the mechanism

Managed C# (preferred: Roslyn)

Cheapest fit wins:

  1. Ban a specific API → add a line to repo-root BannedSymbols.txt (RS0030 is already error). This file is currently supplied only to Datadog.Trace.csproj; for another project, include it as AdditionalFiles there or choose a custom analyzer. Message must state the replacement and the real reason (correctness, config, or a clear perf win).
  2. Ban a pattern (syntax, types, logging templates, WithKeys arguments) → custom analyzer under tracer/src/Datadog.Trace.Tools.Analyzers/.
  3. Existing StyleCop / IDE diagnostic, new severity → .editorconfig dotnet_diagnostic.<ID>.severity. Do not invent StyleCop IDs.
  4. Do not enable EnableNETAnalyzers / EnforceCodeStyleInBuild globally. Built-in .NET analyzers are off on purpose (shared/CodeAnalysis.props).

Custom analyzers are referenced only from tracer/src/Directory.Build.props as OutputItemType="Analyzer". New [DiagnosticAnalyzer] types are picked up with no CI YAML changes. BannedSymbols.txt is an AdditionalFiles item on Datadog.Trace.csproj (core), not on test projects.

StyleCop and .editorconfig are broader (they include tests). Do not raise a StyleCop/IDE diagnostic severity repo-wide as a way to lint test code, and do not treat that existing breadth as a reason to extend custom rules or scripts beyond core.

Native C/C++ (light)

Do not introduce Roslyn, clang-format CI, or a new analyzer framework.

AreaPrimary toolsWhere they run
Native tracer + native loaderCppCheckAzure static_analysis_checks_tracer
ProfilerClang-Tidy (fails on error:) and CppCheckAzure static_analysis_tests_profiler (only if profiler changed)

Default posture: fix the code or add a narrow suppression. Do not tighten check sets or remove --suppress= flags unless the user asked for a new native rule and existing noise is acceptable.

  • Tracer/loader suppressions are CLI --suppress= lists on the CppCheckNativeSrc / CppCheckNativeLoader Nuke targets.
  • Profiler CppCheck: profiler/cppcheck-suppressions.txt (--inline-suppr is enabled).
  • Profiler Clang-Tidy: base set is profiler/.clang-tidy. CI -checks (ClangTidyChecks in Build.Profiler.Steps.cs) is appended, not a replacement. Do not add style checks by default; a new check is opt-in and fails the profiler analysis stage on error:.
  • .clang-format is local style only; CI does not verify it.

4. Severity (managed)

Introduce every new diagnostic as Error. Set defaultSeverity: DiagnosticSeverity.Error.

  • Error — the only acceptable severity for a new rule. Fails the build and blocks the PR.
  • Warning — not a softer landing. TreatWarningsAsErrors is true, so it already fails the build. Do not use it as the final state.
  • Info — legacy only (DDSEAL001). IDE-only, ignored in CI, and ignored in practice. Do not add new Info rules. Do not “try Info first and bump later.”

If cleanup is large, use stacked PRs to fix hits, then enable the rule as Error. If it is not worth that, do not add it. Match category to §1 (Usage, CodeQuality, Maintainability, Performance only when §2 is satisfied).

5. Implementation workflow (managed)

  1. Classify (§1) and confirm the perf bar (§2).
  2. Grep DiagnosticId under tracer/src/Datadog.Trace.Tools.Analyzers for the next DDxxxx or start DD<AREA>001 for a family (DDLOG, DDDUCK).
  3. Follow reference.md: analyzer, tests, optional code fix.
  4. Clean up all current hits in the same PR (or in stacked PRs before enabling Error), or the tree will not compile. Prefer real fixes over #pragma / GlobalSuppressions.
  5. Tests: Datadog.Trace.Tools.Analyzers.Tests via CSharpAnalyzerVerifier / CSharpCodeFixVerifier.
  6. Compile: CompileManagedSrc or BuildAndRunManagedUnitTests with a filter on the new test class.

Do not add Nuke targets, Azure stages, GitHub workflows, CodeQL config, or static-analysis.datadog.yml entries.

6. PR description

State: category (style / convention / correctness / performance), diagnostic ID, what is forbidden, the replacement, and why. If performance, cite the allocation/hot-path evidence in one sentence. If style, say so and do not claim runtime impact.

Checklist

  • Category is explicit; style is not labeled Performance
  • Perf claims meet §2; otherwise no perf language in the diagnostic
  • Enforcement is "core" production code only; analyzer unit tests still added
  • Managed: Roslyn analyzer or BannedSymbols.txt, not a new CI job
  • Native: CppCheck and/or existing Clang-Tidy surface only
  • Introduced as Error (Info is legacy and will be ignored)
  • Analyzer tests cover a flag case and a no-flag case
  • Existing violations fixed in the same change
  • Generated-code analysis left None; concurrent execution enabled

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.