Um construtor do projeto incremental é um objeto que manipula os recursos em um projeto na forma que é definido pelo próprio construtor. 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, o plug-in do JDT (Ferramentas de desenvolvimento Java) fornecido com a plataforma SDK define um construtor de projeto incremental que compila um arquivo fonte Java em um arquivo class sempre que um arquivo é incluído ou modificado em um projeto Java e recompila os outros arquivos afetados pela alteração.
A plataforma define dois tipos de construção:
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 construtores são melhor entendidos pelo exemplo. O JDT (Ferramentas de desenvolvimento Java) fornece um compilador Java que é levado por um construtor de projeto incremental Java a recompilar arquivos que são afetados por alterações. Quando uma construção completa é acionada, todos os arquivos .java no projeto são compilados. Qualquer problema na compilação é adicionado como marcador 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 compiladas novamente em resposta a uma alteração em um recurso Java.
Apesar de a estrutura básica para construções ser definida na plataforma, o trabalho real é feito no plug-in. 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.
Um construtor pode ser chamado explicitamente de uma das seguintes maneiras:
Na prática, o usuário do workbench dispara 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.
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 } }
O processo de construção começa com o método construção(), que inclui informações sobre o tipo de construção que foi solicitada, FULL_BUILD, INCREMENTAL_BUILD, ou AUTO_BUILD. Se uma construção incremental foi solicitada, um delta de recurso é fornecido para descrever as alterações nos recursos do projeto 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.
A lógica necessária para processar um pedido de construção completa é específico para o plug-in. Isso pode envolver a visita a todos os recursos no projeto (se a construção for acionada para um projeto) ou mesmo o exame de outros projetos se houver dependências entre os projetos. O fragmento a seguir 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.
Quando executar uma construção incremental, você trabalha com um delta de alteração de recurso em vez de todo o projeto.
protected void incrementalBuild(IResourceDelta delta, IProgressMonitor monitor) throws CoreException { // o visitante faz o trabalho. delta.accept(new MyBuildDeltaVisitor()); }
Observe que para construção incremental, o visitante da construção funciona com uma árvore de delta de recurso em vez de uma árvore completa de recurso.
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.
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.
O fragmento a seguir inclui um novo construtor como o primeiro construtor na lista de construtores existentes.
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.