「Eclipse JDT – Abstract Syntax Tree (AST) and the Java Model – Tutorial」を翻訳した(2)


www.vogella.comのhttp://www.vogella.com/tutorials/EclipseJDT/article.html
紹介されていたチュートリアルを翻訳した。多少端折った部分と追加した部分がある。

追加部分の画像が多すぎて結局3分割になった(ノ∀`)


ハンドラーを以下の内容へ変更します。

package de.vogella.jdt.infos.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.text.Document;

public class SampleHandler extends AbstractHandler {

  public Object execute(ExecutionEvent event) throws ExecutionException {
    // ワークスペースのルートを取得します。
    IWorkspace workspace = ResourcesPlugin.getWorkspace();
    IWorkspaceRoot root = workspace.getRoot();
    // ワークスペース内の全てのプロジェクトを取得します。
    IProject[] projects = root.getProjects();
    // 全てのプロジェクトでループします。
    for (IProject project : projects) {
      try {
        printProjectInfo(project);
      } catch (CoreException e) {
        e.printStackTrace();
      }
    }
    return null;
  }

  private void printProjectInfo(IProject project) throws CoreException,
      JavaModelException {
    System.out.println("Working in project " + project.getName());
    // Javaプロジェクトを持っているかチェックします
    if (project.isNatureEnabled("org.eclipse.jdt.core.javanature")) {
      IJavaProject javaProject = JavaCore.create(project);
      printPackageInfos(javaProject);
    }
  }

  private void printPackageInfos(IJavaProject javaProject)
      throws JavaModelException {
    IPackageFragment[] packages = javaProject.getPackageFragments();
    for (IPackageFragment mypackage : packages) {
      // Package fragmentsはクラスパス内の全てのパッケージを含みます。
      // このプログラムはソースフォルダのみを見ます
      // K_BINARYは更にJar(例えばrt.jar)を含みます。
      if (mypackage.getKind() == IPackageFragmentRoot.K_SOURCE) {
        System.out.println("Package " + mypackage.getElementName());
        printICompilationUnitInfo(mypackage);

      }

    }
  }

  private void printICompilationUnitInfo(IPackageFragment mypackage)
      throws JavaModelException {
    for (ICompilationUnit unit : mypackage.getCompilationUnits()) {
      printCompilationUnitDetails(unit);

    }
  }

  private void printIMethods(ICompilationUnit unit) throws JavaModelException {
    IType[] allTypes = unit.getAllTypes();
    for (IType type : allTypes) {
      printIMethodDetails(type);
    }
  }

  private void printCompilationUnitDetails(ICompilationUnit unit)
      throws JavaModelException {
    System.out.println("Source file " + unit.getElementName());
    Document doc = new Document(unit.getSource());
    System.out.println("Has number of lines: " + doc.getNumberOfLines());
    printIMethods(unit);
  }

  private void printIMethodDetails(IType type) throws JavaModelException {
    IMethod[] methods = type.getMethods();
    for (IMethod method : methods) {

      System.out.println("Method name " + method.getElementName());
      System.out.println("Signature " + method.getSignature());
      System.out.println("Return Type " + method.getReturnType());

    }
  }
}

プラグインを開始します。
(※)このプラグインを含んだ新しいeclipseが起動する。
jdttutorial021

新しいワークスペース内で2~3のプロジェクトを作成します。
それらの為の2~3のパッケージと2~3のJavaファイルを作成します。サンプルコマンドを指すメニューエントリを押します。
jdttutorial022

呼び出し側のワークベンチのコンソールビュー内で一覧にされたプロジェクト、パッケージ及びソースファイルを見られるはずです。
jdttutorial023


尚、マシンスペックが低いと処理途中で呼び出したeclipseがハングアップする場合がある。
下記の”PermGen Space Error”が出る場合はeclipse.iniに”-XX:MaxPermSize=128m”を
追加する必要がある模様。うちの環境ではそれでも駄目で”-XX:MaxPermSize=256m”に
しても駄目で、eclipse再起動でも駄目で、OS再起動後にようやく動いた…(ヽ’ω`)
色々と謎…
java.lang.OutOfMemoryError: PermGen space及びJava PermGenについて
PermGen Space Error


原文では4.1と4.2は新規にプラグインプロジェクトを作成する前提のようだが、
面倒臭いのでこのinfosプロジェクト内で動作確認をしてしまった(ノ∀`)
4.1を追加した手順は以下の通り。4.2も同様で出来るはず。細かいことを
気にせず動作確認をしたいだけなら、呼び出されるファイル内容を書き換える
だけでもいい筈。

  1. MANIFEST.MFの「拡張」タブを開き、「org.eclipse.ui.commands」を右クリック、
    コンテキストメニューから[新規]-[command]の順に選択。
    addpackage01
  2. 右側の拡張要素詳細の「id*」欄に”de.vogella.jdt.infos.commands.addPackage”、「name*」欄に”パッケージ追加”と入力。
    addpackage02
  3. 「org.eclipse.ui.handlers」を右クリック、コンテキストメニューから[新規]-[handler]の順に選択。
    addpackage03
  4. 右側の拡張要素詳細の
    「commandId*」欄に”de.vogella.jdt.infos.commands.addPackage”、
    「class」欄に”de.vogella.jdt.infos.handlers.AddPackage”と入力。
    addpackage04
  5. 「class」リンクをクリック。
    addpackage05
  6. <完了>をクリック。
    addpackage06
  7. 作成されたjavaファイルに以下のAddPackage.javaの内容を貼り付け。パッケージ宣言のみを”package de.vogella.jdt.infos.handlers;”に修正し保存
  8. 再びMNIFEST.MFの「拡張」タブに戻り、図のように「サンプル・メニュー」を右クリック、
    コンテキストメニューから[新規]-[command]の順に選択。
    addpackage07
  9. 右側の拡張要素詳細の「commandId*」欄に”de.vogella.jdt.infos.commands.addPackage”、「id」欄に”de.vogella.jdt.infos.menus.addPackage”と入力。
    addpackage08
  10. 全てを保存したことを確認し、「概要」タブの「Eclipse アプリケーションの起動」をクリック。
  11. メニューバーから[サンプル・メニュー]-[パッケージ追加]の順に選択。
    addpackage09
  12. プロジェクト名と同じ名前のパッケージが追加されていることを確認。
    addpackage10

4. プロジェクトの修正


4.1. Javaモデルによる新しいJava要素の作成

以下の内容はJavaプロジェクトと同じ名前を持つ、新しいパッケージを既存(かつオープン状態の)Javaプロジェクトへ作成するコマンドを作成します。
例えば、ワークスペース内に全くパッケージを持たない”de.vogella.test”というプロジェクトの場合、このコマンドはこのプロジェクト内に”de.vogella.test”パッケージを作成します。

新しいプラインプロジェクト”de.vogella.jdt.newelements”を作成します。新しいコマンド”de.vogella.jdt.newelements.AddPackage”を追加し、それをメニューへ入れます。

このコマンド用に以下のハンドラを作成します。
※原文try~catch文の閉じカッコ抜け?

package de.vogella.jdt.newelements.handler;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;

public class AddPackage extends AbstractHandler {

  @Override
  public Object execute(ExecutionEvent event) throws ExecutionException {
    IWorkspace workspace = ResourcesPlugin.getWorkspace();
    IWorkspaceRoot root = workspace.getRoot();
    // ワークスペース内の全てのプロジェクトを取得します。
    IProject[] projects = root.getProjects();
    // 全てのプロジェクトで繰り返します。
    for (IProject project : projects) {
      try {
        // Java ネーチャーを持つオープン状態のプロジェクトでのみ機能します。
        if (project.isOpen()
            & project.isNatureEnabled(JavaCore.NATURE_ID)) {
          createPackage(project);
        }
      } catch (CoreException e) {
        e.printStackTrace();
      }
    }
    return null;
  }

  private void createPackage(IProject project) throws JavaModelException {
    IJavaProject javaProject = JavaCore.create(project);
    IFolder folder = project.getFolder("src");
    // folder.create(true, true, null);
    IPackageFragmentRoot srcFolder = javaProject
        .getPackageFragmentRoot(folder);
    IPackageFragment fragment = srcFolder.createPackageFragment(project.getName(), true, null);
  }
} 

Tip
これはJavaプロジェクト名を持つパッケージをワークスペース内の開いているプロジェクト全てに追加します。
あなたが本当にこの動作を望んでいるか確認して下さい。またあなたはパッケージエクスプローラのコンテクストメニューにアクションを追加し、選択されたプロジェクトにのみそれを適用出来ます。あなたはそのやり方をパッケージエクスプローラの拡張で学ぶことが出来ます。”de.vogella.jdt.packageexplorer”プロジェクトのソースページ上に例があります。コマンドハンドラ”AddPackage.java”を見て下さい。

4.2. クラスパスの変更


また、あなたはプロジェクトのクラスパスを変更出来ます。以下のサンプルハンドラは”de.vogella.jdt.addclasspath”プロジェクトに含まれています。これはあなたのプロジェクトへJUnit4を追加します。
※原文 changeClassPath → changeClasspath

package de.vogella.jdt.addclasspath.handlers;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;

public class SampleHandler extends AbstractHandler {

  private static final String JDT_NATURE = "org.eclipse.jdt.core.javanature";

  
  public Object execute(ExecutionEvent event) throws ExecutionException {
    IWorkspace workspace = ResourcesPlugin.getWorkspace();
    IWorkspaceRoot root = workspace.getRoot();
    // ワークスペース内の全てのプロジェクトを取得します。
    IProject[] projects = root.getProjects();
    // 全てのプロジェクトで繰り返します。
    for (IProject project : projects) {
      try {
        // Java ネーチャーを持つオープン状態のプロジェクトでのみ機能します。
        if (project.isOpen() && project.isNatureEnabled(JDT_NATURE)) {
          changeClasspath(project);
        }
      } catch (CoreException e) {
        e.printStackTrace(); 
      }
    }
    return null;
  }
  
  private void changeClasspath(IProject project) throws JavaModelException {
    IJavaProject javaProject = JavaCore.create(project);
    IClasspathEntry[] entries = javaProject.getRawClasspath();
    IClasspathEntry[] newEntries = new IClasspathEntry[entries.length + 1];

    System.arraycopy(entries, 0, newEntries, 0, entries.length);

    // Pathを使用してコンテナへ新しいエントリを追加します。
    Path junitPath = new Path("org.eclipse.jdt.junit.JUNIT_CONTAINER/4");
    IClasspathEntry junitEntry = JavaCore
        .newContainerEntry(junitPath);
    newEntries[entries.length] = JavaCore
        .newContainerEntry(junitEntry.getPath());
    javaProject.setRawClasspath(newEntries, null);
  }
  
} 

「Eclipse JDT – Abstract Syntax Tree (AST) and the Java Model – Tutorial」を翻訳した(1)
「Eclipse JDT – Abstract Syntax Tree (AST) and the Java Model – Tutorial」を翻訳した(3)