delphi-unit-backtrace
A partir de um .dproj e do nome da unit, rastreia usos reversos até o DPR e gera grafo HTML navegável, relatório e log. Delphi 13.
- Active · last change 9-18-2026
- ★ 3 on GitHub
README
Delphi Unit Backtrace
Ferramenta console para mapear tudo que um projeto Delphi usa a partir do DPR ou responder quem usa uma unit e por quais caminhos ela chega ao projeto. Somente o .dproj é obrigatório; --unit seleciona o modo de backtrace. O resultado contém um relatório em result.txt, um grafo navegável em graph.html, as ligações em graph.dot e decisões de análise em analysis.log.
Baixar e executar
Baixe o ZIP Win64 ou Win32 na página da versão mais recente e extraia os arquivos. No diretório do projeto, execute:
D:\Ferramentas\UnitBacktrace.exe --project MeuERP.dprojEsse comando gera o mapa completo das dependências alcançáveis a partir do DPR. Para o backtrace de uma unit específica:
No mapa do projeto, a visão inicial agrupa os arquivos pelo primeiro diretório, mantendo ramos como src reunidos. Clique nos blocos para abrir somente o ramo escolhido. O botão Pastas (visão geral) sempre retorna ao primeiro nível; o botão fixo Voltar para o nível anterior restaura a pasta, o nível de agrupamento e a visão anteriores, inclusive depois de abrir as units de uma pasta. A lista lateral carrega os arquivos somente quando uma pasta é expandida, para manter projetos grandes responsivos.
D:\Ferramentas\UnitBacktrace.exe --project MeuERP.dproj --unit uExtratorSem --output, o mapa fica em analysis-output\<projeto>-<identificador>\project-map; o backtrace fica em analysis-output\<projeto>-<identificador>\<unit>. O identificador deriva do caminho do .dproj, para distinguir projetos homônimos em pastas diferentes. Com --output, usa exatamente a pasta informada. Se a análise for parcial (código de saída 3), consulte analysis.log. O ZIP inclui as licenças e avisos das dependências.
UnitBacktrace.exe --project "D:\MeuERP\MeuERP.dproj" --unit uExtrator --output "D:\Analise"O programa procura fontes recursivamente na pasta do projeto e avalia DCC_UnitSearchPath, DCC_IncludePath e DCC_Define com o MSBuild do Delphi 13 para a configuração e plataforma selecionadas. Em uma máquina com Delphi 13, também lê o Search Path e o Browsing Path registrados na IDE para localizar fontes de bibliotecas. Os padrões vêm do .dproj; use --platform Win32|Win64 e --config Debug|Release para selecioná-los. Se fontes de uma biblioteca estiverem fora desses caminhos, --source-root DIR acrescenta uma raiz recursiva; a opção pode ser repetida. Para analisar somente os caminhos do projeto, use --no-global-path.
Uma raiz adicional amplia o escopo da análise; avisos de outras units da biblioteca também podem aparecer no log.
Também encontra arquivos referenciados diretamente pelo DPR, usa MainSource quando o DPR tem outro nome e procura includes relativos e em DCC_IncludePath. Lê uses em interface e implementation com DelphiAST, identifica cada arquivo pelo caminho resolvido e preserva os ramos do grafo. Quando o DelphiAST rejeita uma sintaxe, a ferramenta tenta extrair os uses por tokens, registra o fallback e marca o resultado como parcial. Nomes curtos como Classes são resolvidos usando a ordem de namespaces do projeto. A enumeração textual é limitada a 10.000 caminhos para evitar explosão combinatória; o DOT conserva todas as ligações alcançáveis. Ciclos e ramos sem consumidores são identificados.
O código separa modelos e interfaces (Reverse.Domain), leitura de fontes (Reverse.AST), caminhos do projeto e da IDE (Reverse.MSBuild e Reverse.DelphiPaths), descoberta de fontes (Reverse.Scope), resolução de referências (Reverse.Analysis), travessia do grafo (Reverse.Graph) e saída/log (Reverse.Output e Reverse.Log). Parser, avaliação MSBuild, provedor de caminhos globais e log usam interfaces para permitir substituição em testes e outras implementações.
Extensão para a IDE
O package UnitBacktraceIDE.bpl integra os dois modos ao Delphi 13 sem depender do executável. Console e extensão compilam o mesmo núcleo Reverse.Runner; a IDE fornece o projeto e a unit atuais, executa a análise em segundo plano, mostra progresso e cancelamento e abre o HTML ao concluir. Consulte IDE.md para compilação, instalação e uso.
Compilar e testar no Delphi 13
git clone --recurse-submodules https://github.com/regyssilveira/delphi-unit-backtrace.git
cd delphi-unit-backtrace
.\tools\Build.ps1 -Platform Win64
.\tools\Build.ps1 -Tests -Platform Win64
.\bin\Win64\UnitBacktraceTests.exe
.\bin\Win64\UnitBacktrace.exe --project .\tests\fixtures\Small\Small.dproj --no-global-path --output .\bin\project-map-output
node .\tests\ProjectMap.Render.test.js .\bin\project-map-output\graph.html
.\bin\Win64\UnitBacktrace.exe --project .\tests\fixtures\Small\Small.dproj --unit Target --no-global-path --output .\bin\workflow-test
node .\tests\Visual.Trace.test.js .\bin\workflow-test\graph.html
node .\tests\Visual.Render.test.js .\bin\workflow-test\graph.htmlO script detecta o Delphi 13 (BDS 37.0) pela variável de ambiente BDS ou pelo RootDir registrado em HKCU/HKLM e confirma que o compilador da plataforma existe. Os projetos .dproj também estão na raiz. DUnitX acompanha o RAD Studio 13; o DelphiAST é um submódulo Git. O teste opcional com Node.js verifica a lógica da cadeia no JavaScript gerado.
O executável para testes locais fica em bin\Win64\UnitBacktrace.exe. A análise gera result.txt, graph.dot, graph.html e analysis.log na pasta de saída. Abra graph.html no navegador para explorar o grafo sem instalar dependências. A busca lista até 30 units encontradas e centraliza a seleção. Ao selecionar um arquivo, o grafo destaca uma cadeia de declarações uses até o DPR; se não houver essa ligação, destaca uma cadeia até um arquivo do projeto. Os botões Anterior e Próximo percorrem cada ligação da cadeia com arquivo, seção e linha, sem limite de passos; Copiar arquivo:linha copia a declaração selecionada. Você pode isolar a cadeia, ver ligações diretas ou mostrar todas as rotas resolvidas até o DPR. O zoom, o ajuste da cadeia ou do grafo visível, o arraste e o filtro visual por seção ajudam a percorrer grafos grandes.
No modo padrão, sem --unit, a análise começa no DPR e inclui somente arquivos realmente alcançáveis por declarações uses, mesmo quando estão no Search Path ou em --source-root. O HTML abre na visão Pastas, agrega a quantidade de relações entre diretórios e permite alternar para Units. O controle Agrupar diretórios detecta a profundidade real da árvore e oferece todos os níveis encontrados — 1, 2, 3 e assim por diante — além do caminho completo. Clicar num grupo com subpastas entra no próximo nível; Voltar um nível retorna ao agrupamento anterior. Ao chegar numa pasta física, o clique abre apenas suas units, evitando tentar renderizar milhares de arquivos de uma vez. Os quadros exibem nomes mais longos e mostram o caminho completo ao apontar o mouse. A lateral apresenta um resumo sem duplicações, com arquivos e relações de entrada e saída por pasta física, seguido da árvore Pastas e arquivos. Selecionar uma unit muda para o grafo detalhado filtrado nesse arquivo. A busca aceita pasta, unit ou caminho completo, e o filtro separa DPR, interface e implementation.
O gráfico abre em modo progressivo com a unit alvo e seus consumidores diretos. No topo, Visão progressiva recupera essa visualização limpa e Grafo completo mostra todos os arquivos para partir do conjunto inteiro e reduzi-lo com busca, filtros, ocultação de ramos ou isolamento de rotas. A lista Rotas encontradas agrupa cadeias por DPR, projeto, biblioteca, ausência de consumidor e ciclo; selecionar uma entrada isola a cadeia. Os controles permitem expandir o próximo nível, expandir até o DPR ou até o final, recolher e ocultar um ramo. Um duplo clique isola rapidamente a rota de uma unit, enquanto apontar o mouse destaca sua cadeia e atenua as ligações não relacionadas. O layout reordena as units pela posição média dos vizinhos para reduzir cruzamentos e mantém DPR, arquivos finais do projeto e raízes de biblioteca na coluna de destinos.
O painel de simulação permite marcar uma ou mais declarações uses para verificar se ainda resta uma rota resolvida da unit alvo até o DPR. A simulação não altera arquivos fonte; o filtro por seção também não muda seu cálculo. Outro painel lista os consumidores diretos da unit selecionada que participam das rotas como declarações a revisar. Referências ambíguas ou não resolvidas potencialmente ligadas ao alvo aparecem como incertas; outras ficam no log. Em grafos com mais de 250 arquivos, a abertura mostra os consumidores diretos e a seleção expande a exploração; o grafo completo continua disponível. Um resultado parcial exige conferir o log antes de alterar código.
Arquivos descobertos são identificados pela origem: pasta do projeto, referência explícita do projeto, Search Path do projeto, Search Path global da IDE ou --source-root. As cadeias recebem um destino estruturado: DPR, arquivo do projeto, raiz de biblioteca, sem consumidor conhecido ou ciclo. No HTML, Mostrar usos fora do DPR isola os ramos que continuam somente em bibliotecas ou arquivos desvinculados da entrada do projeto; o filtro Origem dos arquivos permite inspecionar cada grupo. Mostrar todas as rotas restaura o conjunto completo. O console e o result.txt apresentam a contagem de cada tipo e o relatório textual marca os finais com [DPR], [PROJECT], [LIBRARY], [NO CONSUMER] ou [CYCLE].
A saída elimina linhas exatamente iguais de caminhos e evidências, além de declarações de nós e ligações repetidas no DOT. Relações com arquivo, seção ou linha diferentes continuam separadas. Projetos com muitos ramos podem produzir milhares de caminhos distintos mesmo após essa limpeza; a lista textual mantém o limite de 10.000 caminhos, enquanto o grafo conserva as ligações alcançáveis.
Durante a execução, o console mostra uma barra de 24 posições, a porcentagem e a contagem de cada etapa com total conhecido; a montagem do grafo aparece como etapa em andamento até terminar. Em um terminal interativo, a barra atualiza na mesma linha e só a conclusão fica no histórico. Quando a saída é redirecionada, as atualizações ficam em linhas separadas para preservar um log legível. A frequência é limitada a uma atualização a cada 500 ms por etapa, além do início e do fim. Ao concluir, o resumo conta consumidores diretos, declarações uses e ligações alcançáveis até o DPR, e informa se a análise é parcial. Exemplo do histórico após a conclusão:
Preparando projeto e descobrindo arquivos...
Arquivos descobertos: 4 | Win32 | Debug
Analisando arquivos: [------------------------] 0% 0/4
Analisando arquivos: [########################] 100% 4/4
Resolvendo dependencias: [------------------------] 0% 0/5
Resolvendo dependencias: [########################] 100% 5/5
Montando grafo reverso...
Gravando resultado e log...
Concluido: D:\Analise
Abra no navegador: D:\Analise\graph.htmlLog e códigos de saída
O log UTF-8 registra INFO, WARN, ERROR e DEBUG, incluindo candidatos para a unit alvo, cada relação encontrada, o arquivo escolhido para cada referência, fallback do parser ou MSBuild, falhas e caminhos de busca sem resolução. Código 0: análise concluída sem fallback, falhas, referências não resolvidas ou ambíguas; 1: erro fatal; 2: argumentos ausentes; 3: resultado gerado com fallback, fontes ou referências sem resolução ou ambíguas. Relações não resolvidas ficam no log e não entram no grafo.
Alcance atual
Esta versão analisa dependências declaradas em uses. Ela não verifica se um símbolo da unit é realmente chamado. O parser considera os símbolos condicionais do projeto e os símbolos Win32/Win64 da plataforma selecionada. Se a avaliação MSBuild falhar, o log registra msbuild-fallback e a leitura textual dos caminhos e símbolos pode incluir configurações não selecionadas; variáveis $(...) sem valor conhecido são sinalizadas. O teste sintético reproduzível possui 2.202 fontes distribuídos entre o projeto e três bibliotecas externas. Os testes DUnitX cobrem parser, fallback, includes, caminhos e símbolos condicionais MSBuild, resolução de arquivos e namespaces, grafo e saída console.
Exemplo de saída
O projeto pequeno em tests/fixtures/Small reproduz a saída sem bibliotecas externas. Execute a partir da raiz do repositório.
.\bin\Win64\UnitBacktrace.exe --project .\tests\fixtures\Small\Small.dproj --unit Target --no-global-path --output .\bin\readme-example-outputOs trechos abaixo mostram as linhas principais. Os prefixos dos caminhos absolutos foram encurtados e os horários do log foram omitidos.
result.txt mostra os caminhos reversos até o DPR e a linha que declarou cada uses.
Target: Target | ...\Small\Target.pas
Project entry: Small
Parsed: 4 | AST fallback: 0 | Failed: 0 | Unresolved: 0 | Ambiguous: 0 | Reachable edges: 5
Reverse paths:
Target -> A -> B -> Small [DPR]
Target -> A -> Small [DPR]
Target -> B -> Small [DPR]
Evidence:
Target -> A | interface | ...\Small\A.pas:3 | used file: ...\Small\Target.pasgraph.dot preserva todas as ligações alcançáveis; cada nó usa o caminho físico do arquivo.
digraph UnitBacktrace {
rankdir=LR;
"...\\Target.pas" -> "...\\A.pas" [label="interface:3"];
"...\\Target.pas" -> "...\\B.pas" [label="interface:3"];
"...\\A.pas" -> "...\\B.pas" [label="interface:3"];
"...\\A.pas" -> "...\\Small.dpr" [label="program:4"];
"...\\B.pas" -> "...\\Small.dpr" [label="program:5"];
}analysis.log registra plataforma, avaliação de caminhos, dependências e resumo.
[INFO] platform | Win32
[INFO] config | Debug
[INFO] msbuild-evaluated | DCC_UnitSearchPath | 1 entries
[DEBUG] dependency | ...\Small\A.pas:3 | A uses Target
[INFO] complete | 4 parsed; 0 fallback; 0 failed; 0 unresolved; 0 ambiguous; 5 reachable edges; 0 ms[DPR] indica que o caminho alcançou a entrada do projeto; interface:3 indica a seção e a linha da declaração.
Licença
O código desta ferramenta está sob Apache-2.0. O submódulo DelphiAST mantém suas licenças originais: MPL-2.0 para DelphiAST e avisos MPL-1.1 em quatro arquivos do SimpleParser usados no executável. Consulte THIRD_PARTY_LICENSES.md e NOTICE para atribuições e acesso às fontes. O histórico Git preserva os commits anteriores sob MIT.

