Fenner
Compilador

"Diagnósticos: --diag, códigos e --explain"

Três estilos de mensagem (plain, rich, json), códigos estáveis FE/FW/FH em cada diagnóstico e fc --explain para entendê-los.

O que é e por que existe#

Uma mensagem de erro em texto livre é boa para ler e ruim para ferramentas, para a busca na internet e para o CI. Três recursos resolvem isso, e nenhum muda o comportamento padrão: sem eles a saída é, byte a byte, a de sempre.

RecursoPara quê
--diag=plain|rich|jsono formato das mensagens
--diag-codesum código estável em cada mensagem
--explain <código>uma explicação em português, com um exemplo mínimo que dispara o código

Estilos: --diag#

Para o mesmo programa (nameof(Totall), nome com erro de digitação), gerado pelo compilador:

texto
$ fc e08.fxp                      # plain: o formato de sempre (padrão)
e08.fxp(4,18): Erro: nameof: "Totall" não está declarado

$ fc e08.fxp --diag=rich          # rich: a linha do fonte e um ^ sob a coluna
e08.fxp(4,18): Erro: nameof: "Totall" não está declarado
  WriteLn(nameof(Totall));
                 ^~~~~~

$ fc e08.fxp --diag=json --diag-codes     # json: UMA linha por diagnóstico
{"file":"e08.fxp","line":4,"col":18,"severity":"error","message":"nameof: \"Totall\" não está declarado","code":"FE2070"}
  • Ligar: na linha de comando (--diag=rich; valor inválido é erro, saída 1) ou no .config com Config All DiagStyle rich. A linha de comando vence o .config.
  • rich: tabulação vira 4 espaços e o ^ conta células, não bytes (UTF-8 não desalinha); o ~ sublinha o resto do identificador; linhas com mais de 120 células são janeladas com ….
  • json: severity é error, warning ou hint; o campo code aparece com --diag-codes. Sai sem a linha N erros. Serve a adaptadores de IDE e ao CI.
  • O leitor de problemas do VS Code ($mycompiler-erro…) funciona com rich e não com json.

Códigos estáveis: --diag-codes#

texto
$ fc --diag-codes prog.fxp
e04.fxp(11,13): Erro FE2421: "Conn" não tem parâmetro chamado "ATime"

FE é erro, FW aviso, FH dica. No json vira o campo "code". Também vale Config All DiagCodes on no .config (e --diag-codes=off desliga). Mensagens sem posição (opção desconhecida, aviso de config) também ganham código; no --symbols o diagnóstico leva code, e no --lsp o publishDiagnostics leva code, source: "fc" e um codeDescription.href que aponta para o erros.md.

Um número já dado nunca é reaproveitado, mas pode ser subdividido: uma mensagem que casava um molde genérico pode passar a ter o código de um molde mais específico. Por isso um teste que compara códigos deve ser regerado quando o compilador sobe de versão.

Explicando: --explain#

texto
$ fc --explain FE2420
FE2420
  Molde: argumento posicional depois de argumento nomeado na chamada %: escreva primeiro os
  posicionais e depois os "Nome := valor"
  (o "%" do molde é a parte que muda de caso para caso)

Numa chamada com argumentos nomeados ("Nome := valor"), os posicionais vêm PRIMEIRO e os nomeados
depois, em qualquer ordem. [...]

Exemplo:
    program Exemplo;
    procedure Conecta(Host: LString; Porta: Int32 = 80; Timeout: Int32 = 30);
    ...
    begin
      Conecta(Porta := 8080, 'x');
    end.

Mostra o molde da mensagem, uma explicação em português e um programa mínimo que dispara o código. Cerca de 75 códigos têm texto; um código sem texto mostra só o molde, e um código desconhecido dá Erro: código de mensagem desconhecido: "FE9998". A lista completa de códigos fica no erros.md do compilador.

Tabela de códigos que aparecem nestas páginas#

CódigoOnde
FE0651defer fora de bloco
FE0804, FE1100case e choice não exaustivos
FE0840downin sem GetReverseEnumerator
FE1457closure que captura var/out e pode escapar
FE1484static_assert falhou
FE2070nameof de nome inexistente
FE2080?. sobre tipo que sempre tem valor (nullable)
FE2290, FE2484concatenação e fatias
FE2400–FE2404propagação ?
FE2420–FE2428argumentos nomeados
FE2450–FE2459readonly e init

Armadilhas#

  • Limitações do catálogo: o código vem de um catálogo de moldes (diagcodes.txt); uma mensagem que nenhum molde cobre sai como FE9999 até o catálogo ser atualizado. O fc acha o catálogo em MYCOMPILER_DIAGCODES, ao lado do fc.exe ou em <fc>\..\src; a distribuição deve levar diagcodes.txt e diagexplain.txt.
  • No rich, caracteres largos (CJK, emoji) contam 1 célula e o ^ pode desalinhar. O trecho do fonte é relido do disco: não há trecho para fonte protegido ou arquivo que sumiu.
  • Mensagens sem linha e coluna (RTL não encontrada, erros do clang/ligador) continuam em texto puro em qualquer estilo.

Veja também#