inline funの効果を検証する

汎用ロガーを作ったが、リリース時にはバイナリから消え去ってほしいと思い、[Inline Functions](https://kotlinlang.org/docs/reference/inline-functions.html)を使ってみた。

実際には、そういった運用をするならProguardで消せばいいと思う。

Inline Functions
---
`inline fun`を呼ぶとバイナリ上に組み込まれるようになる。C言語とかのマクロみたいな感じで使えるはず。

対象
---
```kotlin:Logger.kt
class Logger(val tag: String) {
    inline fun println(priority: Int, msgCreator: () -> String, e: Throwable? = null) {
        if (BuildConfig.DEBUG) {
            // BuildConfig.DEBUGはconst扱いなので、inlineであればリリース時にはクラスファイルからも消えるはず
            val msg = msgCreator() + (e?.let { "\n" + Log.getStackTraceString(it) } ?: "")
            Log.println(priority, tag, msg)
        }
    }

    inline fun v(msgCreator: () -> String) = println(Log.VERBOSE, msgCreator)
    inline fun d(msgCreator: () -> String) = println(Log.DEBUG, msgCreator)
    inline fun i(msgCreator: () -> String) = println(Log.INFO, msgCreator)
    inline fun w(msgCreator: () -> String) = println(Log.WARN, msgCreator)
    inline fun e(msgCreator: () -> String) = println(Log.ERROR, msgCreator)
    inline fun v(msgCreator: () -> String, e: Throwable) = println(Log.VERBOSE, msgCreator, e)
    inline fun d(msgCreator: () -> String, e: Throwable) = println(Log.DEBUG, msgCreator, e)
    inline fun i(msgCreator: () -> String, e: Throwable) = println(Log.INFO, msgCreator, e)
    inline fun w(msgCreator: () -> String, e: Throwable) = println(Log.WARN, msgCreator, e)
    inline fun e(msgCreator: () -> String, e: Throwable) = println(Log.ERROR, msgCreator, e)
}
```

```kotlin:MyApplication.kt
class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Logger("foo").v { "bar" }
    }
}
```

方法
---
出力されたapkをデコンパイルし、jadコマンドで吐かれたコードを比較する。

結果
---
```java:MyApplication.debug.jad
public final class MyApplication extends Application
{

    public MyApplication()
    {
    }

    public void onCreate()
    {
        Object obj;
        Logger logger;
        super.onCreate();
        logger = new Logger("foo");
        if(false)
            throw new UnsupportedOperationException("Super calls with default arguments not supported in this target, function: println");
        obj = (Throwable)null;
        if(!BuildConfig.DEBUG) goto _L2; else goto _L1
_L1:
        StringBuilder stringbuilder = (new StringBuilder()).append((String)"bar");
        if(obj == null) goto _L4; else goto _L3
_L3:
        obj = (Throwable)obj;
        obj = (String)(new StringBuilder()).append("\n").append(Log.getStackTraceString(((Throwable) (obj)))).toString();
        if(obj == null) goto _L4; else goto _L5
_L5:
        obj = stringbuilder.append(obj).toString();
        Log.println(2, logger.getTag(), ((String) (obj)));
_L2:
        return;
_L4:
        obj = "";
        if(true) goto _L5; else goto _L6
_L6:
    }
}
```

```java:MyApplication.release.jad
public final class MyApplication extends Application
{

    public MyApplication()
    {
    }

    public void onCreate()
    {
        super.onCreate();
        new a("foo"); // 注:Logger
        if(false)
        {
            throw new UnsupportedOperationException("Super calls with default arguments not supported in this target, function: println");
        } else
        {
            Throwable throwable = (Throwable)null;
            return;
        }
    }
}
```

という感じで、リリース時にログ内容がごっそり消せた。

`UnsupportedOperationException`はKotlinによるものだと思うが、詳細は把握しきれていない。

ちなみに、`app/build`に出力されるProguard前のバイトコードは大差がなかったので、Proguardによる最適化効果と思われる。