Construtores do Projeto Incremental

Um construtor de projeto incremental é um objeto que manipula os recursos em um projeto de um modo específico. Os construtores do projeto incremental são freqüentemente utilizados para aplicar uma transformação em um recurso para produzir um recurso ou artefato de outro tipo.

Os plug-ins contribuem com construtores de projeto incremental para a plataforma a fim de implementar transformações de recurso especializado. Por exemplo, as JDT (Java Development Tools) definem um construtor de projeto incremental que compila um arquivo de origem Java em um arquivo de classe sempre que um arquivo seja incluído ou modificado em um projeto Java. Também mantém controle dos arquivos dependentes e os recompila quando necessário.

A partir do ponto de vista da API, a plataforma define dois tipos básicos de construções:

As construções incrementais são semeadas com um delta de alteração de recurso. O delta reflete o efeito de rede de todas as alterações de recurso desde que o construtor fez a última construção do projeto. Esse delta é similar ao que é utilizado dentro dos eventos de alteração de recurso.

Os projetos podem ser periodicamente limpos pelo usuário para forçar uma reconstrução de um projeto completo na próxima vez em que uma construção incremental for executada nesse projeto. Limpar um projeto remove as informações de construção como marcadores de problemas e arquivos de classe.

Os construtores são melhor entendidos pelo exemplo. O compilador JDT Java é dirigido por um construtor de projeto incremental Java que recompila os arquivos em um projeto que são afetados por alterações. Quando uma construção completa é acionada, (ou uma construção incremental depois de uma limpeza) todos os arquivos .java no projeto são compilados. Quaisquer problemas de compilação encontrados são incluídos como marcadores de problemas nos arquivos .java afetados. Quando uma construção incremental é disparada, o construtor compila novamente de forma seletiva os arquivos .java incluídos, alterados ou de alguma forma afetados que são descritos no delta do recurso e atualiza os marcadores de problemas, se necessário. Qualquer arquivo .class ou marcador que não seja mais apropriado é removido.

As construções incrementais possuem benefícios de desempenho óbvios para projetos com centenas ou milhares de recursos, a maioria deles não podem ser alterados em nenhum ponto dados no tempo.

A objeção técnica para construção incremental é determinar exatamente o que é necessário ser reconstruído. Por exemplo, o estado interno mantido pelo construtor Java inclui coisas como um gráfico de dependência e uma lista de problemas de compilação informados. Essas informações são utilizadas durante uma construção incremental para identificar quais classes precisam ser recompiladas em resposta a uma alteração em um recurso Java.

Embora a estrutura básica para a construção seja definida na plataforma, o trabalho real é feito no código do construtor. Os padrões para a implementação complexa de construtores incrementais estão longe do escopo dessa discussão, desde que a implementação seja dependente do design do construtor específico.

Chamando uma construção

Um construtor pode ser chamado explicitamente de uma das seguintes maneiras:

Na prática, o usuário do workbench aciona uma construção selecionando os comandos correspondentes no menu do navegador de recurso.

Os construtores de projeto incremental são também chamados implicitamente pela plataforma durante a construção automática. Se ativada, as construções automáticas são executadas em qualquer lugar na área de trabalho que é alterada.

Definindo um construtor de projeto incremental

O ponto de extensão org.eclipse.core.resources.builders é utilizado para contribuir com um construtor de projeto incremental para a plataforma. A seguinte marcação mostra como o plug-in hipotético com.example.builders poderia contribuir com o construtor de projeto incremental.

   <extension
      id="mybuilder" name="Meu Construtor de Exemplo" point="org.eclipse.core.resources.builders">
      <builder
         <run
            class="com.example.builders.BuilderExample">
            <parameter name="optimize" value="true" />
            <parameter name="comment" value="Comentário do construtor" />
         </run>
      </builder>
   </extension>

A classe identificada no ponto de extensão deve estender a classe de plataforma IncrementalProjectBuilder.

   public class BuilderExample extends IncrementalProjectBuilder {
      IProject[] build(int kind, Map args, IProgressMonitor monitor)
         throws CoreException {
         // incluir sua lógica da construção aqui
      return null;
      }
      protected void startupOnInitialize() {
         // incluir a lógica init do construtor aqui
      }
      protected void clean(IProgressMonitor monitor) {
         // add builder clean logic here
      }
   }

O processamento de construção começa com o método build(), que inclui informações sobre o tipo de construção que foi pedido. A construção é um dos seguintes valores:

Se uma construção incremental tiver sido pedida, um delta de recurso é fornecido para descrever as alterações nos recursos desde a última construção. O fragmento a seguir define mais para frente o método construção() .

      protected IProject[] build(int kind, Map args, IProgressMonitor monitor
         throws CoreException {
      if (kind == IncrementalProjectBuilder.FULL_BUILD) {
            fullBuild(monitor);
         } else {
         IResourceDelta delta = getDelta(getProject());
         if (delta == null) {
            fullBuild(monitor);
         } else {
            incrementalBuild(delta, monitor);
         }
      }
      return null;
   }

Isso algumas vezes acontece quando o projeto de construção "X," um construtor precisa de informações sobre alterações em algum outro projeto "Y."  (Por exemplo, se uma classe Java em X implementar uma interface fornecida em Y.)  Durante a construção de X, um delta para Y fica disponível para chamar getDelta(Y).  Para garantir que a plataforma possa fornecer esses deltas, o construtor de X deve ter declarado a dependência entre X e Y retornando uma matriz que contenha Y de uma chamada anterior de build().  Se um construtor não tiver dependências, é possível simplesmente retornar nulo. Consulte IncrementalProjectBuilder para obter informações adicionais.

Construção completa

A lógica necessária para processar um pedido de construção completa é específico para o plug-in. Pode envolver a visita de cada recurso no projeto ou mesmo examinar outros projetos se houver dependências entre os projetos. O seguinte fragmento sugere como uma construção completa pode ser implementada.

   protected void fullBuild(final IProgressMonitor monitor) throws CoreException {
      try {
         getProject().accept(new MyBuildVisitor());
      } catch (CoreException e) { }
   }

O visitante da construção executaria a construção para o recurso específico (sem resposta verdadeira para continuar visitando todos os recursos filho).

   class MyBuildVisitor implements IResourceVisitor {
      public boolean visit(IResource res) {
         //construir o recurso especificado.
         //retornar true para continuar visitando os filhos.
         return true;
      }
   }

O processo de visitação continua até que a árvore de recurso completa tenha sido movida.

Construção incremental

Ao executar uma construção incremental, o construtor funciona com um delta de alteração de recurso em vez de uma árvore de recursos completa.

   protected void incrementalBuild(IResourceDelta delta, 
         IProgressMonitor monitor) throws CoreException {
      // o visitante faz o trabalho.
      delta.accept(new MyBuildDeltaVisitor());
   }

O processo de visitação continua até que a árvore do delta do recurso completo tenha sido movida. A natureza específica das alterações é semelhante à descrita em Implementando um atendente de alteração de recurso.  Uma diferença importante é que com os construtores de projeto incremental, você está trabalhando com um delta de recurso com base em um determinado projeto, não no espaço de trabalho inteiro.

Limpando Antes de uma Construção

O workbench permite que os usuários limpem um projeto ou um conjunto de projetos antes de iniciar uma construção. Esse recurso permite que o usuário force uma reconstrução a partir do ponto de partida somente em determinados projetos. Os construtores devem implementar este método para limpar os marcadores de problemas e recursos derivados no projeto.

Associando um construtor de projeto incremental a um projeto

Para disponibilizar um construtor para um projeto informado, é necessário incluí-lo na construção específica para o projeto. Uma construção específica do projeto é uma lista de comandos para executar, na seqüência, quando o projeto é construído. Cada comando nomeia um construtor de projeto incremental simples.

NOTA: O nome do construtor em um comando build é o id completo da extensão do construtor. O ID completo de uma extensão é criado com a combinação do id do plug-in com o id simples da extensão no arquivo plugin.xml. Por exemplo, um construtor com ID simples de extensão simples "mybuilder" no plug-in "com.example.builders" terá o nome "com.example.builders.mybuilder"

O fragmento a seguir inclui um novo construtor como o primeiro construtor na lista de construtores existentes.

   final String BUILDER_ID = "com.example.builders.mybuilder";
   IProjectDescription desc = project.getDescription();
   ICommand[] commands = desc.getBuildSpec();
   boolean found = false;

   for (int i = 0; i < commands.length; ++i) {
      if (commands[i].getBuilderName().equals(BUILDER_ID)) {
         found = true;
         break;
      }
   }
   if (!found) { 
      //incluir construtor no projeto
      ICommand command = desc.newCommand();
      command.setBuilderName(BUILDER_ID);
      ICommand[] newCommands = new ICommand[commands.length + 1];

      // Incluí-lo antes de outros construtores.
      System.arraycopy(commands, 0, newCommands, 1, commands.length);
      newCommands[0] = command;
      desc.setBuildSpec(newCommands);
      project.setDescription(desc, null);
   }

A configuração do construtor do projeto é feita somente uma vez, normalmente enquanto o projeto está sendo criado.