IntelliJ用のプラグインの開発についてもう少し

最近、Intellij IDEの拡張機能の作成に関する記事がHabré- oneに掲載され始めました。

この輝かしい傾向を続け、まだ触れられていないIntellij OpenAPIの場所を説明しようとします。 また、例としては面白いコミックを使用したプラグインがあります。





実際、拡張機能はたった1つの単純なことを行います。お気に入りのGeek&Pokeの新しい画像をソケットに表示し、定期的にサイトからダウンロードしてディスクにキャッシュします。 ところで、 GitHub'eのソース

特に警戒している人のために-漫画はCC BY-SA 3.0の良いライセンスの下にあるので、すべてが合法です:)

プロジェクト自体の作成、 plugin.xmlおよびその他の基本的なplugin.xml作成-関連するドキュメントへのリンク-は既に上記の記事で説明されているため、ここでは繰り返しません。 そして、それらのソリューションを使用して開発する際に抱えていたいくつかの質問について説明します。

プロキシサポート


IntelliJ IDEA(および他のIDE)はプロキシを介してネットワークに接続できます。設定の詳細については、ドキュメントを参照してください

しかし、拡張機能でグローバルIDE設定を使用するには、 com.intellij.util.net.HttpConfigurableクラスの方向にcom.intellij.util.net.HttpConfigurableする価値がcom.intellij.util.net.HttpConfigurableます。 そのパブリックフィールドには、必要な情報がすべて含まれています。たとえば、 USE_HTTP_PROXYフラグは、プロキシを使用するかどうかを示します。 ホスト、ポート、ユーザーに関する情報も含まれます。

最も簡単な方法は、 prepareURLメソッドを使用して、接続ごとに呼び出すことです。
  /** * Call this function before every HTTP connection. * If system configured to use HTTP proxy, this function * checks all required parameters and ask password if * required. * @param url URL for HTTP connection * @throws IOException */ public void prepareURL (String url) throws IOException { 


たとえば、あるurlのコードでは、次のようになります。
  // Ensure that proxy (if any) is set up for this request. final HttpConfigurable httpConfigurable = HttpConfigurable.getInstance(); httpConfigurable.prepareURL(url.toExternalForm()); 


JetBrainsフォーラムで、 誰かがこの方法は役に立たないと誓いますが、私の意見では、彼らは無駄になっています。

プラグインの初期化中にプロセスを開始する


メインページの更新を定期的にチェックする別のスレッドを開始する必要がありました。

これはApplicationComponentに役立ちApplicationComponent 。 コンポーネントの種類とその作成については、 プラグイン構造の記事のドキュメントで特に説明されています。

コンポーネントをplugin.xml追加します。

  <application-components> <component> <implementation-class>com.abelsky.idea.geekandpoke.ComicsPlugin</implementation-class> <interface-class>com.abelsky.idea.geekandpoke.ComicsPlugin</interface-class> </component> </application-components> 


そして、その中でinitComponentメソッドを定義します:

 public class ComicsPlugin implements ApplicationComponent { private static final int UPDATE_PERIOD = 15 * 60 * 60 * 1000; //         ; //    ProjectComponent -    . @Override public void initComponent() { startUpdateTimer(); } private void startUpdateTimer() { final Timer timer = new Timer("Geek and Poke updater"); timer.schedule(new TimerTask() { @Override public void run() { //   -   15 ... } }, 0, ComicsPlugin.UPDATE_PERIOD); } 


ローカリゼーション


ローカライズには、次のスニペットを使用すると便利です。

 package com.abelsky.idea.geekandpoke.messages; // ... public class MessageBundle { private static Reference<ResourceBundle> bundleRef; //     com/abelsky/idea/geekandpoke/messages/MessageBundle.properties // -  key-value .properties-. @NonNls private static final String BUNDLE = "com.abelsky.idea.geekandpoke.messages.MessageBundle"; private MessageBundle() { } public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) { return CommonBundle.message(getBundle(), key, params); } private static ResourceBundle getBundle() { ResourceBundle bundle = null; if (MessageBundle.bundleRef != null) { bundle = MessageBundle.bundleRef.get(); } if (bundle == null) { bundle = ResourceBundle.getBundle(BUNDLE); MessageBundle.bundleRef = new SoftReference<ResourceBundle>(bundle); } return bundle; } } 


ここでは、いくつかの点に注意する価値があります。

最初の方法は、 ResourceBundleSoftReferenceに保存することです。 これは、IDEAソースコードではかなり一般的な方法です-非ハードリンクにできるだけ多くのオブジェクトを保持します。

ところで、 com.intellij.reference.SoftReferenceクラスを確認することをお勧めしますcom.intellij.reference.SoftReferenceからの実装の代わりにそれを使用するのは開発者自身です。 違いは、メモリリークが疑われる場合、 com.intellij.reference.SoftReferenceをハードリンクにすばやく変換できることです。これはプロファイリングに役立ちます。

2番目はアノテーションorg.jetbrains.annotations.PropertyKeyです。 注釈付きメソッド引数は、 resourceBundleパラメーターで指定されたバンドルのストリングのみであることを示しています。 その使用により、.propertiesファイルとコード内のキーが同期していないという確信が追加されます(さらに、キーとバンドルの間に接続があるため、IDEAのリファクタリングも多くを学びます)。

第三に、アノテーションorg.jetbrains.annotations.NonNls / org.jetbrains.annotations.Nls 、翻訳すべきでない(または逆にすべき)行をマークします。 使用するJetBrainsのドキュメントはこちらです。

通知


いくつかのイベントでは、美しい通知を表示したいです。 そのような例:



ここでは、クラスcom.intellij.notification.Notifications価値がcom.intellij.notification.Notificationsます。 たとえば、次のように:

  private void notifyNewEntry() { final Notification newEntryNotification = new Notification( /*   */ MessageBundle.message("notification.new.strip.group"), /*  */ MessageBundle.message("notification.new.strip.title"), /*  */ MessageBundle.message("notification.new.strip.content"), NotificationType.INFORMATION); //     UI- -      invokeLater. Notifications.Bus.notify(newEntryNotification); } 


通知グループはIDE設定に表示されます 。詳細については、 ドキュメントを参照してください。



設定




プラグインの設定ページの作成方法については、 ドキュメントで詳しく説明されています

しかし、要するに、まず、 plugin.xmlに登録します。

  <extensions defaultExtensionNs="com.intellij"> <!-- ... --> <applicationConfigurable instance="com.abelsky.idea.geekandpoke.ui.SettingsPanel"/> </extensions> 


次に、 com.intellij.openapi.options.Configurableインターフェースcom.intellij.openapi.options.Configurableを実装します。 これらのうち、最も重要なcreateComponentは、設定が表示されるコンポーネントを返す必要があります。

オフラインキャッシュ


私のプラグインは画像をディスクに保存する必要がありました-原則として、プロジェクトディレクトリまたは%TMP%場所のないあらゆる種類のキャッシュを書き込むときに同じ質問が発生します。 たとえば、 %USERPROFILE%どこかに書き込むか、もっと面白くすることができます-プラグイン自体がインストールされているディレクトリを使用します。

拡張機能は、デフォルトで%USERPROFILE%/.IdeaIC11/config/plugins/PLUGIN_NAMEインストールされます。 ただし、 idea.plugins.pathで変数idea.plugins.pathを設定することにより、このパスを変更できます。

  // PLUGIN_ID -   id  plugin.xml. final PluginId id = PluginId.getId(PLUGIN_ID); final IdeaPluginDescriptor plugin = PluginManager.getPlugin(id); //    . File path = plugin.getPath(); 


ちなみに、拡張機能が別のディレクトリに展開されていない場合、結果のパスは簡単にJARファイルになります。

PS


この短いFAQがIntelliJプラットフォームを詳しく調べる初心者に役立つことを願っています。 そしてその間、私はこのすべてを理解し始めたポイントに進みます-非常に興味深いプログラミング言語をサポートするIDEAプラグイン;)

Source: https://habr.com/ru/post/J150829/


All Articles