Scrittura di plugin IntelliJ IDEA

1. Introduzione

Negli ultimi anni, IntelliJ di JetBrains è diventato rapidamente l'IDE migliore per gli sviluppatori Java. Nel nostro più recente rapporto sullo stato di Java, IntelliJ è stato l'IDE preferito dal 55% degli intervistati, rispetto al 48% dell'anno precedente.

Una caratteristica che rende IntelliJ così attraente per gli sviluppatori Java è la possibilità di estendere e creare nuove funzionalità utilizzando i plugin. In questo tutorial vedremo come scrivere un plugin IntelliJ per dimostrare alcuni dei modi per estendere l'IDE.

E nota che sebbene questo articolo sia incentrato sui plugin IntelliJ, tutti gli IDE JetBrains condividono codice comune. Pertanto, molte delle tecniche qui utilizzate possono essere applicate ad altri IDE di JetBrain come PyCharm, RubyMine e altri.

2. Funzionalità del plugin

La funzionalità del plugin per IntelliJ rientra in genere in una delle 4 categorie:

  • Linguaggi personalizzati : la capacità di scrivere, interpretare e compilare codice scritto in lingue diverse
  • Framework : supporto per framework di terze parti come Spring
  • Strumenti : integrazione con strumenti esterni come Gradle
  • Componenti aggiuntivi dell'interfaccia utente : nuove voci di menu, finestre degli strumenti e pulsanti e altro ancora

I plugin rientrano spesso in più categorie . Ad esempio, il plugin Git fornito con IntelliJ, interagisce con l'eseguibile git installato nel sistema. Il plugin fornisce la sua finestra degli strumenti e le voci del menu popup, integrandosi anche nel flusso di lavoro di creazione del progetto, nella finestra delle preferenze e altro ancora.

3. Creazione di un plugin

Il modo più semplice per iniziare con i plugin IntelliJ è usare il loro Plugin DevKit. È possibile accedervi dal menu Nuovo > Progetto :

Nota che dobbiamo usare un JDK JetBrains per assicurarci che le classi di plugin richieste siano disponibili sul classpath. IntelliJ dovrebbe essere fornito con un JDK adatto per impostazione predefinita, ma in caso contrario possiamo scaricarne uno da qui.

Al momento della stesura di questo documento, possiamo usare solo Java 8 per scrivere plugin IntelliJ . Questo perché JetBrains attualmente non fornisce un JDK ufficiale per Java 9 o versioni successive.

4. Plugin di esempio

Per dimostrare la scrittura di un plug-in IntelliJ, creeremo un plug-in che fornisce un accesso rapido al popolare sito Web Stack Overflow da più aree dell'IDE. Aggiungeremo:

  • Una voce di menu Strumenti per visitare la pagina Fai una domanda
  • Una voce di menu popup sia nell'editor di testo che nell'output della console per cercare Stack Overflow per il testo evidenziato.

4.1. Creazione di azioni

Le azioni sono il componente principale utilizzato per scrivere plugin IntelliJ . Le azioni vengono attivate da eventi nell'IDE, come il clic su una voce di menu o un pulsante della barra degli strumenti.

Il primo passaggio nella creazione di un'azione è creare una classe Java che estende AnAction . Per il nostro plug-in Stack Overflow, creeremo 2 azioni.

La prima azione apre la pagina Fai una domanda in una nuova finestra del browser:

public class AskQuestionAction extends AnAction { @Override public void actionPerformed(AnActionEvent e) { BrowserUtil.browse("//stackoverflow.com/questions/ask"); } }

Usiamo la classe BrowserUtil incorporata perché gestisce tutte le sfumature dell'apertura di una pagina web su diversi sistemi operativi e browser.

La seconda azione apre la pagina di ricerca Overflow dello stack e passa il testo di ricerca come stringa di query. Questa volta implementeremo due metodi.

Il primo metodo che implementiamo è proprio come la nostra prima azione e gestisce l'apertura di un browser web.

Per prima cosa, però, dobbiamo raccogliere due valori per StackOverflow. Uno è il tag della lingua e l'altro è il testo da cercare.

Per ottenere il tag della lingua, useremo l'interfaccia della struttura del programma. Questa API analizza tutti i file in un progetto e fornisce un modo programmatico per ispezionarli.

In questo caso, utilizziamo il PSI per determinare il linguaggio di programmazione di un file:

PsiFile file = e.getData(CommonDataKeys.PSI_FILE); Language lang = e.getData(CommonDataKeys.PSI_FILE).getLanguage(); String languageTag = "+[" + lang.getDisplayName().toLowerCase() + "]";

Si noti che il PSI fornisce anche dettagli specifici della lingua su un file. Ad esempio, potremmo usare PSI per trovare tutti i metodi pubblici in una classe Java.

Per ottenere il testo da cercare, utilizzeremo l' API dell'editor per recuperare il testo evidenziato sullo schermo:

final Editor editor = e.getRequiredData(CommonDataKeys.EDITOR); CaretModel caretModel = editor.getCaretModel(); String selectedText = caretModel.getCurrentCaret().getSelectedText();

Anche se questa azione è la stessa sia per l'editor che per le finestre della console, l'accesso al testo selezionato funziona allo stesso modo.

Ora, possiamo mettere tutto insieme in una dichiarazione actionPerformed :

@Override public void actionPerformed(AnActionEvent e) { PsiFile file = e.getData(CommonDataKeys.PSI_FILE); Language lang = e.getData(CommonDataKeys.PSI_FILE).getLanguage(); String languageTag = "+[" + lang.getDisplayName().toLowerCase() + "]"; Editor editor = e.getRequiredData(CommonDataKeys.EDITOR); CaretModel caretModel = editor.getCaretModel(); String selectedText = caretModel.getCurrentCaret().getSelectedText() String query = selectedText.replace(' ', '+') + languageTag; BrowserUtil.browse("//stackoverflow.com/search?q=" + query); } 

Questa azione sovrascrive anche un secondo metodo denominato update . Questo ci consente di abilitare o disabilitare l'azione in diverse condizioni.

In questo caso, disabilitiamo l'azione di ricerca quando non c'è testo selezionato:

@Override public void update(AnActionEvent e) { Editor editor = e.getRequiredData(CommonDataKeys.EDITOR); CaretModel caretModel = editor.getCaretModel(); e.getPresentation().setEnabledAndVisible(caretModel.getCurrentCaret().hasSelection()); } 

4.2. Registrazione di azioni

Una volta che abbiamo scritto le nostre azioni, dobbiamo registrarle con l'IDE . Ci sono due modi per farlo.

Il primo modo è utilizzare il file plugin.xml , che viene creato per noi quando iniziamo un nuovo progetto.

Per impostazione predefinita il file avrà un vuoto elemento, che è dove aggiungeremo le nostre azioni:

L'utilizzo del file XML per registrare le azioni garantirà che vengano registrate durante l'avvio dell'IDE, che di solito è preferibile.

Il secondo modo per registrare le azioni è a livello di codice utilizzando la classe ActionManager :

ActionManager.getInstance().registerAction("StackOverflow.SearchAction", new SearchAction());

Questo ha il vantaggio di permetterci di registrare dinamicamente le azioni. Ad esempio, se scriviamo un plugin da integrare con un'API remota, potremmo voler registrare un diverso insieme di azioni in base alla versione dell'API che chiamiamo.

The disadvantage to this approach is that actions do not register at startup. We have to create an instance of ApplicationComponent to manage actions, which requires more coding and XML configuration.

5. Testing the Plugin

As with any program, writing an IntelliJ plugin requires testing. For a small plugin like the one we have written, it's sufficient to ensure the plugin compiles and that the actions we created work as expected when we click them.

We can manually test (and debug) our plugin by using a Plugin run configuration:

This will launch a new instance of IntelliJ with our plugin activated. This allows us to click the different menu items we created and ensure the proper Stack Overflow pages open up.

If you wish to do more traditional unit testing, IntelliJ provides a headless environment to run unit tests. We can write tests using any test framework we want, and the tests run using real, unmocked components from the IDE.

6. Deploying the Plugin

The plugin DevKit provides a simple way to package plugins so we can install and distribute them. Simply right-click the plugin project and select “Prepare plugin module for Deployment”. This will generate a JAR file inside the project directory.

The generated JAR file contains the code and configuration files needed to load into IntelliJ. You can install it locally, or publish it to a plugin repository for use by others.

The screenshot below shows one of the new Stack Overflow menu items in action:

7. Conclusion

In questo articolo abbiamo sviluppato un semplice plugin che evidenzia solo alcuni dei modi in cui possiamo migliorare l'IDE di IntelliJ.

Sebbene lavorassimo principalmente con le azioni, l'SDK del plug-in IntelliJ offre diversi modi per aggiungere nuove funzionalità all'IDE. Per ulteriori letture, consulta la guida introduttiva ufficiale.

Come sempre, il codice completo per il nostro plug-in di esempio può essere trovato nel nostro repository GitHub.