Diagnostics
Partly written. §1–§5 were written with milestone M12a of the Lyric 5 plan (slices S2–S5); the rest follows, spec-first: each rule lands here with its conformance case before or with its implementation. Source of the decisions: 11 Tooling and interop W6/W7.
Scope
The diagnostic record, codes and areas, severities, lints and their levels, fixes, the output forms.
1. The text form
What the toolchain writes to the standard error for a person to read (11 G5, C7). A program reads the JSON form instead (§4).
Conformance. The suite reads the head lines (rule 1) of every rejecting case; the layout in the
toolchain's own tests (tests/Lyric.Tests.Core, TextRendererTests).
- A diagnostic begins with its head,
severity[CODE]: message, on a line of its own; the severity iserror,warningorhint. Nothing else in the output begins a line that way. - A diagnostic with a place follows it with the arrow,
--> path:line:column— line and column from 1, the column in characters of the line as the file holds them. - The source lines of its places follow, in a gutter of line numbers: the primary place marked
^, the secondary ones-, each with its label beside or under its mark. The places of one file stand together, in line order; a place in another file has its lines under::: path:line:column. A span across lines is marked on its first line and its last. A tab takes four columns, a wide character two, a combining one none, a control character one stand-in, so a mark stands under what it marks; a line too wide is cut around its marks, with…where it was cut. - A note without a place is the line
= note: …, advice= help: …. A note with a place is a block of its own,note: …with its arrow and lines; a suggested change ishelp: …with the line as it would read after it. - Paths are said relative to the package's root where the file lies under it, else as the file
system has them;
--absolute-pathssays every one as the file system has it. - Colour:
--color auto|always|never.auto, the default, colours where the standard error is a terminal, unlessNO_COLORis set to a non-empty value orTERMisdumb. Colour changes no character of the text. - The diagnostics come in the order of their files, then their places; the order is the same for the same input and is not otherwise a contract. Each is said once.
- Rules 1, 2 and 6 and what rules 3–4 show are normative; the widths, the spacing and the colours chosen are not.
2. What follows from an error
(11 G6)
Conformance. conformance/cases/16-diagnostics/.
- A declaration the parser cannot read whole reports its lexical and syntax errors (
LYR-LEX…,LYR-PAR…) and nothing that follows from them: no finding whose place lies inside it. The other declarations of the file report as they would. - A mistake is said once. What follows from it is not said again: an instance whose type
arguments an annotation got wrong, refused there and not again where an initializer takes them;
the names an or-pattern's alternative does not bind, in one finding; the parser's recovery, which
skips the rest of an unclosed interpolation and reads
T { x: 1 }as the initializer it is (LYR-PAR0037, with=as its fix), a field or an initializer's field that ends with;instead of,, said once at the;and read as the,it stands for —T { a = 1; }after the name of a type is the initializer, not a call with a trailing block (LYR-PAR0064, with,as its fix) —, and acontinue,breakorreturnwhere a value stands, a match arm or a branch of anif, read as the block it belongs in (LYR-PAR0065, with{ continue; }as its fix); a literal's suffix the lexer refused, which the parser does not refuse again; a conformance written twice (LYR-SEM0133), whose second block the calls do not see; a compile-time-only call, said where the program makes it and not again inside the standard library. - A file the parser reads as holding nothing — nesting it does not carry (
LYR-PAR0045) — holds nothing for the rest of the build: neither its missingmainnor a name its importers do not find is said. --max-errors Ndraws the firstNerrors, 50 unless said, all of them for0; what comes after is counted, and one closing line,note: …, says how many errors and other findings were not drawn. The exit code is what it would be without the limit.
3. Codes and the catalogue
Conformance. Every rejecting case names its codes; the catalogue against the compiler in the toolchain's
own tests (tests/Lyric5.Tests, CatalogTests).
- A code is
LYR-, an area —LEX,PAR,RES,SEM,MAC,MIG,CT,CG,PKG,BLD,LNK,CLI,ICE,RT, andIR, retired —, and four digits.LNKholds the link's findings (15 §5.2 rule 12),MIGthe migration's (§6 rule 5). The code and its severity are contract; the message's wording is not. - Every code the toolchain reports stands in Appendix A, generated from the toolchain's catalogue, with its severity, the chapter whose rule it is, and when it is reported. A code no longer reported is retired there: its number is not given to another finding.
lyric explain CODEprints the catalogue's entry — for an error or a warning an explanation, a program that reports it and the program put right. A code is read asLYR-SEM0001,SEM0001orsem0001; one the catalogue does not hold is a usage error (exit 2, 14 §1.1).- A message begins in lowercase and ends without a period; it names the program's own names in quotes.
4. The JSON form
Conformance. The toolchain's own tests (tests/Lyric5.Tests, JsonFormTests; tests/Lyric.Tests.Core,
EventWriterTests).
--jsononbuild,run,check,testandfixwrites, in place of the text form, one JSON object a line on the standard output — a reader takes a line at a time while the command runs. Nothing else is written there, but the output of the programrunruns, after the build's lines; the standard error stays empty. (metadata --jsonis a document of its own, 14 §2.)- Every line holds
"type"and"version", the schema's version,1. A reader skips a type it does not know and refuses a version it does not know. diagnostic:code,severity(error,warning,hint),message,span, the primarylabelwhere there is one,labels(eachspanandlabel),notes(eachkind—note,help,suggestion,category—,message,span, and for a suggestion itsfix:span,text,applicabilitysafeorneeds-review), andrendered, the finding in the text form without colour. A span isnullor{file, start, end},startandendeach{line, column, offset}, the file as the text form says it (§1 rule 5). Every finding is a line — §2's limit is the text form's.artifact: what a build wrote —kind(binary, orlibraryforbuild --lib),name,path; a static library's alsolinkArgs, what a C program links beside it (13 §4 rule 9), an array of strings.test: a test oflyric testas it ends —name,outcome(passed,failed,skipped), and where there is one amessage(why it was skipped, what ended it) and thepanic's code.tests: the run's count —passed,failed,skipped.output: a line the program wrote that is no event —stream(stdout,stderr) andtext.fix: a changelyric fixmade (§6) —path, thelineandcolumnwhere it begins, thecodeof the finding it answers, and thetextput in.summarycloses the command —errorsandwarnings, the findings said — once;runwrites it before its program runs.ice: the toolchain's own failure (LYR-ICE…) —code,message, where it was (while) and itstrace.
5. Lints
Conformance. conformance/cases/16-diagnostics/; the places and the precedence in the toolchain's own tests
(tests/Lyric5.Tests, LintTests).
- Every warning is a lint: a name — lowercase words joined by
-, asunused-variable—, a group, and a level of its own; Appendix A lists them,lyric explain NAMEprints one. The groups areunused,correctness,resources,concurrency,deprecation,style,perfanddocs;warningsnames every lint. A warning that is no lint does not exist. - A lint's level is
allow— it is not said —,warn— it is said as a warning —, ordeny— it is said as an error, with a note that names who denied it, and the build fails (exit 1, 14 §1.1). - A selector names a lint, by its name or its code, a group, or
warnings. One that names nothing is refused: in an attributeLYR-SEM0179, in a manifestLYR-PKG0002, on the command line as a usage error (exit 2) — each with the selector closest to it in spelling, where one is. - Three places, one mechanism:
@Allow,@Warn,@Denywith a selector on a declaration set the level in what the declaration holds (11 §1 rule 13);allow,warn,denyof a package's[lints], each an array of selectors, set it in the package's files (15 §1 rule 4) — a selector in one of them;-A,-W,-Dwith a selector on the command line ofbuild,run,check,expand,test,benchandfixset it in the files of the package built. - Precedence: the narrowest attribute around the finding decides; without one the command line, then the
manifest, then the lint's own level. Within one place the more specific selector decides — a lint over its
group over
warnings—, and of two alike the later. - The warnings of a dependency and of
stdare not said;--warn-depssays them, at the dependency's own levels — but never as errors: another package's levels do not fail this build. Their errors always are. - An
@Allowthat decides no warning — none of its lints is met in what it sits on, or a narrower level decides each — warns:useless-allow(LYR-SEM0180). The@Allowitself never decides that warning. - Warnings as errors is a switch: a profile's
denyWarnings(15 §4 rule 4) and--deny-warningsare-D warningsfor the package built, in front of the command line's own levels — each warning is an error, and its note names the profile. A build script's warnings are the lintbuild-script-warningand denied the same way. - Every lint is held by two cases of the suite: a red one, whose program the lint reads (
warning:its code), and a green one, the same program put right, which compiles in silence (clean:its name). Two lints are held otherwise:reserved-device-nameby its green case alone, as its red program is a file Windows cannot hold — the toolchain's own tests read it where such a file can be made —, anddeprecated-editionby neither, as it names the warning on a construct an edition retires and there is no edition yet.
6. Fixes and lyric fix
(11 G7)
Conformance. The toolchain's own tests (tests/Lyric5.Tests, FixTests): the suite compiles and runs
programs; it does not change them.
- A finding may carry a suggestion: a note with a change — a span and the text put in its place — and
its applicability,
safeorneeds-review. A safe change is the finding's whole remedy and leaves the program's meaning as it was; one that needs a reader is a guess, or a remedy among others. The text form draws the line as the change would leave it (§1); the JSON form carries the change (§4 rule 3). lyric fix [<file.lyr>]makes the safe changes of the findings in the package's own files — under itssrc/; a file alone, its own — and none in a dependency's or instd. A pass checks the program asbuilddoes, without building it, and makes in each file the changes that do not overlap one before them, in source order; the next pass checks the changed text, until a pass finds nothing to change. Then it says what stays — the findings without a safe change, each change that needs a reader among them —, and exits 1 where an error stays, else 0. A secondfixchanges nothing.fixtakes-C,--offline, the lint options of §5 rule 4 — a lint set toallowsays nothing and so suggests nothing — and--json(§4).--dry-runmakes one pass and writes nothing: it prints the changes as a unified diff on the standard output.- The safe changes:
unused-importtakes the import out, or the one name out of its list, or leaves the module alone where the file calls what its blocks add (04 §4 rule 3);unused-varwritesletforvar;useless-trytakes a plaintryout (try?andtry!change the value's type, and acatchis code);needless-returntakes thereturn;out;self-assignmentwritesx++forx = x++;deprecatedwrites the@Deprecated'sreplacementwhere it is a name; a call that writes fewer type arguments than the function has gets a_for each one left out (LYR-SEM0026), the call the inference would have made. A change that needs a reader:unused-import's removal where the import alone holds in the program a module that gives a conformance of a type and an interface it declares neither of, since a constraint that conformance satisfies names nothing of the module;naming's new name, written where the name is declared (its uses are an editor's rename);self-assignment's removal ofx = x, which may stand for an assignment meant otherwise; an unknown name's closest known one (did you mean). - (Informative.)
lyric fix --from-4 [<file.lyr>]migrates a Lyric 4 program — thelyric.jsonof the directory (-C), or the file — to Lyric 5. It reads the program with Lyric 4.6's own front end, frozen in the toolchain, and a program 4.6 refuses is not changed (LYR-MIG0001, exit 1; alyric.json4.6 would not read,LYR-MIG0002, exit 2). The rules of the migration rewrite the program's own files in place — spans of the text, so comments and layout stay —, make alyric.tomlof thelyric.json, and say what they leave to a person as hints of the areaMIG, on the standard error and infix-from-4.txtbeside the manifest or the file.--dry-runprints the changes as a unified diff and writes nothing;--jsondoes not go with it. The migration promises no program that compiles:lyric checksays what is left.