| Property | Value |
|---|---|
| Category | Constraints (JustDummies.Constraints) |
| Severity | 🔵 Info |
| Enabled by default | Yes |
An anchored literal — a prefix, a suffix or a contained value — holds a character the declared character family, subtraction or casing cannot draw.
The chain says two things about its characters. It asks for alphanumerics, then writes a hyphen. Read on its own that is a contradiction, and the library resolves it one specific way: a character constraint governs the characters the generator draws, and a literal you wrote is not drawn, so it is kept exactly as written (ADR-0079 opens in a new tab). This rule names the ambiguity where you wrote it, so you know which reading applies without having to run a draw and look.
It is legal, and it stays legal — that resolution is precisely how a fixed separator is expressed, and the simple way to get ORD-pDc8:
string reference = Any.String().AlphaNumeric().StartingWith("ORD-").WithLengthBetween(8, 20).Generate();
// ORD-7K2P9QW — the hyphen is the separator, and the body stays alphanumeric
So the rule reports a fact, not a fault: that character appears where you wrote it and nowhere else. It is information rather than a warning because the chain is doing something useful — it just is not doing the only thing it could be read as doing.
Reported
AnyString reference = Any.String().AlphaNumeric().StartingWith("ORD-").WithLength(12); // cannot draw the '-'
AnyString batch = Any.String().WithoutNumeric().StartingWith("ORD-1").WithLength(12); // removes the '1'
AnyString slug = Any.String().InUpperCase().StartingWith("ord-").WithLength(12); // cannot draw the 'o'
All three are accepted and all three are reported. The first two are almost certainly deliberate; the third almost certainly is not. The rule does not try to tell them apart — it states what the declaration means and leaves the judgement where it belongs.
Not reported
AnyString digits = Any.String().Numeric().StartingWith("123").WithLength(12); // the family draws every character
AnyString plain = Any.String().StartingWith("ORD-").WithLength(12); // no family: the draw is all of ASCII
AnyString cased = Any.String().InUpperCase().StartingWith("ORD-").WithLength(12); // a casing rules letters; '-' is not one
AnyString pooled = Any.String().AlphaNumeric().OneOf("ORD-1"); // a value set: see below
- A non-constant literal, family or pool.
- A chain split across statements or variables. The chain must be written as one expression: following a generator through a local would need dataflow.
- A conflict-asserting negative test, where the chain is the whole body of a lambda argument.
Why a value set is silent here
Once OneOf(...) is declared there is no filler: the caller supplies the whole value, so nothing is drawn beside the literal and “appears only where you wrote it” has no subject. A pooled value a constraint refuses is not kept-as-written at all — it is removed from the pool, which is a different fact reported at a different severity. JD029 names the values a constraint removed while the chain still draws; JD015 reports it as a 🟠 Warning once every value is gone, because the chain then throws rather than narrows.
That is the whole shape of it: a literal beside a filler is an ambiguity worth a note, a value set a constraint empties is a chain that fails.
Turning it off
It is information, so it costs nothing to leave on. If a codebase writes fixed-prefix formats everywhere and the note stops carrying news:
dotnet_diagnostic.JD033.severity = none
Why a rule reports correct code at all
Because the fact it carries is fixed by the library, not by taste. ADR-0080 opens in a new tab admits such a rule on exactly two grounds: the library names a shorter form exactly equivalent by construction — that is JD031 — or two of the chain’s own declarations contradict each other about the same characters and a recorded decision settles which governs, which is this one. Both are checkable against a source file rather than argued.