2011年6月11日土曜日

[XYZZYTIPS]PHPDoc風関数コメントとコメントを生成するマクロ

仕事でPHPを利用しているのですが、PHPは型の指定を一切しないのに、PHPDoc用の関数コメントには型を明記しないといけないんですよね。それとインデントをそろえるのが面倒くさくて関数とコメントを生成するマクロを作成してみました。


具体的には、

これはテスト用の関数です。
@test_function param:array:配列 return:string

という入力を
/**
* これはテスト用の関数です。
*
* @param  array  param 配列
* @return string       
*/
function test_function($param) {



}

に変更します。



これは次のような手順で実現しています。

  1. コメント部分を生成する
    1. 「@」ではじまる行以外は、単純にコメントとして追加していく。
    2. 「@」ではじまる行に対して、下記の処理を実行する。
      1. 空白で区切ったリストを生成する
      2. 1つ目より後の要素に対して、
        1. 「:」で区切ったリストを生成する
        2. 「return」ではじまる要素以外の要素を「@param」、「型」、「変数名」、「コメント」のリストにする。
        3. 生成したリストから1行分の引数コメントを一つの要素にしたリストを生成する
        4. リストからコメントを生成する



    この部分のソースはこちら
    ;;リストを指定した要素の順番で並び替える
    (defun list_sort (list sortList &optional newList)
    (if (equal nil sortList) newList
    (if (equal nil (elt list (first sortList)))
    (list_sort list (rest sortList) newList)
    (list_sort list (rest sortList) (append newList (list (elt list (first sortList)))))))
    )
    
    
    ;;リストの指定した位置に要素を追加する
    (defun list_insert(list index item)
    (let (temp_list)
    (setq temp_list (append (subseq list 0 index) (list item)))
    (if (> (list-length list) index)
    (append temp_list (subseq list index (list-length list)))
    temp_list)))
    
    
    ;; form:array:なんとか property:array:プロパティ return:array:フォーム配列
    ;; というリストをlist(@param array form なんとか)list(@param array property プロパティ) list(@return array "" フォーム配列)
    ;; というリストに変更する
    (defun param_list (list &optional newList)
    (if (equal nil list) (reverse newList)
    (if (equal "return" (first (split-string (first list) ":")))
    (param_list (rest list) (cons (cons "@return" (list_insert (rest (split-string (first list) ":")) 1 "")) newList))
    (param_list (rest list) (cons (cons "@param" (list_sort (split-string (first list) ":") '(1 0 2))) newList)))))
    
    ;;各リストの列ごとの最大文字数取得
    (defun column_max_length (list)
    (let ((length_list nil) (i 0) (max_length (apply #'max (mapcar #'length list))))
    (while (<= i max_length)
    (setq length_list (cons (apply #'max (mapcar #'length (mapcar (lambda (a)(elt a i)) list))) length_list)
    i (+ i 1))
    )
    (reverse length_list))
    )
    
    ;;引数コメント用リストを生成する
    (defun param_comment_list (list length_list &optional (new_list nil))
    (if (equal list nil) (reverse new_list)
    (let () (setq new_list (cons (reduce
    (lambda(a b)(concat a " " b))
    (mapcar (lambda(item length)
    (let ((format_str (format nil "~~A~~@~AT" (- length (length item)))))
    (format nil format_str item))) (first list) length_list))
    new_list))
    (param_comment_list (rest list) length_list new_list)))
    )
    
    ;; 関数コメントを生成する
    (defun function_comment (ls commentStr)
    (setq list (mapcar (lambda (item) (if (equal "return" (first (split-string item ":"))) item (concat "$" item))) (rest ls)))
    (setq list (if (not (equal nil list)) (param_comment_list (param_list list) (column_max_length (param_list list)))))
    (if (equal nil list) commentStr (concat commentStr " * " (reduce (lambda(a b) (concat a "\n * " b)) list) "\n")))
    
  2. 関数部分を生成する
  3. ;; PHP関数を生成する
    (defun parse_function (ls)
    (setq param_list (mapcar (lambda(item)
    (if (not (equal "return" (first (split-string item ":"))))
    (concat "$" (first (split-string item ":"))))) (rest ls)))
    (setq param_list (remove nil param_list))
    (setq param_list (if (equal nil param_list) (list "") param_list))
    (concat "function " (first ls) "(" (reduce (lambda(a b)(concat a ", " b)) param_list) ") {\n\n\n\n}")
    )
    

最後に上記2つの処理を呼び出す関数を生成する

(defun create_function(str)
(let (
(total_function "\n/**\n")
(ls (split-string str "\n"))
(func_str "")
)
(loop
(if (equal nil ls)(return (concat total_function " */\n\n" func_str)))
(if (string-match "@" (car ls))
(let ((param_item (split-string (substitute-string (car ls) "@" "") " ")))
(setq total_function (function_comment param_item (concat total_function " *\n"))
func_str (parse_function param_item)))
(setq total_function (concat total_function (format nil " * ~A\n" (car ls))))
)
(setq ls (cdr ls))
)
)
)

0 件のコメント:

コメントを投稿