Sabemos que os plug-ins podem definir extensões de arquivos e editores de contribuição especializados que fornecem recursos de edição especializados destes tipos de arquivos. Durante a edição (ou construção) de um recurso, um plug-in pode precisar de recursos de marcação para comunicar problemas ou outras informações ao usuário. O mecanismo marcador de recurso é utilizado para gerenciar esse tipo de informação.
Um marcador é como uma nota tipo barra amarela aderida a um recurso. Em um marcador é possível gravar informações sobre um problema (ex.: localização, gravidade) ou uma tarefa a ser executada. Ou é possível simplesmente gravar uma localização para um marcador como um favorito.
Os usuários podem pular rapidamente para a localização marcada dentro de um recurso. A UI do workbench suporta apresentações de favoritos, pontos de interrupção, tarefas e problemas ao lado do editor. Esses marcadores também podem ser mostrados como itens em exibições, como a exibição de tarefas ou favoritos.
Os recursos de API de plataforma definem os métodos para criar marcadores, definir valores de marcador e aumentar a plataforma com novos tipos de marcadores. Enquanto a plataforma gerencia marcadores, são os plug-ins que controlam sua criação, remoção e valores do atributo.
Os marcadores são objetos pequenos e leves. Poderiam haver centenas e até mesmo milhares de marcadores em um único projeto. Por exemplo, o compilador Java utiliza um marcador para indicar cada problema que encontra no código fonte.
A plataforma descartará marcadores anexados aos recursos que são excluídos, mas os plug-ins são responsáveis pela remoção dos marcadores stale quando não são mais aplicados a um recurso que ainda existe.
A manipulação de um marcador é semelhante à manipulação de um recurso. Os marcadores são objetos identificadores. É possível obter um identificador de marcador a partir de um recurso, mas você não sabe se ele existe realmente até que utilize o protocolo exists() ou, de outra maneira, tente manipulá-lo. Depois de ter estabelecido que um marcador existe, você pode consultar atributos nomeados que possam ter sido atribuídos a ele.
Os marcadores pertencem e são gerenciados pela plataforma, que oferece marcadores persistentes e notifica atendentes conforme os marcadores são adicionados, excluídos ou alterados. Os plug-ins são responsáveis pela criação de qualquer marcador necessário, alterando seus atributos e removendo-os quando não forem mais necessários.
Os marcadores não são criados diretamente utilizando um construtor. Eles são criados utilizando um método de fábrica (IResource.createMarker()) no recurso associado.
IMarker marker = file.createMarker(IMarker.TASK);
Para criar um marcador que possua escopo global (não associado a qualquer recurso específico), é possível utilizar a raiz da área de trabalho (IWorkspace.getRoot()) como recurso.
O código para excluir um marcador é direto.
try { marker.delete(); } catch (CoreException e) { // Algo deu errado }
Quando um marcador é excluído, seu objeto do marcador (identificador) torna-se"stale." Os plug-ins devem utilizar o protocolo IMarker.exists() para certificar-se de que um objeto marcador ainda é válido.
Os marcadores podem ser excluídos no batch perguntando se os marcadores de um recurso serão excluídos. Esse método é útil quando remover muitos marcadores de uma vez ou se referências do marcador individual ou IDs não estão disponíveis.
int depth = IResource.DEPTH_INFINITE; try { resource.deleteMarkers(IMarker.PROBLEM, true, depth); } catch (CoreException e) { // algo deu errado }
Quando excluir um grupo de marcadores, você especifica um tipo de marcador para excluir, como IMarker.PROBLEM, ou nulo para excluir todos os marcadores. O segundo argumento indica se deseja excluir marcadores de subtipo. (Veremos subtipos no momento em que definimos novos tipos de marcadores.) O argumento depth controla a profundidade da exclusão.
Também é possível excluir marcadores utilizando IWorkspace.deleteMarkers(IMarker []).
Dando um marcador, é possível solicitar seu recurso associados, seu id (único relativo àquele recurso) e seu tipo. É possível também acessar informações adicionais via atributos genéricos.
Cada tipo de marcador possui um conjunto específico de atributos que são definidos pelo criador do tipo de marcador utilizando convenções de nomenclatura. A interface IMarker define um conjunto de constantes contendo os nomes do atributo padrão (e alguns dos valores esperados) para os tipos de marcador de plataforma. O método a seguir manipula atributos utilizando as constantes da plataforma.
IMarker marker = file.createMarker(IMarker.TASK); if (marker.exists()) { try { marker.setAttribute(IMarker.MESSAGE, "Um exemplo de mensagem do marcador"); marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH); } catch (CoreException e) { // É necessário identificar o caso em que o marcador não existe mais } }
Os atributos são mantidos genericamente como pares de nome/valor, onde os nomes são cadeias e um valor pode ser qualquer um dos tipos de valores suportados (booleano, inteiro, cadeia). A limitação nos tipos de valor permite que a plataforma preserve os valores rápida e simplificadamente.
Os recursos podem ser consultados pelos seus marcadores e pelos marcadores dos filhos. Por exemplo, consultar a raiz da área de trabalho com profundidade infinita, considera todos os marcadores na área de trabalho.
IMarker[] problems = null; int depth = IResource.DEPTH_INFINITE; try { problems = resource.findMarkers(IMarker.PROBLEM, true, depth); } catch (CoreException e) { // algo deu errado }
O resultado retornado por findMarkers depende dos argumentos transmitidos. No fragmento acima, procuramos todos os marcadores de tipo PROBLEM que aparecem no recurso e todos os seus descendentes diretos e indiretos.
Se você passar nulo como o tipo de marcador, você obterá todos os tipos de marcadores associados ao recurso. O segundo argumento especifica se deseja ver os filhos do recurso. O argumento depth controla a profundidade da pesquisa quando estiver procurando os filhos do recurso. A profundidade pode ser DEPTH_ZERO (somente o recurso informado), DEPTH_ONE (os recurso e todos os seus filhos diretos) ou DEPTH_INFINITE (os recursos e todos os seus descendentes diretos e indiretos).
Os marcadores padrão da plataforma (tarefa, problema e marcador) são persistentes. Isso significa que seus estados serão salvos no encerramento e na inicialização do espaço de trabalho. Entretanto, os marcadores de um tipo persistente podem ser transformados de maneira seletiva em transientes definindo o atributo reservado transient como true.
Novos tipos de marcadores declarados pelos plug-ins não são persistentes, a não ser que sejam declarados como tal.
Os plug-ins podem declarar seus próprios tipos de marcadores utilizando o ponto de extensão org.eclipse.core.resources.markers. Os tipos de marcador padrão para problemas, tarefas e marcadores são declarados pela plataforma na marcação do plug-in dos recursos.
<extension id="problemmarker" point="org.eclipse.core.resources.markers" name="%problemName"> <super type="org.eclipse.core.resources.marker"/> <persistent value="true"/> <attribute name="severity"/> <attribute name="message"/> <attribute name="location"/> </extension> <extension id="taskmarker" point="org.eclipse.core.resources.markers" name="%taskName"> <super type="org.eclipse.core.resources.marker"/> <persistent value="true"/> <attribute name="priority"/> <attribute name="message"/> <attribute name="done"/> <attribute name="userEditable"/> </extension> <extension id="bookmark" point="org.eclipse.core.resources.markers" name="%bookmarkName"> <super type="org.eclipse.core.resources.marker"/> <persistent value="true"/> <attribute name="message"/> <attribute name="location"/> </extension>
Novos tipos de marcadores são derivados de marcadores existentes utilizando herança múltipla. Novos tipos de marcadores herdam todos os atributos de seus super tipos e incluem qualquer novo atributo definido como parte da declaração. Eles também herdam transitivamente atributos de super tipos dos seus super tipos. A marcação a seguir define um novo tipo de marcador em um plug-in hipotético com.example.markers.
<extension id="mymarker" point="org.eclipse.core.resources.markers" /> <extension id="myproblem" point="org.eclipse.core.resources.markers"> <super type="org.eclipse.core.resources.problemmarker"/> <super type="com.example.markers.mymarker"/> <attribute name="myAttribute" /> <persistent value="true" /> </extension>
Observe que o tipo org.eclipse.core.resources.problemmarker é na verdade um dos tipos predefinidos (também conhecido como IMarker.PROBLEM).
O único aspecto de um super tipo de marcador que não é herdado é seu sinalizador persistence. O valor padrão para persistência é falso, então qualquer tipo de marcador que deveria ser persistente deve especificar <persistent value="true"/>.
Depois de declarar o novo tipo de marcador no arquivo de manifesto de plug-in, é possível criar ocorrências de tipo de marcador com.example.markers.myproblem e definir livremente o atributo myAttribute.
A declaração de novos atributos permite que você associe dados a marcadores que planeja utilizar em qualquer outro lugar (nas exibições e editores). Os marcadores de um tipo determinado não têm que ter valores para todos os atributos declarados. As declarações de atributo são mais para resolver problemas de convenções de nomenclatura (para todos usarem"mensagem" para falar sobre uma descrição de marcador) que para limitar conteúdo.
public IMarker createMyMarker(IResource resource) { try { IMarker marker = resource.createMarker("com.example.markers.myproblem"); marker.setAttribute("myAttribute", "MYVALUE"); return marker; } catch (CoreException e) { // É necessário identificar os casos em que o valor do atributo é rejeitado } }
É possível consultar seus próprios tipos de marcador da mesma forma que consulta os tipos de marcador da plataforma. O método a seguir localiza todos os mymarkers associados ao recurso de destino informado e todos os seus descendentes. Observe que isso localizará também todos osmyproblems desde que verdadeiro for passado para o argumento includeSubtypes.
public IMarker[] findMyMarkers(IResource target) { String type = "com.example.markers.mymarker"; IMarker[] markers = target.findMarkers(type, true, IResource.DEPTH_INFINITE); }