Analyzer
SF0003
Flags ordinary methods whose cyclomatic complexity exceeds 10 so teams do not normalize “hard to reason about” as a routine cost.
Diagnostic contract
Under pressure, complex methods slow diagnosis and increase the chance of editing the wrong branch. That is exactly the problem TwoAmTest is supposed to catch.
An ordinary source method calculates above the fixed cyclomatic complexity threshold of 10.
Method {0} has cyclomatic complexity {1}, which exceeds the limit of 10
/analyzers/sf0003/
When it fires
These are the concrete cases to look for in code review and IDE diagnostics.
- Only ordinary methods are analyzed; constructors and other method kinds are handled elsewhere or ignored.
- The analyzer calculates cyclomatic complexity from the method declaration syntax and reports when the score exceeds 10.
- The diagnostic is advisory today. The right fix depends on extracting intent, not just splitting lines mechanically.
Bad / better example
Use these examples to explain the rule, not just silence it.
Before
public string ResolveStatus(Order order, User user, bool isPriority)
{
if (order is null) return "missing";
if (!user.IsActive) return "blocked";
if (order.IsPaid)
{
if (order.IsPacked)
{
if (order.IsShipped)
{
return order.IsDelayed ? "investigate" : "complete";
}
return isPriority ? "expedite" : "dispatch";
}
return order.HasBackOrder ? "hold" : "pack";
}
return order.RequiresReview ? "review" : "collect-payment";
} The reader has to simulate several branches before they can answer a routine question.
After
public string ResolveStatus(Order order, User user, bool isPriority)
{
if (order is null) return "missing";
if (!user.IsActive) return "blocked";
return order.IsPaid
? ResolvePaidOrderStatus(order, isPriority)
: ResolveUnpaidOrderStatus(order);
}
private static string ResolvePaidOrderStatus(Order order, bool isPriority)
{
if (!order.IsPacked) return order.HasBackOrder ? "hold" : "pack";
if (!order.IsShipped) return isPriority ? "expedite" : "dispatch";
return order.IsDelayed ? "investigate" : "complete";
} The branching still exists, but the path names are easier to scan and change under pressure.
Code fix
There is no automatic code fix for this rule today. Treat it as a prompt to simplify deliberately.
- Start by naming the decision points, not by blindly extracting random blocks.
- If the method is orchestration, consider moving sub-decisions into narrower collaborators.
- Use watch or diff to confirm the simplification improves the broader solution signal, not just one method.
Source and follow-up links
Use these links when you need to validate behavior against the source or connect the docs back to project tracking.
Analyzer implementation
HighComplexityAnalyzer.cs
TrackingIssue #55
Documentation tracker for the analyzer pages and related integration guidance.
FilterTwoAmTest
Method complexity is one of the main reasons a TwoAmTest verdict falls.
Commandwatch
Use watch during refactoring sessions to see if the broader signal improves as complexity drops.