deprecated, experimental, tip e todo
Marcas que o compilador transforma em avisos e dicas no ponto de uso, e os níveis de {$config}.
O que é e por que existe#
Quando uma API muda, avisar no lugar onde ela é usada é o que ajuda quem chama. Quatro marcas escrevem isso na própria declaração:
| Marca | Para quê | Sai | Padrão |
|---|---|---|---|
deprecated | obsoleto: não use mais | no uso | Aviso |
experimental | a assinatura ainda muda | no uso | Aviso |
tip | sugestão ("use X no lugar") | no uso | Dica |
todo | pendência de quem escreve | na declaração ou no comando | Dica |
type
TBox = class
FSize: Int32 todo 'trocar por Int64';
FOld: Int32 deprecated 'use FSize';
procedure OldShow; deprecated; // sem texto: só "obsoleta"
procedure Beta; experimental 'a assinatura ainda muda';
procedure Slow; tip 'use Fast quando souber o tamanho';
end class;
const
cOldLimit = 10 deprecated 'use cNewLimit';A marca vem depois do tipo, valor ou cabeçalho e antes do ;, sozinha ou com um texto entre aspas. Pode marcar rotina e método, tipo (class, record, enum…), campo, property, constante e variável. No tipo, a marca vem depois do end.
program Marks;
// Demo: marcas que o compilador transforma em mensagens no PONTO DE USO.
// deprecated -> Aviso: "use outra coisa"
// experimental -> Aviso: "a API ainda muda"
// tip -> Dica: sugestão para quem chama
// todo -> Dica: pendência de quem escreve (aparece onde a marca foi escrita)
// O programa roda normalmente: as mensagens saem na COMPILAÇÃO (veja o LEIAME).
type
TBox = class
FSize: Int32 todo 'trocar por Int64';
FOld: Int32 deprecated 'use FSize';
procedure Show;
procedure OldShow; deprecated; // sem texto: só "obsoleta"
procedure Beta; experimental 'a assinatura ainda muda';
procedure Slow; tip 'use Fast quando souber o tamanho';
procedure Fast;
procedure Clean; todo 'liberar o buffer interno';
end class;
const
cOldLimit = 10 deprecated 'use cNewLimit';
cNewLimit = 20;
procedure TBox.Show;
begin
WriteLn('show ', FSize);
end procedure;
procedure TBox.OldShow;
begin
Show; // dentro de algo deprecated não há aviso
end procedure;
procedure TBox.Beta;
begin
WriteLn('beta');
end procedure;
procedure TBox.Slow;
begin
WriteLn('lento');
end procedure;
procedure TBox.Fast;
begin
WriteLn('rápido');
end procedure;
procedure TBox.Clean;
begin
todo 'ainda não libera nada'; // todo também funciona como comando e não gera código
WriteLn('limpo');
end procedure;
var
LBox: TBox;
begin
LBox := TBox.Create;
LBox.FSize := 7;
LBox.FOld := 1; // Aviso: obsoleta
LBox.OldShow; // Aviso: obsoleta
LBox.Beta; // Aviso: experimental
LBox.Slow; // Dica: tip
LBox.Fast;
LBox.Clean;
WriteLn(cOldLimit); // Aviso: obsoleta
// {$config ...} muda o nível da mensagem daqui para a frente: ignore, hint, warning, error, fatal
{$config Deprecated ignore}
LBox.OldShow; // calado
{$config Deprecated warning}
{$config Experimental hint}
LBox.Beta; // agora só uma Dica
{$config Tip ignore}
LBox.Slow; // calado
end.show 7
beta
lento
rápido
limpo
10
show 7
beta
lentoDemo 50. O programa roda normalmente; as mensagens saem na COMPILAÇÃO (veja abaixo).
As mensagens da compilação do demo:
Marks.fxp(61,8): Aviso: "FOld" e' obsoleta (deprecated): use FSize
Marks.fxp(63,8): Aviso: "Beta" e' experimental: a assinatura ainda muda
Marks.fxp(64,8): Dica: "Slow" tem uma dica (tip): use Fast quando souber o tamanho
Marks.fxp(18,22): Dica: pendência (todo): liberar o buffer internoTrocando o nível com {$config}#
{$config Deprecated ignore} // ignore, hint, warning, error ou fatal
{$config Experimental hint}
{$config Tip ignore}Vale do ponto da diretiva para a frente. Padrões: Deprecated e Experimental = aviso; Tip e Todo = dica. error lista todos os usos como erro (serve para barrar um build); fatal para na hora, sem a cascata de erros: com dois usos obsoletos, error mostra os dois e fatal só o primeiro. Isso vale também para {$message fatal '…'}.
Uma mensagem de deprecated promovida a erro mantém o código de aviso (FW0011), mas é tratada como erro.
todo em detalhe#
todo também é comando (todo 'tratar o erro de abertura';) e declaração solta (todo 'revisar este módulo';). Não gera código. fc --todo <projeto|unit|pasta> lista todas as pendências, inclusive os comentários // TODO: x:
Marks.fxp(11,18): pendência [todo/declaração] em TBox / FSize: trocar por Int64
Marks.fxp(18,22): pendência [todo/declaração] em TBox / Clean: liberar o buffer interno
Marks.fxp(52,3): pendência [todo/comando] em TBox.Clean: ainda não libera nada
3 pendência(s): 3 de todo, 0 de comentárioOpções: --todo-format=text|json|md, --todo-out=arq, --no-todo-comments e --todo-fail-on-any (sai com 1 se houver alguma, para integração contínua). {$config TodoUse on} (padrão off) também avisa no uso de um símbolo marcado com todo.
Regras de silêncio e armadilhas#
- O aviso sai no uso, não na declaração. Não há aviso em código gerado pelo compilador, em arquivo da RTL, nem quando o uso está dentro de algo igualmente marcado da mesma espécie (a rotina corrente e as que a envolvem). O silêncio é por espécie:
deprecateddentro de algoexperimentalavisa. Recursão não conta como uso externo. tipetodosão palavras contextuais: só marcam quando seguidas de;ou de texto entre aspas.var tip: Int32;e um métodoTipcontinuam comuns.- Só em minúsculas:
DeprecatedouOVERRIDEnão são reconhecidos e a compilação falha. - Fora de alcance: apelido de tipo nomeado (
type A = B deprecated), constante tipada, módulo inteiro e membro individual de enum não aceitam a marca. Herança (class(TOld)),is/ase o castTOld(x)ainda não avisam. platforme o{$DEPRECATED ON/OFF}do Delphi continuam sendo apenas engolidos.
Veja também#
- Avisos opt-in de código sem uso, Diretivas.
- Demo
50-marcas-aviso.