[Delphi] Visualizador de DataSets com Open Tools API – Evaluate

Olá, programadores!
No artigo anterior, observamos a facilidade ao criar um novo menu na IDE do RAD Studio com as Interfaces do Open Tools API. No artigo de hoje, focaremos na codificação do método Execute para extrair os dados do DataSet em runtime para depois exibi-los em uma Grid. Vamos continuar?

Evaluate

Para compreender como o visualizador irá funcionar, vamos, primeiramente, executar alguns passos manuais.

Uma das formas mais simples de salvar os dados de um DataSet em runtime, considerando que os breakpoints estão devidamente posicionados, é acionar a janela de Evaluate/Modify (CTRL + F7) e escrever a seguinte instrução:

Em seguida, é necessário utilizar uma ferramenta que exiba os dados de um arquivo XML organizados em uma Grid.

O objetivo do nosso wizard é automatizar todo este procedimento, ou seja, acessar a operação de Evaluate do debugger, salvar os dados e carregá-los em um formulário de modo automático, dispensando qualquer interação.

Para isso, faremos uso de três novas Interfaces nesse artigo: IOTAEditorServices, IOTADebuggerServices e IOTAThread. Com a primeira, identificaremos o texto selecionado no editor de código. Com a segunda, acessaremos o processo na IDE referente à depuração. Com a última, simularemos a operação de Evaluate do depurador. Embora essa explicação nos dê a impressão de uma codificação extensa e trabalhosa, veremos, a seguir, que é bem simples.

1) Configurar o caminho do arquivo temporário

O método SaveToFile da classe TClientDataSet exige o diretório e o nome do arquivo que será gerado. No nosso caso, já que este arquivo será temporário, pensei em salvá-lo justamente na pasta temporária do usuário, que recebe o nome de “AppData” no Windows. No entanto, não precisamos mais de funções específicas para buscar este diretório. O próprio Delphi já possui uma função nativa para essa finalidade, contida na unit System.IOUtils:

2) Identificar o texto selecionado no editor de código

Na unit “ToolsAPI.pas”, existe uma variável global chamada BorlandIDEServices, que corresponde aos serviços compartilhados pela IDE, como o editor de código. O nosso wizard precisa acessar estes serviços, portanto, utilizaremos essa variável global, aplicando alguns castings para as Interfaces mencionadas no início do artigo.

Pois bem, para identificar o texto selecionado, ou melhor, o “bloco” selecionado no editor, basta chamar o método GetBlock da Interface IOTAEditorServices:

3) Montar a expressão que será interpretada pelo debugger

Desejamos que os dados do DataSet selecionado no editor (variável TextoSelecionado) sejam exportados para um arquivo (variável ArquivoDados), certo? Bom, como essas duas variáveis já estão preenchidas, montar a expressão não será nada complicado:

Neste ponto, vale ressaltar que “expressão” corresponde ao texto que digitamos no campo “Expression” da janela Evaluate/Modify (CTRL + F7) quando estamos depurando uma aplicação.

4) Acessar a thread do debugger

Essa etapa é muito importante. O serviço de depuração do Delphi (que nos fornece a possibilidade de examinar breakpoints, inspecionar objetos, monitorar variáveis, entre outros) trabalha em uma thread enquanto o programa está em tempo de execução. Para executar o Evaluate, obteremos o ponteiro dessa thread através do método CurrentThread da Interface IOTADebuggerServices:

5) Executar o Evaluate!

Até agora, usei bastante a palavra “Evaluate” no artigo. Pela tradução, que significa “Avaliar”, fica fácil compreender o nosso propósito: solicitaremos ao Delphi que avalie a nossa expressão, da mesma forma como ocorre na janela Evaluate/Modify. Porém, antes de finalmente executar a função Evaluate da Interface IOTAThread, acho importante estudarmos a sua assinatura:

Eis uma breve explicação dos parâmetros:

  • ExprStr: expressão que será avaliada;
  • ResultStr: texto de resultado da avaliação;
  • ResultStrSize: tamanho do texto de resultado da avaliação;
  • CanModify (out): indica se a expressão pode ser alterada;
  • AllowSideEffects: indica se o “avaliador” pode invocar outras funções para completar a avaliação;
  • FormatSpecifiers: especifica formatadores para o resultado;
  • ResultAddr (out): endereço em memória do resultado;
  • ResultSize (out): tamanho em memória do resultado (SizeOf);
  • ResultVal (out): valor em memória do resultado;

Já que executaremos um SaveToFile, que é um procedure, não é necessário considerar o texto do resultado da avaliação, logo, o segundo e terceiro parâmetros podem ser ignorados. Este texto seria necessário apenas se estivéssemos avaliando uma propriedade do DataSet, como State, por exemplo.

Além disso, como há quatro parâmetros out na assinatura do método, também devemos criar as variáveis para preenchê-los:

Com essa instrução, o arquivo já será criado! 🙂

6) Verificando o retorno da avaliação

Em algumas situações, a função Evaluate pode falhar devido a erros levantados pelo próprio depurador. Em vista dessa possibilidade, é prudente verificar o retorno da função para que possamos prosseguir com a visualização dos dados do DataSet. Para isso, utilizaremos uma variável do tipo enumerado TOTAEvaluateResult, no qual comporta os seguintes valores: erOK, erDeferred, erError ou erBusy.

Continuaremos a execução somente se a variável for diferente dos dois últimos valores.

Hora de juntar tudo!

Após seguir os seis passos, o resultado final da nossa codificação é apresentado abaixo (com comentários):

Por que o método “AbrirVisualizador” está comentado?
Este método é justamente o que faremos na terceira parte dessa série de artigos! 😀

Hora de testar!

Para demonstrar a geração do arquivo através do nosso wizard, fiz um teste rápido. Criei um novo projeto, inseri um TClientDataSet e preenchi alguns dados em memória. No evento de clique de um botão, adicionei um breakpoint em uma linha que contém o DataSet e executei o projeto. Na parada do breakpoint, em tempo de execução, selecionei o DataSet:

Texto selecionado no Code Editor do Delphi

Em seguida, acionei o wizard pelo menu Help > Help Wizards > Visualizar DataSet.

Ao navegar até a pasta temporária do usuário, observe que o arquivo “Dados.xml” foi gerado conforme esperado!

Demonstração do arquivo de dados gerado pelo wizard

Para finalizar a compreensão do que fizemos até agora, observe, com atenção, os destaques da imagem da janela Evaluate/Modify e as relações com a nossa codificação:

Janela de Evaluate/Modify durante o debugging no Delphi

  • (1) Thread que obtemos pelo método CurrentThread;
  • (2) Expressão para avaliação;
  • (3) Função Evaluate da Interface IOTAThread;
  • (4) Texto do resultado (segundo parâmetro da função Evaluate).

 

Volto amanhã com a criação do formulário para visualização dos dados.

Boa noite, leitores!


[Delphi] Visualizador de DataSets com Open Tools API – Pacote
[Delphi] Visualizador de DataSets com Open Tools API – Evaluate
[Delphi] Visualizador de DataSets com Open Tools API – Formulário
[Delphi] Visualizador de DataSets com Open Tools API – Notificador


 

André Celestino