Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Annotation Processing を使ってソースを生成する

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Annotation Processing を使ってソースを生成する

Avatar for Hiroshi Kurokawa

Hiroshi Kurokawa

December 17, 2014
Tweet

More Decks by Hiroshi Kurokawa

Other Decks in Programming

Transcript

  1. ある Androider の悩み ( ^ω ^) ここに Android のコードがあるじゃろ? これをこうして...

    g e t L o a d e r M a n a g e r ( ) . i n i t L o a d e r ( L O A D E R _ I D _ 1 , n u l l , n e w L o a d e r C a l l b a c k s < D a t a > ( ) { @ O v e r r i d e p u b l i c L o a d e r < D a t a > o n C r e a t e L o a d e r ( i n t i d , B u n d l e a r g s ) { r e t u r n n e w D a t a L o a d e r ( ) ; } @ O v e r r i d e p u b l i c v o i d o n L o a d F i n i s h e d ( L o a d e r < D a t a > l o a d e r , D a t a d a t a ) { o n D a t a L o a d F i n i s h e d ( d a t a ) ; } . . . } ) ; g e t L o a d e r M a n a g e r ( ) . i n i t L o a d e r ( L O A D E R _ I D _ 2 , n u l l , n e w L o a d e r C a l l b a c k s < M e s s a g e L i s t > ( ) { @ O v e r r i d e p u b l i c L o a d e r < M e s s a g e L i s t > o n C r e a t e L o a d e r ( i n t i d , B u n d l e a r g s ) { r e t u r n n e w M e s s a g e L i s t L o a d e r ( ) ; } @ O v e r r i d e p u b l i c v o i d o n L o a d F i n i s h e d ( L o a d e r < M e s s a g e L i s t > l o a d e r , M e s s a g e L i s t d a t a ) { o n M e s s a g e L i s t L o a d F i n i s h e d ( d a t a ) } . . . } ) ;
  2. こうしたい! p r o t e c t e d

    v o i d o n C r e a t e ( B u n d l e s a v e d I n s t a n c e S t a t e ) { s u p e r . o n C r e a t e ( s a v e d I n s t a n c e S t a t e ) ; M u l t i L o a d e r . i n j e c t ( t h i s , L O A D E R _ I D _ 1 , L O A D E R _ I D _ 2 ) ; } @ O n C r e a t e L o a d e r ( L O A D E R _ I D _ 1 ) p u b l i c L o a d e r < D a t a > o n C r e a t e D a t a L o a d e r ( i n t i d , B u n d l e a r g s ) { . . . } @ O n L o a d F i n i s h e d ( L O A D E R _ I D _ 1 ) p u b l i c v o i d o n D a t a L o a d F i n i s h e d ( L o a d e r < D a t a > l o a d e r , D a t a d a t a ) { . . . } @ O n C r e a t e L o a d e r ( L O A D E R _ I D _ 2 ) p u b l i c L o a d e r < M e s s a g e L i s t > o n C r e a t e M e s s a g e L i s t L o a d e r ( i n t i d , B u n d l e a r g s ) { . . . } @ O n L o a d F i n i s h e d ( L O A D E R _ I D _ 2 ) p u b l i c v o i d o n M e s s a g e L i s t L o a d F i n i s h e d ( L o a d e r < M e s s a g e L i s t > l o a d e r , M e s s a g e L i s t d a t a ) { . . .
  3. Annotation Processing Java SE 6 で導入されたアノテーションを javac で処理する仕 組み。J2SE 5.0

    では apt という非標準ツールがあった。 j a v a x . a n n o t a t i o n . p r o c e s s i n g . A b s t r a c t P r o c e s s o r を継承したクラスを定義して、 p a c k a g e c o m . h k u r o k a w a . m u l t i l o a d e r . i n t e r n a l ; p u b l i c c l a s s M u l t i L o a d e r P r o c e s s o r e x t e n d s A b s t r a c t P r o c e s s o r { @ O v e r r i d e p u b l i c b o o l e a n p r o c e s s ( S e t < ? e x t e n d s T y p e E l e m e n t > a n n o t a t i o n s , R o u n d E n v i r o n m e n t r o u n d . . . } } クラス名を M E T A - I N F / s e r v i c e s / j a v a x . a n n o t a t i o n . p r o c e s s i n g . P r o c e s s o r に書いておけば良い。 c o m . h k u r o k a w a . m u l t i l o a d e r . i n t e r n a l . M u l t i L o a d e r P r o c e s s o r
  4. Android Studio での開発 Android の JDK には、 j a v

    a x . a n n o t a t i o n . p r o c e s s i n g . A b s t r a c t P r o c e s s o r が含まれていない。 従って、Processor のコードと Android のコードを同じプロジ ェクトで一緒に gradle ビルドすることはできない(Maven だ とできる?)。
  5. プロジェクト構成 以下のようなプロジェクト構成にする必要がある multiloader Android ライブラリモジュー ル。Android アプリから呼び出 す API を提供。

    multiloader-compiler Annotation Processing を行う コード。Android アプリには含 まれない。 multiloader-sample ライブラリを呼び出すサンプ ルアプリ。
  6. build.gradle b u i l d . g r a

    d l e には以下のように書いておく。m u l t i l o a d e r - c o m p i l e r が dependency に入るけれど apk に入らない、という 状態を作るために、 を利用する。 android-apt multiloader/build.gradle multiloader-compiler/build.gradle multiloader-sample/build.gradle a p p l y p l u g i n : ' c o m . a n d r o i d . l i b r a r y ' d e p e n d e n c i e s { c o m p i l e p r o j e c t ( ' : m u l t i l o a d e r - c o m p i l e r ' ) } a p p l y p l u g i n : ' j a v a ' a p p l y p l u g i n : ' c o m . a n d r o i d . a p p l i c a t i o n ' a p p l y p l u g i n : ' a n d r o i d - a p t ' d e p e n d e n c i e s { a p t p r o j e c t ( ' : m u l t i l o a d e r - c o m p i l e r ' ) c o m p i l e p r o j e c t ( ' : m u l t i l o a d e r ' ) }
  7. Processor の実装 文字列連結... b u i l d e r

    . a p p e n d ( " / / G e n e r a t e d c o d e f r o m M u l t i L o a d e r . D o n o t m o d i f y ! \ n " ) ; b u i l d e r . a p p e n d ( " p a c k a g e " ) . a p p e n d ( c l a s s P a c k a g e ) . a p p e n d ( " ; \ n \ n " ) ; b u i l d e r . a p p e n d ( " p u b l i c c l a s s " ) . a p p e n d ( c l a s s N a m e ) . a p p e n d ( " i m p l e m e n t s L o a d e r M a n a g e r . L o a d e b u i l d e r . a p p e n d ( " p r i v a t e " + e n c l o s i n g C l a s s N a m e + " m A c t i v i t y ; \ n " ) ; StringBuilder じゃなくてストリームでも書けます プログラム構造を解析して、いろいろチェックもできます