| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
| <html xmlns="http://www.w3.org/1999/xhtml"> |
| <head> |
| <meta http-equiv="content-type" content="text/html; charset=UTF-8"> |
| <!-- -*- xhtml -*- --> |
| <title>Tutorial de infra-estrutura da linguagem NetBeans Java para a Plataforma NetBeans 6.0</title> |
| <link rel="stylesheet" type="text/css" href="../../../netbeans.css"> |
| <meta name="AUDIENCE" content="NBUSER"> |
| <meta name="TYPE" content="ARTICLE"> |
| <meta name="EXPIRES" content="N"> |
| <meta name="developer" content="geertjan.wielenga@sun.com"> |
| <meta name="indexed" content="y"> |
| <meta name="description" |
| content="A walk-through of the Retouche approach."> |
| <!-- Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. --> |
| <!-- Use is subject to license terms.--> |
| </head> |
| <body> |
| <h1>Tutorial Infra-estrutura da linguagem Java</h1> |
| |
| <p>Neste tutorial, você será apresentado aos aspectos das novas APIs de "Retouche" do NetBeans 6.0, que fornecem acesso ao editor NetBeans Java. |
| |
| </p><p><b>Conteúdo</b></p> |
| |
| <img src="../../images/articles/60/netbeans-stamp60-61.gif" class="stamp" width="114" height="114" alt="O conteúdo desta página se aplica ao IDE NetBeans 6.1 " title="O conteúdo desta página se aplica ao IDE NetBeans 6.1"> </p> |
| <ul class="toc"> |
| <li><a href="#intro">Introdução à infra-estrutura da linguagem Java</a></li> |
| <li><a href="#setting-up-the-module">Configurando o módulo</a></li> |
| <li><a href="#creating-a-context-sensitive-toolbar-button">Criando um botão de barra de ferramentas sensível ao contexto</a></li> |
| <li><a href="#identifying-java-source-files">Editando os arquivos-fonte Java</a></li> |
| <li><a href="#determining-open-state">Determinando o estado aberto</a></li> |
| <li><a href="#detecting-the-element-under-the-caret">Detectando o elemento sob o cursor</a></li> |
| <li><a href="#doing-something-useful">Fazendo algo útil</a></li> |
| </ul> |
| |
| <p><b>Para seguir este tutorial, você preciso dos softwares e recursos listados na tabela seguinte.</b></p> |
| |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software ou recurso</th> |
| <th class="tblheader" scope="col">Versão necessária</th> |
| </tr> |
| <tr> |
| <td class="tbltd1">NetBeans IDE</td> |
| <td class="tbltd1">versão <a href="http://download.netbeans.org/netbeans/6.1/final/">versão 6.1</a> ou<br> |
| versão 6.0</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">Java Developer Kit (JDK)</td> |
| <td class="tbltd1"><a href="http://java.sun.com/javase/downloads/index.jsp">versão 6</a> ou<br> |
| versão 5</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p class="tips">Opcionalmente, para fins de solução de problemas, você pode <a href="http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=2753">baixar a amostra completa</a> e inspecionar os códigos-fonte. |
| |
| </p><p></p><h2><a name="intro"> </a>Introdução à infra-estrutura da linguagem Java</h2> |
| |
| <p>Antes do NetBeans IDE 6.0, a infra-estrutura da linguagem Java que oferecia suporte ao Editor Java, incluindo a geração de código Java e a refatoração para Java, era baseada em JMI para Java (também conhecido como MDR). O JMI para Java tinha alguns problemas de arquitetura como o bloqueio exclusivo de leitura. Em outras palavras, um bloqueio tinha que ser adquirido apenas para ler informações de seu modelo, embora isso normalmente seja necessário apenas em ações de gravação. Durante alguns anos, o JMI foi depurado e aprimorado em termos de desempenho. Mas outro problema era que ele usava a própria cópia interna do analisador de Java, o que significava que ele tinha sua própria abordagem da interpretação do código-fonte Java, o que diferia do compilador Java do JDK. Com a introdução dos genéricos no JDK 5, o que introduziu construções Java mais complicadas e sutis, o gerenciamento dessa divergência ficou mais difícil. Portanto, devido aos problemas de desempenho do JMI e como um modelo de linguagem formal foi desenvolvido para tornar o compilador JDK Java uma ferramenta programaticamente acessível, o JMI para Java foi substituído por uma nova abordagem, baseada no compilador JDK Java. |
| |
| </p><p>Foi assim que Retouche , uma palavra francesa que significa "correção", surgiu. Retouche é a nova e rápida infra-estrutura de linguagem Java no NetBeans IDE, capaz de suportar todos os recursos interessantes do editor Java que foram aprendidos no NetBeans 6.0. Em sua essência, Retouche delimita uma instância do compilador JDK Java e consome seus artefatos, como a árvore de sintaxe abstrata (também conhecida como "AST") e as resoluções simbólicas emitidas em várias fases da análise. Ao trabalhar com Retouche, você precisará lidar com alguns destes artefatos. A <a href="http://java.sun.com/javase/6/docs/jdk/api/javac/tree/index.html">API da árvore do compilador</a>, por exemplo, é um deles. A nomeação de pacotes das classes na API da árvore do compilador é <tt>com.sun.*</tt>. Assim, tecnicamente, esta é uma API não-JDK, mas que vem do compilador JDK Java. Outro exemplo de artefatos do compilador JDK Java com os quais você trabalha em relação à Retouche é o modelo de linguagem formal nas APIs JDK, fornecido pelos pacotes <tt>javax.language.model.*</tt>. |
| |
| |
| </p><p></p><h2><a name="setting-up-the-module"></a>Configurando o módulo</h2> |
| |
| <p>Nesta seção, utilizamos assistentes para criar um projeto de módulo e para definir dependências em módulos relevantes do NetBeans. |
| |
| </p><ol> |
| |
| <li>Escolha Arquivo > Novo projeto. No assistente para Novo projeto. escolha Módulos do NetBeans em Categorias e Projeto de módulo em Projetos e clique em Próximo. |
| |
| </li><li>Digite <tt>CopyFQN</tt> em Nome do projeto e defina Localização do projeto como uma pasta apropriada no disco. Se não estiverem selecionadas, selecione Módulo independente e Definir como projeto principal. Clique em Próximo. |
| |
| </li><li>Digite <tt>org.netbeans.modules.copyfqn</tt> em Nome de base de código e <tt>CopyFQN</tt> em Nome de exibição do módulo. Clique em Terminar. |
| |
| </li><li>Clique com o botão direito do mouse no projeto, escolha Propriedades, clique em Bibliotecas na caixa de diálogo Propriedades do projeto e declare uma dependência nas seguintes APIs: |
| |
| <p></p><ul> |
| <li>API de sistema de dados |
| </li><li>Biblioteca 2 do editor |
| </li><li>API do sistema de arquivos |
| </li><li>Wrapper da API Javac |
| </li><li>Fonte Java |
| </li><li>API de nós |
| </li><li>API de texto |
| </li><li>API de utilitários para UI |
| </li><li>API de utilitários |
| </li><li>API do sistema de janelas |
| </li></ul> |
| |
| <p>O seguinte deverá ser exibido: |
| |
| </p><p align="left"><img border="1" src="../../images/tutorials/copyfqn/proj-props-copyfqn-60.png" alt="copy fqn"> |
| |
| |
| |
| </p><p>Clique em OK. |
| |
| </p></li> |
| |
| <p></p><h2><a name="creating-a-context-sensitive-toolbar-button"> </a>Criando um botão de barra de ferramentas sensível ao contexto</h2> |
| |
| <p>Nesta seção, criaremos um botão com reconhecimento de contexto na barra de ferramentas. Isto não tem nada a ver com as novas APIs de Retouche, mas fornece um elemento de interface do usuário para interagir com a implementação das APIs de Retouche, posteriormente neste tutorial. |
| |
| </p><ol> |
| <li>Você pode abrir o projeto do módulo, escolhendo Novo > Outro e selecionando Ação na categoria Desenvolvimento do módulo. Clique em Próximo. |
| |
| </li><li>Escolha Habilitada condicionalmente e mantenha todos os padrões, conforme mostrado abaixo, para que a ação seja sensível a <tt>DataObjects</tt> e para que só seja habilitada quando um <tt>DataObject</tt> for selecionado.</p> |
| |
| |
| <p align="left"><img border="1" src="../../images/tutorials/copyfqn/cookie-action-60.png" alt="ação de cookie"> |
| |
| </p><p>Clique em Próximo. |
| |
| </p></li><li>Escolha Editar em Categoria e Editar na Barra de ferramentas. </p> |
| |
| <p>Agora você deve ver o seguinte: |
| |
| </p><p align="left"><img border="1" src="../../images/tutorials/copyfqn/gui-registration-60.png" alt="registro da gui"> |
| |
| </p><p>Clique em Próximo.</p> |
| |
| </li><li>Digite <tt>CopyFQNAction</tt> em Nome da classe e <tt>CopyFQN</tt> em Nome de exibição. |
| |
| </li><li>Vá até um ícone que será exibido no botão da barra de ferramentas. Por exemplo, use o que será utilizado neste tutorial:</p> |
| |
| <p align="left"><img border="1" src="../../images/tutorials/copyfqn/icon.png" alt="ícone "> |
| |
| </p><p>Clique em Terminar.</p> |
| |
| <p>Você verá o seguinte código na sua nova classe <tt>CopyFQNAction.java</tt>: |
| |
| </p><pre class="examplecode">public final class CopyFQNAction extends CookieAction { |
| |
| protected void performAction(Node[] activatedNodes) { |
| DataObject dataObject = activatedNodes[0].getLookup().lookup(org.openide.loaders.DataObject.class); |
| // TODO use dataObject |
| } |
| |
| protected int mode() { |
| return CookieAction.MODE_EXACTLY_ONE; |
| } |
| |
| public String getName() { |
| return NbBundle.getMessage(CopyFQNAction.class, "CTL_CopyFQNAction"); |
| } |
| |
| protected Class[] cookieClasses() { |
| return new Class[] { |
| DataObject.class |
| }; |
| } |
| |
| protected String iconResource() { |
| return "org/netbeans/modules/copyfqn/icon.png"; |
| } |
| |
| public HelpCtx getHelpCtx() { |
| return HelpCtx.DEFAULT_HELP; |
| } |
| |
| protected boolean asynchronous() { |
| return false; |
| } |
| |
| }</pre> |
| |
| <p><b class="notes">Observação:</b> todo o trabalho feito no restante deste tutorial será focalizado no método <tt>performAction()</tt> acima.</p> |
| |
| <p>Você criou uma ação sensível a objetos de dados. Vejamos o que isso significa. |
| |
| </p></li><li>Clique com o botão direito do mouse no módulo e escolha Instalar.</p> |
| |
| <p>Depois que o módulo for instalado, você verá um novo botão na barra de ferramentas. |
| |
| </p></li><li>Selecione um nó na janela Projetos e procure o botão na barra de ferramentas. Se você selecionar um nó representando um arquivo ou uma pasta (incluindo um pacote), o botão será habilitado, conforme mostrado aqui:</p> |
| |
| <p align="left"><img border="1" src="../../images/tutorials/copyfqn/ctx-sensitive-on.png" alt="ícone "> |
| |
| </p><p>Entretanto, se você selecionar um nó representando um projeto, o botão será desabilitado, conforme mostrado abaixo:</p> |
| |
| <p align="left"><img border="1" src="../../images/tutorials/copyfqn/ctx-sensitive-off.png" alt="ícone "> |
| |
| </p></li> |
| </ol> |
| <p>Na próxima seção, iremos fazer mais que distinguir entre nós de projeto e nós de arquivo/pasta: iremos distinguir entre nós de arquivo para classes Java versus todos os outros tipos de nós de arquivo. |
| |
| |
| </p><p></p><h2><a name="identifying-java-source-files"></a>Identificando arquivos do código-fonte Java</h2> |
| |
| <p>Nesta seção, começaremos usando uma das novas APIs de "Retouche", chamada de <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-java-source/overview-summary.html">Código-fonte Java</a>. Aqui usamos a classe <a href="http://www.netbeans.org/download/dev/javadoc/org-netbeans-modules-java-source/org/netbeans/api/java/source/JavaSource.html">JavaSource</a>, que representa um arquivo de código-fonte Java. Retornamos uma instância desta classe para o objeto de arquivo associado ao objeto de dados. Se for retornado um valor nulo, o objeto de arquivo não é um arquivo de código-fonte Java. O resultado é exibido na barra de status, quando o botão é clicado enquanto um arquivo é selecionado. |
| |
| </p><ol> |
| |
| <li>Preencha o método <tt>performAction()</tt> adicionando as linhas destacadas abaixo: |
| |
| <pre class="examplecode">protected void performAction(Node[] activatedNodes) { |
| DataObject dataObject = activatedNodes[0].getLookup().lookup(org.openide.loaders.DataObject.class); |
| // TODO use dataObject |
| |
| <b>FileObject fileObject = dataObject.getPrimaryFile(); |
| |
| <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-java-source/org/netbeans/api/java/source/JavaSource.html">JavaSource</a> javaSource = <a href="http://www.netbeans.org/download/dev/javadoc/org-netbeans-modules-java-source/org/netbeans/api/java/source/JavaSource.html#forFileObject(org.openide.filesystems.FileObject)">JavaSource.forFileObject(fileObject)</a>; |
| if (javaSource == null) { |
| StatusDisplayer.getDefault().setStatusText("Not a Java file: " + fileObject.getPath()); |
| } else { |
| StatusDisplayer.getDefault().setStatusText("Hurray! Um arquivo Java: " + fileObject.getPath()); |
| }</b> |
| }</pre> |
| |
| </li><li>Certifique-se de que os comandos import sejam os seguintes: |
| |
| <pre class="examplecode">import org.netbeans.api.java.source.JavaSource; |
| import org.openide.awt.StatusDisplayer; |
| import org.openide.filesystems.FileObject; |
| import org.openide.loaders.DataObject; |
| import org.openide.nodes.Node; |
| import org.openide.util.HelpCtx; |
| import org.openide.util.NbBundle; |
| import org.openide.util.actions.CookieAction;</pre> |
| |
| </li><li>Instale o módulo novamente. |
| |
| </li><li>Selecione um nó de arquivo e pressione o botão.</p> |
| |
| <p>Observe que a mensagem "Hurray!" aparece somente quando você seleciona um arquivo Java, conforme mostrado abaixo: |
| |
| </p><p align="left"><img border="1" src="../../images/tutorials/copyfqn/message-java-file-60.png" alt="message-java-file-60"> |
| |
| |
| </p><p>Uma abordagem alternativa seria <i>habilitar o botão somente quando um arquivo Java for selecionado</i>. Para implementar isto, substitua o método <tt>CookieAction.enable()</tt> da seguinte maneira: |
| |
| </p><pre class="examplecode">@Override |
| protected boolean enable(Node[] activatedNodes) { |
| if (super.enable(activatedNodes)) { |
| DataObject dataObject = activatedNodes[0].getLookup().lookup(org.openide.loaders.DataObject.class); |
| FileObject fileObject = dataObject.getPrimaryFile(); |
| JavaSource javaSource = JavaSource.forFileObject(fileObject); |
| if (javaSource == null) { |
| return false; |
| } |
| return true; |
| } |
| return false; |
| }</pre> |
| |
| <p>O método acima filtra qualquer arquivo que <i>não</i> seja um arquivo Java. Como resultado, o botão só será habilitado se o arquivo atual for Java. |
| |
| </p></li> |
| |
| |
| <p></p><h2><a name="determining-open-state"></a>Determinando o estado aberto</h2> |
| |
| <p>Nesta seção, seremos apresentados à nossa primeira tarefa de "Retouche" chamada explicitamente. Essa tarefa é fornecida pelo método <tt>runUserActionTask</tt> da classe JavaSource. Uma tarefa deste tipo permite que você controle as fases de um processo de análise, que é aplicável quando você deseja responder imediatamente à entrada do usuário. Tudo feito na tarefa é feito como uma unidade única. No nosso caso, desejamos que a chamada da ação, representada por um botão na barra de ferramentas, seja imediatamente seguida pela exibição de um texto na barra de status. |
| |
| </p><ol> |
| |
| <li>Substitua a mensagem "Hurray!" no método <tt>performAction()</tt> por esta linha: |
| |
| <pre class="examplecode"><a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-java-source/org/netbeans/api/java/source/JavaSource.html#runUserActionTask(org.netbeans.api.java.source.Task,%20boolean)">javaSource.runUserActionTask</a>(new <a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-java-source/org/netbeans/api/java/source/Task.html">Task</a><<a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-java-source/org/netbeans/api/java/source/CompilationController.html">CompilationController</a>>());</pre> |
| |
| <p>Você verá uma lâmpada na barra esquerda do editor, conforme mostrado aqui: |
| |
| </p><p align="left"><img border="1" src="../../images/tutorials/copyfqn/runuserasactiontask-60.png" alt="ícone "> |
| |
| </p></li><li>Clique na lâmpada. Como alternativa, coloque o cursor na linha e pressione Alt-Enter. Em seguida, deixe que o IDE implemente o método. |
| |
| </li><li>Ajuste o método ligeiramente, adicionando um valor booleano <tt>true</tt> ao final do método e permitindo que o IDE quebre o retalho em um bloco try/catch. No final, o resultado deve ser o seguinte: |
| |
| <pre class="examplecode">protected void performAction(Node[] activatedNodes) { |
| DataObject dataObject = activatedNodes[0].getLookup().lookup(org.openide.loaders.DataObject.class); |
| // TODO use dataObject |
| |
| FileObject fileObject = dataObject.getPrimaryFile(); |
| |
| JavaSource javaSource = JavaSource.forFileObject(fileObject); |
| if (javaSource == null) { |
| StatusDisplayer.getDefault().setStatusText("Not a Java file: " + fileObject.getPath()); |
| } else { |
| |
| <b>try { |
| javaSource.runUserActionTask(new Task<CompilationController>() { |
| |
| public void run(CompilationController arg0) throws Exception { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| }, true); |
| } catch (IOException ex) { |
| Exceptions.printStackTrace(ex); |
| }</b> |
| |
| } |
| |
| }</pre> |
| |
| </li><li>Implemente o método <tt>run()</tt> da seguinte maneira: |
| |
| <pre class="examplecode">public void run(CompilationController compilationController) throws Exception { |
| |
| <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-java-source/org/netbeans/api/java/source/CompilationController.html#toPhase(org.netbeans.api.java.source.JavaSource.Phase)">compilationController.toPhase(Phase.ELEMENTS_RESOLVED)</a>; |
| |
| <a href="http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/text/Document.html">Document</a> document = <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-java-source/org/netbeans/api/java/source/CompilationController.html#getDocument()">compilationController.getDocument()</a>; |
| if (document != null) { |
| StatusDisplayer.getDefault().setStatusText("Hurray, the Java file is open!"); |
| } else { |
| StatusDisplayer.getDefault().setStatusText("The Java file is closed!"); |
| } |
| |
| }</pre> |
| |
| </li><li>Certifique-se de que os comandos import sejam os seguintes: |
| |
| <pre class="examplecode">import java.io.IOException; |
| import javax.swing.text.Document; |
| import org.netbeans.api.java.source.CompilationController; |
| import org.netbeans.api.java.source.JavaSource; |
| import org.netbeans.api.java.source.JavaSource.Phase; |
| import org.netbeans.api.java.source.Task; |
| import org.openide.awt.StatusDisplayer; |
| import org.openide.filesystems.FileObject; |
| import org.openide.loaders.DataObject; |
| import org.openide.nodes.Node; |
| import org.openide.util.Exceptions; |
| import org.openide.util.HelpCtx; |
| import org.openide.util.NbBundle; |
| import org.openide.util.actions.CookieAction;</pre> |
| |
| </li><li>Instale o módulo novamente. |
| |
| </li><li>Selecione um nó de arquivo e pressione o botão.</p> |
| |
| <p>Observe que a mensagem "Hurray!" aparece somente quando você seleciona um arquivo Java que está aberto no Editor Java, conforme mostrado aqui: |
| |
| </p><p align="left"><img border="1" src="../../images/tutorials/copyfqn/message-java-file-open-60.png" alt="message-java-file-open-60"> |
| |
| </p></li> |
| |
| |
| <p></p><h2><a name="detecting-the-element-under-the-caret"></a>Detectando o elemento sob o cursor</h2> |
| |
| <p>Nesta seção, agora que sabemos que estamos lidando com um arquivo Java e que ele está aberto, podemos começar a detectar o tipo de elemento sob o cursor a qualquer momento específico. |
| |
| </p><ol> |
| |
| <li>Comece declarando uma dependência nas APIs de E/S, para que possamos imprimir nossos resultados na janela Saída. |
| |
| </li><li>Substitua a mensagem "Hurray!" no método <tt>run()</tt> pelas linhas destacadas abaixo: |
| |
| <pre class="examplecode">public void run(CompilationController compilationController) throws Exception { |
| |
| compilationController.toPhase(Phase.ELEMENTS_RESOLVED); |
| Document document = compilationController.getDocument(); |
| |
| if (document != null) { |
| <b>new MemberVisitor(compilationController).scan(compilationController.getCompilationUnit(), null);</b> |
| } else { |
| StatusDisplayer.getDefault().setStatusText("The Java file is closed!"); |
| } |
| |
| }</pre> |
| |
| |
| <p></p></li><li>E aqui está a classe <tt>MemberVisitor</tt>, definida como uma classe interna da classe <tt>CopyFQNAction</tt>: |
| |
| |
| <pre class="examplecode">private static class MemberVisitor extends TreePathScanner<Void, Void> { |
| |
| private CompilationInfo info; |
| |
| public MemberVisitor(CompilationInfo info) { |
| this.info = info; |
| } |
| |
| @Override |
| public Void visitClass(ClassTree t, Void v) { |
| Element el = info.getTrees().getElement(getCurrentPath()); |
| if (el == null) { |
| StatusDisplayer.getDefault().setStatusText("Cannot resolve class!"); |
| } else { |
| TypeElement te = (TypeElement) el; |
| List<? extends Element> enclosedElements = te.getEnclosedElements(); |
| InputOutput io = IOProvider.getDefault().getIO("Analysis of " |
| + info.getFileObject().getName(), true); |
| for (int i = 0; i < enclosedElements.size(); i++) { |
| Element enclosedElement = (Element) enclosedElements.get(i); |
| if (enclosedElement.getKind() == ElementKind.CONSTRUCTOR) { |
| io.getOut().println("Constructor: " |
| + enclosedElement.getSimpleName()); |
| } else if (enclosedElement.getKind() == ElementKind.METHOD) { |
| io.getOut().println("Method: " |
| + enclosedElement.getSimpleName()); |
| } else if (enclosedElement.getKind() == ElementKind.FIELD) { |
| io.getOut().println("Field: " |
| + enclosedElement.getSimpleName()); |
| } else { |
| io.getOut().println("Other: " |
| + enclosedElement.getSimpleName()); |
| } |
| } |
| io.getOut().close(); |
| } |
| return null; |
| } |
| |
| }</pre> |
| |
| </li><li>Instale o módulo novamente, e abra uma classe Java. Em seguida, clique no botão e observe que os construtores, métodos e campos são gravados na janela Saída, conforme mostrado abaixo:</p> |
| |
| |
| <p align="left"><img border="1" src="../../images/tutorials/copyfqn/output-window-60.png" alt="message-constructor-60"> |
| |
| |
| </p></li><li>Em seguida, em vez de imprimir todos os elementos na janela Saída, iremos imprimir somente o elemento sob o cursor. Substitua somente o método <tt>visitClass</tt>, pelo código destacado abaixo: |
| |
| <pre class="examplecode">private static class MemberVisitor extends TreePathScanner<Void, Void> { |
| |
| private CompilationInfo info; |
| |
| public MemberVisitor(CompilationInfo info) { |
| this.info = info; |
| } |
| |
| <b>@Override |
| public Void visitClass(ClassTree t, Void v) { |
| try { |
| JTextComponent editor = EditorRegistry.lastFocusedComponent(); |
| if (editor.getDocument() == info.getDocument()) { |
| int dot = editor.getCaret().getDot(); |
| TreePath tp = info.getTreeUtilities().pathFor(dot); |
| Element el = info.getTrees().getElement(tp); |
| if (el == null) { |
| StatusDisplayer.getDefault().setStatusText("Cannot resolve class!"); |
| } else { |
| InputOutput io = IOProvider.getDefault().getIO("Analysis of " |
| + info.getFileObject().getName(), true); |
| if (el.getKind() == ElementKind.CONSTRUCTOR) { |
| io.getOut().println("Hurray, this is a constructor: " |
| + el.getSimpleName()); |
| } else if (el.getKind() == ElementKind.METHOD) { |
| io.getOut().println("Hurray, this is a method: " |
| + el.getSimpleName()); |
| } else if (el.getKind() == ElementKind.FIELD) { |
| io.getOut().println("Hurray, this is a field: " |
| + el.getSimpleName()); |
| } else { |
| io.getOut().println("Hurray, this is something else: " |
| + el.getSimpleName()); |
| } |
| io.getOut().close(); |
| } |
| } |
| } catch (IOException ex) { |
| Exceptions.printStackTrace(ex); |
| } |
| return null; |
| }</b> |
| |
| }</pre> |
| |
| </li><li>Instale o módulo. |
| |
| </li><li>Coloque o cursor em qualquer lugar no código Java e pressione o botão. A janela Saída exibe informações sobre o código sob o cursor, se aplicável. Por exemplo, se você pressionar o botão após colocar o cursor em um método, conforme mostrado abaixo, a janela Saída informa que o cursor está em um método:</p> |
| |
| <p align="left"><img border="1" src="../../images/tutorials/copyfqn/message-constructor-60.png" alt="message-constructor-60"> |
| |
| |
| </p></li><li>Mas podemos detectar muito mais que somente o nome do elemento sob o cursor. No método <tt>visitClass</tt>, substitua as linhas em negrito abaixo: |
| |
| |
| <pre class="examplecode">@Override |
| public Void visitClass(ClassTree t, Void v) { |
| try { |
| JTextComponent editor = EditorRegistry.lastFocusedComponent(); |
| if (editor.getDocument() == info.getDocument()) { |
| int dot = editor.getCaret().getDot(); |
| TreePath tp = info.getTreeUtilities().pathFor(dot); |
| Element el = info.getTrees().getElement(tp); |
| if (el == null) { |
| StatusDisplayer.getDefault().setStatusText("Cannot resolve class!"); |
| } else { |
| InputOutput io = IOProvider.getDefault().getIO("Analysis of " |
| + info.getFileObject().getName(), true); |
| <b>String te = null; |
| if (el.getKind() == ElementKind.CONSTRUCTOR) { |
| te = ((TypeElement) ((ExecutableElement) el).getEnclosingElement()).getQualifiedName().toString(); |
| io.getOut().println("Hurray, this is a constructor's qualified name: " + te); |
| } else if (el.getKind() == ElementKind.METHOD) { |
| te = ((ExecutableElement) el).getReturnType().toString(); |
| io.getOut().println("Hurray, this is a method's return type: " + te); |
| } else if (el.getKind() == ElementKind.FIELD) { |
| te = ((VariableElement) el).asType().toString(); |
| io.getOut().println("Hurray, this is a field's type: " + te); |
| }</b> else { |
| io.getOut().println("Hurray, this is something else: " |
| + el.getSimpleName()); |
| } |
| io.getOut().close(); |
| } |
| } |
| } catch (IOException ex) { |
| Exceptions.printStackTrace(ex); |
| } |
| return null; |
| }</pre> |
| |
| </li><li>Instale o módulo novamente. Desta vez, quando você clicar no botão enquanto o cursor estiver sobre um construtor, método ou campo, mais informações detalhadas sobre o elemento serão impressas na janela Saída. |
| |
| </li></ol> |
| |
| <p>Neste estágio, conseguimos detectar se estamos lidando com um arquivo Java, se o documento está aberto e o tipo de elemento que está sob o cursor. Mas o que podemos fazer com estas informações? Na próxima seção, será apresentado um simples cenário no qual seu conhecimento recém-adquirido mostrará sua utilidade.</p> |
| |
| |
| <p></p><h2><a name="doing-something-useful"> </a>Fazendo algo útil</h2> |
| |
| <p>Nesta seção, definiremos o conteúdo da área de transferência, fornecido por <tt>java.awt.datatransfer.Clipboard</tt>, com base no elemento sob o cursor. Quando você pressionar o botão, o elemento sob o cursor será colocado na área de transferência para que você possa colar o conteúdo em qualquer lugar do código. |
| |
| </p><ol> |
| |
| <li>Comece declarando a área de transferência e definindo um construtor: |
| |
| <pre class="examplecode">private Clipboard clipboard; |
| |
| public CopyFQNAction() { |
| clipboard = Lookup.getDefault().lookup(ExClipboard.class); |
| if (clipboard == null) { |
| clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); |
| } |
| }</pre> |
| |
| </li><li>Em seguida, substitua cada linha "Hurray!" do código por uma linha que envie o elemento como uma string para um método que será definido na próxima etapa. Chamaremos o método de <tt>setClipboardContents</tt>. Assim, substitua, por exemplo, a primeira linha "Hurray!" pelo seguinte: |
| |
| <pre class="examplecode">setClipboardContents(te);</pre> |
| |
| <p>Faça o seguinte nas outras linhas "Hurray!", certificando-se de passar a string correta para o método. |
| |
| </p><p><b class="notes">Observação:</b> como você ainda não definiu o método <tt>setClipboardContents</tt>, cada linha adicionada nesta etapa ficará sublinhada em vermelho. Na próxima etapa, adicionaremos o novo método. |
| |
| </p></li><li>Finalmente, adicione o seguinte ao final da classe. Este método recebe a string e a coloca na área de transferência: |
| |
| <pre class="examplecode">private void setClipboardContents(String content) { |
| if (clipboard != null) { |
| if (content == null) { |
| StatusDisplayer.getDefault().setStatusText(""); |
| clipboard.setContents(null, null); |
| } else { |
| StatusDisplayer.getDefault().setStatusText("Clipboard: " + content); |
| clipboard.setContents(new StringSelection(content), null); |
| } |
| } |
| }</pre> |
| |
| |
| </li></ol> |
| |
| <br> |
| <div class="feedback-box"><a href="https://netbeans.org/about/contact_form.html?to=3&subject=Feedback:%20Java%20Language%20Infrastructure%20Tutorial%20Part%201">Envie-nos seus comentários</a></div> |
| <br style="clear:both;" /> |
| |
| |
| <!-- ======================================================================================== --> |
| |
| <h2><a name="nextsteps"></a>Veja também</h2> |
| |
| <p>Para obter mais informações sobre a criação e o desenvolvimento de módulos do NetBeans, consulte os seguintes recursos: |
| </p><ul> |
| <li><a href="http://wiki.netbeans.org/Java_DevelopersGuide">Guia do desenvolvedor de Java</a></li> |
| <li><a href="http://wiki.netbeans.org/RetoucheDeveloperFAQ">Perguntas freqüentes do desenvolvedor de Retouche</a></li> |
| <li><a href="https://netbeans.org/kb/trails/platform.html">Outros tutoriais relacionados</a></li> |
| <li><a href="https://netbeans.org/download/dev/javadoc/">Javadoc da API da NetBeans </a></li> |
| </ul> |
| |
| <hr> |
| |
| <!-- ======================================================================================== --> |
| |
| </ol></ol></ol></body> |
| </html> |