アクションの作成
アクションクラスの作成を行います。
今回は作成するアクションクラスには、「IActionDelegate#runで呼び出された際に、PHPEclipseから選択されているエディタで編集中のPHP情報を元にsetter/getterの文字列を生成し、その文字列を編集中のエディタに反映させる」という動作をさせます。
package jp.codezine.popup.actions; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import net.sourceforge.phpdt.core.ICompilationUnit; import net.sourceforge.phpdt.internal.corext.util.CodeFormatterUtil; import net.sourceforge.phpdt.ui.IWorkingCopyManager; import net.sourceforge.phpdt.ui.PreferenceConstants; import net.sourceforge.phpeclipse.PHPeclipsePlugin; import net.sourceforge.phpeclipse.builder.IdentifierIndexManager; import net.sourceforge.phpeclipse.obfuscator.PHPIdentifier; import net.sourceforge.phpeclipse.phpeditor.PHPUnitEditor; import org.eclipse.core.resources.IFile; import org.eclipse.jface.action.IAction; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.ui.IEditorActionDelegate; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.texteditor.IDocumentProvider; public class SetterGetterAction implements IEditorActionDelegate { private IEditorPart targetEditor; public void setActiveEditor(IAction action, IEditorPart targetEditor) { this.targetEditor = targetEditor; } public void selectionChanged(IAction action, ISelection selection) { } public void run(IAction action) { // PHPUnitEditor以外からのアクションは何も行わない if (!(targetEditor instanceof PHPUnitEditor)) { return; } PHPUnitEditor editor = (PHPUnitEditor) targetEditor; PHPeclipsePlugin plugin = PHPeclipsePlugin.getDefault(); IWorkingCopyManager workingCopyManager = plugin.getWorkingCopyManager(); ICompilationUnit unit = workingCopyManager.getWorkingCopy(editor.getEditorInput()); IFile file = (IFile) unit.getResource(); // プロジェクトからPHPファイルの一覧を取得 IdentifierIndexManager indexManager = plugin.getIndexManager(file.getProject()); // インデックスからファイルを指定し、PHPの解析結果を取得 Map identifiers = indexManager.getIdentifiers(file); Iterator iterator = identifiers.entrySet().iterator(); List<String> methods = new ArrayList <String>(); List<String> properties = new ArrayList <String>(); while(iterator.hasNext()){ Map.Entry entry = (Map.Entry)iterator.next(); Object value = entry.getValue(); if(value instanceof List){ List valueList = (List) value; for(int i = 0; i < valueList.size(); i++){ PHPIdentifier phpId = (PHPIdentifier)valueList.get(i); // メソッドであれば if(phpId.isMethod()){ // メソッド名の取得 methods.add(phpId.getIdentifier()); } // プロパティであれば if(phpId.isVariable()){ // プロパティ名の取得 properties.add(phpId.getIdentifier()); } } // end foreach valueList } // end instanceof List } // end while // 空白文字の取得 String whiteSpace = getWhiteSpace(plugin); // 改行文字の取得 String lineSeparator = getLineDelimiter(editor); StringBuffer buf = new StringBuffer(100); for(int i = 0; i < properties.size(); ++i){ String property = (String)properties.get(i); // メソッド作成のためのインナークラス MethodCreator creator = new MethodCreator(property, whiteSpace, lineSeparator); //setterメソッドが存在しなければ if(!creator.hasSetterMethod(methods)){ //setterメソッドの作成 buf.append(creator.createSetter()); } //getterメソッドが存在しなければ if(!creator.hasGetterMethod(methods)){ //getterメソッドの作成 buf.append(creator.createGetter()); } } // end foreach properties try { // 現在のエディタに作成したメソッドを追記する appendLine(editor, buf.toString()); } catch (BadLocationException e) { // 例外はログファイルに書き込む PHPeclipsePlugin.log(e); } } protected String getWhiteSpace(PHPeclipsePlugin plugin){ // プリファレンスからタブ文字をスペースとして // 使用するかどうかを取得 IPreferenceStore preference = plugin.getPreferenceStore(); if (preference.getBoolean( PreferenceConstants.EDITOR_SPACES_FOR_TABS)) { // スペースを使用する場合 // タブサイズの取得 int tabSize = CodeFormatterUtil.getTabWidth(); StringBuffer buf = new StringBuffer(); for(int i = 0; i < tabSize; i++){ buf.append(' '); } // 指定サイズ分のスペースを返す return buf.toString(); } // タブ文字を返す return "\t"; } protected void appendLine(PHPUnitEditor editor, String text) throws BadLocationException { IDocumentProvider documentProvider = editor.getDocumentProvider(); IDocument document = documentProvider.getDocument(editor.getEditorInput()); ISelectionProvider selectionProvider = editor.getSelectionProvider(); ISelection selection = selectionProvider.getSelection(); if(selection instanceof ITextSelection){ ITextSelection textSelection = (ITextSelection) selection; int offset = textSelection.getOffset(); int length = textSelection.getLength(); // 現在のドキュメントの選択行に作成したテキストを追加 document.replace(offset, length, text); } } protected String getLineDelimiter(PHPUnitEditor editor) { IDocumentProvider documentProvider = editor.getDocumentProvider(); IDocument document = documentProvider.getDocument(editor.getEditorInput()); try { // ドキュメントの最初の行から改行文字を返す return document.getLineDelimiter(0); } catch(BadLocationException e){ // 例外時はシステムの改行文字を返す return System.getProperty("line.separator", "\n"); } } }
PHPEclipseのIdentifierIndexManagerから取得した、PHPクラス内のプロパティ情報を元にメソッドを生成する内部クラスのMethodCreatorは、次のようにしました。
class MethodCreator { /** プロパティ名 */ String propertyName; /**setterメソッド名 */ String setterMethodName; /**getterメソッド名 */ String getterMethodName; /** 空白文字 */ String whiteSpace; /** 改行文字 */ String lineSeparator; MethodCreator(String propertyName, String whiteSpace, String lineSeparator){ String capitalizedName = capitalize(propertyName); this.propertyName = propertyName; this.setterMethodName = "set" + capitalizedName; this.getterMethodName = "get" + capitalizedName; this.whiteSpace = whiteSpace; this.lineSeparator = lineSeparator; } String capitalize(String propertyName){ return Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1); } boolean hasSetterMethod(List methods){ return methods.contains(setterMethodName); } boolean hasGetterMethod(List methods){ return methods.contains(getterMethodName); } /**
*getterメソッドの生成
* @returngetterメソッドの内容
*/ String createSetter(){ StringBuffer buf = new StringBuffer(); buf.append(lineSeparator); buf.append(indent(1)).append("public function ") .append(setterMethodName); buf.append(" ($").append(propertyName).append(") {"); buf.append(lineSeparator); buf.append(indent(2)).append("$this->"); buf.append(propertyName).append(" = $") .append(propertyName).append(";"); buf.append(lineSeparator); buf.append(indent(1)).append("}"); buf.append(lineSeparator); return buf.toString(); } /**
*setterメソッドの生成
* @returnsetterメソッドの内容
*/ String createGetter(){ StringBuffer buf = new StringBuffer(); buf.append(lineSeparator); buf.append(indent(1)).append("public function ") .append(getterMethodName); buf.append(" () {"); buf.append(lineSeparator); buf.append(indent(2)).append("return ").append("$this->"); buf.append(propertyName).append(";"); buf.append(lineSeparator); buf.append(indent(1)).append("}"); buf.append(lineSeparator); return buf.toString(); } /**
* 指定された回数分だけ、空白文字を生成する
* @param count 空白文字を作成する回数
* @return 空白文字
*/ String indent(int count){ StringBuffer buf = new StringBuffer(); for(int i = 0; i < count; ++i){ buf.append(whiteSpace); } return buf.toString(); } }
プラグインの起動(動作の確認)
それでは、ここで作成したアクションを元にもう一度動作確認をしてみます。
先ほどと同じように[マニフェストエディタ]から[概要]タブ→[Eclipse アプリケーションの起動]でEclipseを起動します。起動したらPHPファイルを作成し、PHPクラスを生成してプロパティを作ります。準備ができたら作成したメニューからアクションを起動してみましょう。
無事、setter/getterの生成ができたことを確認できればプラグインは完成です。次は、作成したプラグインを配布可能な形式にしましょう。

