dssl / native /spec /09-diagnostics.md
EHS-Studio's picture
Claude Sonnet 5.5
v0.16.3: native DSSL spec, and the seven bugs writing it found
9da4a9b
|
Raw History Blame Contribute Delete
4.88 kB

9. Diagnostics

DSSL is loud. A mistake is an error with a place and a hint, not a silent no-op.

9.1 Records

  • DIA-1. A diagnostic is { file, line, message, hint? }. hint is omitted (not null) when there is none. Messages and hints are English text and are compared exactly by the conformance tests, so an implementation MUST use the wording in this spec.
  • DIA-2. Errors mean something was wrong and was dropped or replaced. A source is ok when it has no errors. Warnings mean the source compiles and runs but is probably not what the author meant. Warnings never change ok.
  • DIA-3. A tool may offer a strict mode that treats warnings as failures (dssl check --strict). That is a tool choice, not part of resolving.
  • DIA-4. Errors from the parser come first, then errors from the resolver, each in the order found.
  • DIA-5. Deduplication. At the end of resolving, errors with the same file, line and message are reduced to one, keeping the last occurrence, and the order of the others is unchanged.
  • DIA-6. Unknown words are errors, never noise. A word that is left over after a construct has used what it understands is an error, not ignored.
  • DIA-7. A lint or any other helper MUST NOT be able to break a compile. If it fails, its warnings are dropped and everything else stands.

9.2 Where each message is defined

Each message appears in the chapter that defines the construct it belongs to, in code font. The conformance corpus (chapter 10) covers every message at least once. Appendix B is generated from the reference implementation and lists every message template, so a gap between this spec and the corpus shows up as a failing check.

9.3 Did-you-mean

  • DIA-8. didYouMean(word, candidates) returns the best candidate, or nothing:
    1. If the word or the candidate list is empty, return nothing.
    2. Lowercase the word. For each candidate in order, skipping empty ones, compute the Levenshtein distance (insert, delete, substitute, each cost 1) between the lowercase word and the lowercase text of the candidate.
    3. Keep the first candidate with the smallest distance. A later candidate with an equal distance does not replace it.
    4. The tolerance is max(2, floor(length of the word / 3)). If the smallest distance is larger, return nothing. Otherwise return the candidate as text, in its original case.
  • DIA-9. The order of the candidates is the order of the sets and lists in appendix A, which is the insertion order in the reference implementation. A different order can change which of two equally close words is suggested, so implementations MUST keep it.

9.4 Warnings the resolver emits

Where Message starts with
5.3, nested word near a state word "<w>" compiled as a descendant selector
6.3, row and column words two words in ..., "<w>" is written twice in ..., "<w>" has nowhere to go ...
6.6, gradient: and another image "<sel>" sets the background image twice
7.4, animation shorthand animation "<v>" references no motion ..., <prop> does nothing here ...
2.7, raw { } raw { } is verbatim CSS, so this line needs a ";" at the end
same-rule display clash "<prop>:" expands to display: <v>, which overrides the earlier ...
  • DIA-10. Display clash. Inside one rule, when a semantic property that expands to display (row, column, grid, stack) comes after an explicit display: with a different value, the warning is "<via>:" expands to display: <new>, which overrides the earlier "display: <old>" (line <n>) in the same rule - later wins, so the earlier one is dead. At most 400 warnings of this kind are kept per file. Overrides across different rules are the cascade at work and get no warning.
  • DIA-11. Raw semicolons. In a raw { } body (comments blanked), a line that looks like name: value, does not end in ;, {, } or ,, and is followed by another declaration line or a line starting with }, is a warning at the line of that declaration inside the block.

9.5 Lint

A lint pass runs on the finished rules and adds warnings. It covers text contrast (WCAG ratio, 4.5 for body text, 3 for large text), an outline removed from something you can tab to with no focus-visible replacement, and an explicit width or height under 24px on a button or link. It looks only at unconditional rules, follows tokens, alpha and color-mix, and is defined by lint.js.

  • DIA-12. A Level 2 implementation MAY omit the lint pass. It then declares lint: false, and conformance tests compare warnings with the lint warnings removed. A lint warning is one whose message starts with text contrast is, starts with the focus outline is removed, or ends with the smallest target WCAG 2.2 allows.