[Meadowで開発へ戻る]

Javaソースファイルの編集

Meadow+JDEによるJavaソースファイルの編集機能について見ていきます。


ソースコード自動生成

新しいソースコードの雛形生成

新たにJavaのソースコードを編集するときに、雛形を生成する。生成する種類は次のとおり。

  1. Class... public classを定義するソースファイル
  2. Console... main()メソッドを持ったpublic classを定義するソースファイル
  3. Swing App ... Swingライブラリを使ったGUIアプリケーションクラスのソースファイル
JDEメニューのJDE New→Class..で生成した例
/**
 * NewClassA.java
 *
 *
 * Created: Mon Aug 14 02:58:01 2000
 *
 * @author <a href="mailto:torutk@alles.or.jp">Toru TAKAHASHI</a>
 * @version
 */

public class NewClassA extends SuperClass
    implements Interface {
    public NewClassA () {
        
    }
}// NewClassA

[*1] JDE 2.2.1以降のjde-gen.elには、@authorの後ろの展開と、クラス・メソッド定義の{の前の空白がうまく制御できていない(というか気に入らない)ので、修正しています。
JDE2.2.7beta3で@authorの後ろの展開は修正されました。{の前の空白は未のままです。

修正版 jde-gen.el
patch用ファイル jde-gen.el.patch 各バージョン毎に修正するのが面倒なのでdiffでパッチ用差分ファイルを作ってみました。JDE 2.2.3 - 2.2.6について動作確認しています。実行方法は、jde-gen.elのあるディレクトリで
$ patch -p1 <jde-gen.el.patch
jde-gen-1.32_space.patch JDE2.2.7beta3以降用
操作方法
メニューバーのFiles→JDE Newで開かれるメニューから上述のいずれかを選択。なお、3.のSwing Appはメニュー中にはないので、Other...を選択し、ミニバッファ上にTemplate:と表示された後ろにSwing Appと入力する。
Tips1
ミニバッファで何か聞かれたとき、入力する文字列が分からないときはTabキーを押すとよい。その時入力可能な文字列候補が表示される。
Tips2
ここで生成される雛形を変更することができる。JDE→Project→Options→Autocodeで開かれるCustomize Aproposバッファ中で、Jde Gen Class Buffer Template, Jde Gen Console Buffer Template, Jde Gen Jfc App Buffer Templateの3項目。さらに別な項目を追加することも可能。
Tips3
プロジェクトでファイルの先頭に共通のコメント(著作権表記やプロジェクトを述べたもの等)を入れる場合も、この雛形であらかじめ設定しておくと楽です。JDE→Project→Options→Autocodeで開かれるCustomize Aproposバッファ中で、Jde Gen Buffer Boilerplateに記述します。

ファイル先頭に共通の記述を入れるテンプレート

JDE→Project→Options→Autocode で開かれるCustomize Aproposバッファ中で、Jde Gen Buffer Boilerplateの項目に記述する。

ファイル先頭記述テンプレート設定例
Jde Gen Buffer Boilerplate: [Hide]
[INS] [DEL] Line: /**
[INS] [DEL] Line:  * Torutk jde mastering project.
[INS] [DEL] Line:  * Copyright (C) 2000 by Toru TAKAHASHI, all rights reserved.
[INS] [DEL] Line:  * 
[INS] [DEL] Line:  */
[INS] [DEL] Line: 
[INS]
   [State]: you have edited the value as text, but you have not set the option.
Lines of boilerplate text to put at the head of a buffer template.

getter/setterメソッドペアの生成

Javaでは、インスタンス変数はメソッドを介してアクセスすることがよいコーディングとされています。したがって、コーディング中はインスタンス変数の定義とそのアクセス用メソッドをひたすら記述していく、やや機械的な作業を強いられます。そんなときにこのコード生成機能を使います。JDEには2通りの生成方法があります。

1.テンプレート(jde-gen-get-set-var-template)

操作方法
JDEメニュー→Templates→Get/Set Pair...
ミニバッファにVariable typeを聞いてくるので、型を入力する。
次に、Variable nameを聞いてくるので変数名を入力する。
すると、下記表のようなソースコードがカーソル位置に展開されます。
Variable type:String, Variable name:firstName で生成した例
String firstName;
        
/**
 * Get the value of firstName.
 * @return Value of firstName.
 */
public String getFirstName() {return firstName;}
       
/**
 * Set the value of firstName.
 * @param v  Value to assign to firstName.
 */
public void setFirstName(String  v) {this.firstName = v;}

JDEのGet/Set Pairテンプレートで不満な点が3つあります。1つ目は、引数がprivateでないこと、2つ目は、引数の名前が'v'と自動的になってしまうこと、最後の1つは、インスタンス変数の位置がカーソル位置になってしまうことです。本当はフィールドはクラス先頭付近、メソッドはその次にしたいところです。Emacsのよいところは、拡張、改良が細かくできることなので、どんどん解決していきましょう。まず1と2を解決してみました。Get/Set Pair生成テンプレートの改良を参照。

2.ウィザード(jde-wiz-get-set-methods)

クラスに定義されているフィールドのGetメソッドとSetメソッドを自動生成します。既にGet/Setメソッドが存在していれば、二重に生成されないようになっています。

操作方法
JDEメニュー→Wizards→Generate Get/Set Methods
すると、下記表のようなソースコードに対してカーソル位置以下にGet/Setメソッドが展開されます。
先にフィールドを記述しておく
class Foo {
  String firstName;    
     :
}
Get/Setウィザードで生成されたソース
class Foo {
    String firstName;
         :
    /**
     * Gets the value of firstName
     *
     * @return the value of firstName
     */
    public String getFirstName() {
        return this.firstName;
    }

    /**
     * Sets the value of firstName
     *
     * @param argFirstName Value to assign to this.firstName
     */
    public void setFirstName(String argFirstName){
        this.firstName = argFirstName;
    }
}
Tips1
setメソッドの引数名は、"arg" + フィールド名となっています。この"arg"は自由に変更できます。カスタマイズでjde-wiz-get-set-variable-prefixの値を変更します。
Tips2
Set/GetメソッドのJavadocコメントは、カスタマイズでjde-wiz-get-javadoc-template、 およびjde-wiz-set-javadoc-templateの値で変更できます。
Tips3
コーディング規約でフィールド名の接頭辞または接尾辞に一定の記号や文字列を付与せざるを得ない場合があります(例:_name)。この記号がGet/Setメソッドのメソッド名に含まれないようにすることができます。カスタマイズでjde-wiz-get-set-variable-conventionの値を設定します。
Tips4
Setメソッドだけ、あるいはGetメソッドだけを生成したい場合は、カスタマイズでjde-wiz-get-set-methods-includeの値を"Get only"か"Set only"に変更します(デフォルトは"Both")。
Tips5
Setメソッド、Getメソッドの並び順を指定することができます。カスタマイズでjde-wiz-get-set-methods-orderの値を以下から選択します。
"Get followed by set for each field"
"Set followed by get for each field"
"All get methods followed by all set methods"
"All set methods followed by all get methods"

Interfaceを実装するコードの生成

Interfaceで定義したメソッドを実装するときに、実装クラスでそれらメソッドのシグネチャを1から打ち込むのは手間です。Meadow+JDEでは、この手間をコード生成機能で省いてくれます。実装したいInterfaceで定義されているメソッドがコメント付きで挿入されるほか、Interfaceで定義されているメソッドの引数・戻り値型がimport文として生成されます。実装したいインタフェースのクラスがクラスパスに含まれている必要があります。クラスパスは、JDEのプロジェクトで設定します。

操作方法
JDEメニュー→Wizards→Interface Implement または、C-c C-v C-f
ミニバッファにInterface Nameを聞いてくるので、FQCNでクラス名を入力する。
Tips1
カーソル位置にメソッドの実装コードが入るのであらかじめカーソル位置を合わせておく。また、インデントがずれた場合は、自動インデント操作を実施する。

スーパークラスのメソッドをオーバーライドするコードの生成

スーパークラスで定義しているメソッドをオーバーライドするときに、サブクラス側でそのメソッドシグネチャを1から打ち込み、引数や戻り値に使うクラス型をimport文に記述するのはかなりの手間です。

操作方法
JDEメニュー→Wizards→Override Method
ミニバッファにMethod nameを聞いてくるので、メソッド名を入力する。

メソッドをオーバーライドするコードの生成

スーパークラスで定義したメソッドをオーバーライドするときに、サブクラスでそのメソッドのシグネチャを1から打ち込むのは手間であるだけでなく、メソッド名に1文字でもスペルミスがあるとオーバーライドではなく新規メソッドとして定義されてしまうため、デバッグに非常に苦労します。Meadow+JDEでは、このオーバーライドしたいメソッドのシグネチャ記述を自動で行うことが出来ます。

操作方法
JDEメニュー→Wizards→Override Method
ミニバッファにMethod Nameを聞いてくるので、メソッド名を入力する。
Tips
実行にあたって、現在編集中のクラスをコンパイルしておく必要がある。またJDEからそのクラスへのパスが通っている必要がある。
JPanelを継承したクラスで実行、Method Name:paintComponentを入力した例
/**
 *
 * @param param1 <description>
 */
public void paintComponent(Graphics param1) {
  //TO DO: Implement this method.
}

委譲コードの自動生成

Javaでは(というかオブジェクト指向プログラミングでは)、委譲を使うことがよくあります。委譲は機械的なコーディングをしなければならないので、かなり苦痛です。それをやわらげてくれる機能がJDEにあります。

操作方法
JDEメニュー→Wizards→Delegate Methods
ミニバッファに属性名とそのFQCNを聞いてくるので、フィールド名とパッケージ付きクラス名を入力する。フィールド名のオブジェクトへ、クラス名で指定したクラスが持つpublicメソッドの呼び出しを委譲するコードを生成します。

import文の自動生成

コードを書いているときに、新しいクラスを使用するために、import文を書くのは面倒な作業です。JDEでは、コマンド1つでimport文を追加する機能があります。既にimport済みなら、2重にimport文を加えることはありません。

操作方法
JDEメニュー→Wizards→Import Class
または、C-c C-v C-z
ミニバッファにClass:とクラス名を聞いてくるので、クラス名を入力する。本コマンド実行時にあらかじめキャレット(カーソル)をimportしたいクラス名の上または直後に置いておくと、ミニバッファにそのクラス名が現れる。
Tips1
JDK標準以外のクラスライブラリに含まれるクラスを使用するときは、あらかじめJde Global Classpathにそのライブラリを設定しておく必要があります。設定方法は、JDE設定のプロジェクト設定を参照。
Tips2
自動で挿入されるimport文の位置はファイル先頭でpackage文があればその後です。既にimport文が存在していれば、そのimport文群の最後に挿入されます。そこで、あらかじめimport文を置きたい位置に1行だけimport文を記述しておけば、以後自動生成されるimport文はその続きに挿入されます。
Tips3
コーディングしながら随時import文を自動生成していると、import文の並びがばらばらになってしまいます。ソースコードの美しさの観点ではimport文はやっぱりパッケージごとに整然と並んでいて欲しいです。
(1) M-x jde-import-organizeとコマンドを実行すれば、import文群をソートしてくれます。
(2) プロジェクト設定で以下の設定をしておくと、import文自動生成時にソートしてくれます。
設定項目名 デフォルト値 目的 設定する値(例)
Jde Import Auto Sort off import後自動的に整列し直す on
Tips4
不要なimport文を探し出すのは面倒です。そのときはM-x jde-import-kill-extra-importsとコマンドを実行すれば削除できます。詳しくは不要なimport文をチェックするで。

Javadocコメントの自動生成

メソッドを書いた後に、Javadoc用コメントを記述するのは面倒な作業です。JDEEでは、コーディングしたメソッドのJavadoc用コメントを生成する機能があります。

操作方法
JDEメニュー→Documentation→Add

ソースコード補完機能

println文の補完

System.out.println("..."); というコードを書くことは非常に多いですが、タイプするのは長くて面倒です。そこで、、、

操作方法
JDEメニュー→Templates→println...
または、C-c C-v C-l
ミニバッファにPrint out:と、printlnメソッドへ渡す引数を聞いてくるので、入力する。ミニバッファに入力した文字列が、printlnメソッドの引数として記述されるので、例えばSystem.out.println("Hello, World");とコーディングしたい場合は、"Hello, World"と入力する。

フィールド・メソッド名の補完

JBuilderでは、オブジェクト名の後にピリオド'.'をキータイプすると、そのオブジェクトが持つフィールドおよびメソッド名の一覧がポップアップされる機能があります。こんなのに頼らずAPIドキュメントを見なきゃだめだという意見もありますが、人間便利な機能に慣れるとそれなしではいられなくなってしまいます。

操作方法1
C-c C-v . とタイプすると、ミニバッファに候補が現れます。例えば、StringBuffer型の変数bufが定義されていた場合、buf.ap とタイプした後にC-c C-v . とタイプすると、ミニバッファにappend(...)と候補となるフィールド・メソッド名が表示されます。候補が複数あるときは、C-c C-v . とタイプする毎に次の候補がミニバッファに表示されます。
操作方法2
C-c C-v C-. とタイプすると、方法1のミニバッファではなく、ポップアップメニューに候補一覧が表示される。

ソースコードブラウズ

speedbarによるクラスブラウザ

ツリー構造でJavaソースファイルリストを表示する。クラス内のメソッド、フィールドまで展開され、該当ソースコード行をEmacsウィンドウ側に表示させることができます。

Speedbar画面例
操作方法
メニューバーのJDE→SpeedbarでSpeedbarウィンドウが開かれます。

imenuによるファイル内ブラウズ

現在のBufferに開いているクラスのソースのメンバ(フィールドおよびメソッド)を一覧し選択した個所へ移動することができます。

タグテーブル

 タグテーブルは、ファイル名・クラス名・メソッド名などとそれらのファイル内の位置の一覧です。これを使うと、あるメソッド名がどのファイルで定義されているかを見つけ出すことが容易になります。ファイルの数が多くなりがちなJavaではとても便利な機能です。

JDEには、Java文法に対応したjtagsコマンドが含まれていますが、Meadowに含まれるetagsの問題のため、機能しません。Meadowの次期リリースに含まれるetagsでは解消されるようです。(Meadow1.06b1ではOk)

1.1 タグテーブルの作成(etags編)

 タグテーブルを作成するには、etagsコマンドを使います。etagsはMeadowのbinディレクトリに存在します。src以下の複数ディレクトリに格納されているソースファイル全体のタグテーブルを作成するには、次のようにGNUのfindコマンドと組み合わせると簡単です。

    C:\home\torutk\work\src>find . -name *.java -print | etags -

 すると、TAGSという名前のファイルが生成されます。

1.2 タグテーブルの作成(jtags編)

 JDEに含まれるjtagsは、シェルスクリプトなため、Cygnus(GNU Win32)環境が必要です。jtagsを引数なしで実行すると、カレントディレクトリ以下のサブディレクトリを再帰的に検索し、TAGSファイルにタグテーブルを作成します。

2.Meadow上でタグテーブルを指定する

 タグテーブルを指定するには、M-x visit-tags-tableと打ち、ミニバッファ欄にタグテーブルのあるディレクトリ(1.の例では~/work/src)を入力する。

3.Meadow上でのタグテーブルの使用

 ソースコード上でクラス名やメソッド名にポイントを合わせ、M-. と打つと、その名前が定義されている場所をタグテーブルを使って探し、そのファイルを開いて該当個所を表示します。または、M-. name でnameを含むクラス名・メソッド名を検索します。


Emacs/JDEのカスタマイズ

jde-modeのカスタマイズ

JDEは、Emacsのメジャーモードとしてjde-modeを提供しています。そこで、jde-mode-hookを使ってカスタマイズをすることができます。

インデントスタイルの変更

JDEは、cc-modeをベースにしたjde-modeを提供しているので、cc-modeのインデント設定方法で変更することができます。例えば長い行があって、これをインデントを保って改行するとします。

長い行を適切に改行して適切な長さにしたい
SomeType mySomeType = new SomeType(SettingType a, ConfigurationType b);

JDEではデフォルトでは次のようなインデント設定を行います。

JDEのデフォルトインデントスタイル(例)
SomeType mySomeType = new SomeType(SettingType a,
                                   ConfigurationType b);

これでもまだ長いとき、(の直後に改行を入れると、JDEではこのような状態になってしまいます。

括弧の直後で改行しても次の行がそこから始まる
SomeType mySomeType = new SomeType(
                                   SettingType a,
                                   ConfigurationType b
                                  );

これは、JDEのスタイル設定がそうなっているからで、例え手作業で(BSを打って)前へ移動させても、自動インデントをしたりその行に編集を加えてEnterを押したりすると、デフォルトの位置に戻ってしまいます。これでは不便なので、インデントを変更したいと思います。

このようなインデントに修正したい
SomeType mySomeType = new SomeType(
    SettingType a, ConfigurationType b
);

この設定は次のようなElispコードを.emacsに追加します。

(add-hook 'jde-mode-hook
          '(lambda ()
             (c-set-offset 'arglist-intro '+)
             (c-set-offset 'arglist-close 0)))

arglist-introは、引数の開始が独立した行になる場合のインデント量を設定する変数です。+は、標準インデント量(JDEモードの場合は4スペース)を意味します。なお、++とすると、標準インデント量(JDEモードの場合は4)の2倍(つまり8スペース分)を意味します。
arglist-closeは、引数の指定の後にくる閉じ括弧が独立した行にある場合のインデント量を設定する変数です。0は、そのブロックのインデント位置となります。

インデントを設定する変数の調査・設定方法

Emacsのカスタマイズ

インデント時のタブ幅

Javaはマルチプラットフォーム対応なので、様々な環境でソースを閲覧・編集されることが多いです。そこで、インデントにはTABを使わず、スペースを用いることを推奨します。Emacsではインデント時にデフォルトではTABコードを割り当てますが、これをスペースにするよう設定を行います。設定は.emacsではなく、jde-modeに限定するために、上述のjde-mode-hookにadd-hookで追加している設定に下記を追加します。

(setq indent-tabs-mode nil)