# Global Metrics

path: .metrics.nargs.sum
old: 0.0
new: 8.0
path: .metrics.nargs.average
old: 0.0
new: 2.0
path: .metrics.loc.sloc
old: 55.0
new: 160.0
path: .metrics.loc.blank
old: 9.0
new: 45.0
path: .metrics.loc.cloc
old: 22.0
new: 31.0
path: .metrics.loc.lloc
old: 1.0
new: 14.0
path: .metrics.loc.ploc
old: 24.0
new: 84.0
path: .metrics.mi.mi_visual_studio
old: 43.204718680797264
new: 25.527910118806517
path: .metrics.mi.mi_sei
old: 73.01565941492149
new: 20.317834136035703
path: .metrics.mi.mi_original
old: 73.88006894416333
new: 43.65272630315914
path: .metrics.cyclomatic.average
old: 1.0
new: 1.0714285714285714
path: .metrics.cyclomatic.sum
old: 6.0
new: 15.0
path: .metrics.nexits.sum
old: 0.0
new: 4.0
path: .metrics.nexits.average
old: 0.0
new: 1.0
path: .metrics.nom.total
old: 2.0
new: 4.0
path: .metrics.nom.functions
old: 2.0
new: 4.0
path: .metrics.halstead.estimated_program_length
old: 158.14481635314195
new: 427.763530178114
path: .metrics.halstead.n2
old: 24.0
new: 62.0
path: .metrics.halstead.n1
old: 13.0
new: 15.0
path: .metrics.halstead.effort
old: 3149.114559522701
new: 69568.91139188361
path: .metrics.halstead.length
old: 72.0
new: 483.0
path: .metrics.halstead.volume
old: 375.0806423252844
new: 3026.857899155638
path: .metrics.halstead.N1
old: 41.0
new: 293.0
path: .metrics.halstead.bugs
old: 0.07161506413082837
new: 0.5638395689127442
path: .metrics.halstead.time
old: 174.95080886237227
new: 3864.939521771312
path: .metrics.halstead.N2
old: 31.0
new: 190.0
path: .metrics.halstead.level
old: 0.11910669975186104
new: 0.04350877192982456
path: .metrics.halstead.vocabulary
old: 37.0
new: 77.0
path: .metrics.halstead.purity_ratio
old: 2.196455782682527
new: 0.885638778836675
path: .metrics.halstead.difficulty
old: 8.395833333333334
new: 22.983870967741936

# Spaces Data

## Minimal test - lines (32, 32)

path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.loc.lloc
old: 1.0
new: 0.0
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.nom.functions
old: 1.0
new: 0.0
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.nom.total
old: 1.0
new: 0.0
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.cognitive.average
old: 0.0
new: null
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.nargs.average
old: 0.0
new: null
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.nexits.average
old: 0.0
new: null
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.mi.mi_original
old: 155.7127700178179
new: null
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.mi.mi_sei
old: 149.04700897518126
new: null
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 91.0600994256245
new: null
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.halstead.difficulty
old: 2.0
new: 0.0
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.halstead.time
old: 2.0105263894497885
new: 0.0
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.halstead.bugs
old: 0.003646981838562912
new: 0.0
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.halstead.effort
old: 36.18947501009619
new: 0.0
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.halstead.n2
old: 2.0
new: 1.0
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 1.4285714285714286
new: null
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.halstead.n1
old: 4.0
new: 0.0
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.halstead.volume
old: 18.094737505048094
new: 0.0
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.halstead.N1
old: 5.0
new: 0.0
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.halstead.length
old: 7.0
new: 1.0
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 10.0
new: null
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.halstead.N2
old: 2.0
new: 1.0
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.halstead.level
old: 0.5
new: null
path: .spaces[0].spaces[0].spaces[0].spaces[0].metrics.halstead.vocabulary
old: 6.0
new: 1.0

### Code

    struct TypeAdapter;

## Minimal test - lines (15, 157)

path: .spaces[0].spaces[0].metrics.loc.lloc
old: 1.0
new: 14.0
path: .spaces[0].spaces[0].metrics.loc.cloc
old: 14.0
new: 23.0
path: .spaces[0].spaces[0].metrics.loc.sloc
old: 39.0
new: 143.0
path: .spaces[0].spaces[0].metrics.loc.ploc
old: 17.0
new: 77.0
path: .spaces[0].spaces[0].metrics.loc.blank
old: 8.0
new: 43.0
path: .spaces[0].spaces[0].metrics.mi.mi_sei
old: 80.91214970653282
new: 21.140997587650773
path: .spaces[0].spaces[0].metrics.mi.mi_original
old: 80.52905340728438
new: 46.0343622713289
path: .spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 47.0930136884704
new: 26.920679690835616
path: .spaces[0].spaces[0].metrics.halstead.bugs
old: 0.0664281027508775
new: 0.5671279528670113
path: .spaces[0].spaces[0].metrics.halstead.length
old: 66.0
new: 478.0
path: .spaces[0].spaces[0].metrics.halstead.volume
old: 332.93001187765793
new: 2968.118708770638
path: .spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 134.54427823358145
new: 405.6792988464764
path: .spaces[0].spaces[0].metrics.halstead.N2
old: 26.0
new: 186.0
path: .spaces[0].spaces[0].metrics.halstead.time
old: 156.2921444647894
new: 3898.799998808889
path: .spaces[0].spaces[0].metrics.halstead.difficulty
old: 8.45
new: 23.64406779661017
path: .spaces[0].spaces[0].metrics.halstead.n2
old: 20.0
new: 59.0
path: .spaces[0].spaces[0].metrics.halstead.N1
old: 40.0
new: 292.0
path: .spaces[0].spaces[0].metrics.halstead.effort
old: 2813.258600366209
new: 70178.39997856
path: .spaces[0].spaces[0].metrics.halstead.vocabulary
old: 33.0
new: 74.0
path: .spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 2.0385496702057795
new: 0.8487014620219172
path: .spaces[0].spaces[0].metrics.halstead.n1
old: 13.0
new: 15.0
path: .spaces[0].spaces[0].metrics.halstead.level
old: 0.1183431952662722
new: 0.04229390681003584
path: .spaces[0].spaces[0].metrics.nexits.average
old: 0.0
new: 1.0
path: .spaces[0].spaces[0].metrics.nexits.sum
old: 0.0
new: 4.0
path: .spaces[0].spaces[0].metrics.cyclomatic.average
old: 1.0
new: 1.0833333333333333
path: .spaces[0].spaces[0].metrics.cyclomatic.sum
old: 4.0
new: 13.0
path: .spaces[0].spaces[0].metrics.nom.functions
old: 2.0
new: 4.0
path: .spaces[0].spaces[0].metrics.nom.total
old: 2.0
new: 4.0
path: .spaces[0].spaces[0].metrics.nargs.average
old: 0.0
new: 2.0
path: .spaces[0].spaces[0].metrics.nargs.sum
old: 0.0
new: 8.0

### Code

    namespace jni {
    namespace detail {

    // TypeAdapter specializations are the interfaces between native/C++ types such
    // as int32_t and JNI types such as jint. The template parameter T is the native
    // type, and each TypeAdapter specialization can have the following members:
    //
    //  * Call: JNIEnv member pointer for making a method call that returns T.
    //  * StaticCall: JNIEnv member pointer for making a static call that returns T.
    //  * Get: JNIEnv member pointer for getting a field of type T.
    //  * StaticGet: JNIEnv member pointer for getting a static field of type T.
    //  * Set: JNIEnv member pointer for setting a field of type T.
    //  * StaticGet: JNIEnv member pointer for setting a static field of type T.
    //  * ToNative: static function that converts the JNI type to the native type.
    //  * FromNative: static function that converts the native type to the JNI type.

    template
    struct TypeAdapter;

    // TypeAdapter> applies when jobject is a return value.
    template
    struct TypeAdapter> {
      using JNIType = typename Cls::Ref::JNIType;

      static constexpr auto Call = &JNIEnv::CallObjectMethodA;
      static constexpr auto StaticCall = &JNIEnv::CallStaticObjectMethodA;
      static constexpr auto Get = &JNIEnv::GetObjectField;
      static constexpr auto StaticGet = &JNIEnv::GetStaticObjectField;

      // Declare instance as jobject because JNI methods return
      // jobject even if the return value is really jstring, etc.
      static LocalRef ToNative(JNIEnv* env, jobject instance) {
        return LocalRef::Adopt(env, JNIType(instance));
      }

      static JNIType FromNative(JNIEnv*, LocalRef&& instance) {
        return instance.Forget();
      }
    };

    // clang is picky about function types, including attributes that modify the
    // calling convention, lining up.  GCC appears to be somewhat less so.
    #ifdef __clang__
    #  define MOZ_JNICALL_ABI JNICALL
    #else
    #  define MOZ_JNICALL_ABI
    #endif

    // NDK r18 made jvalue* method parameters const. We detect the change directly
    // instead of using ndk-version.h in order to remain compatible with r15 for
    // now, which doesn't include those headers.
    class CallArgs {
      static const jvalue* test(void (JNIEnv::*)(jobject, jmethodID,
                                                 const jvalue*));
      static jvalue* test(void (JNIEnv::*)(jobject, jmethodID, jvalue*));

     public:
      using JValueType = decltype(test(&JNIEnv::CallVoidMethodA));
    };

    template
    constexpr jobject (JNIEnv::*TypeAdapter>::Call)(
        jobject, jmethodID, CallArgs::JValueType) MOZ_JNICALL_ABI;
    template
    constexpr jobject (JNIEnv::*TypeAdapter>::StaticCall)(
        jclass, jmethodID, CallArgs::JValueType) MOZ_JNICALL_ABI;
    template
    constexpr jobject (JNIEnv::*TypeAdapter>::Get)(jobject, jfieldID);
    template
    constexpr jobject (JNIEnv::*TypeAdapter>::StaticGet)(jclass,
                                                                       jfieldID);

    // TypeAdapter> applies when jobject is a parameter value.
    template
    struct TypeAdapter> {
      using JNIType = typename Ref::JNIType;

      static constexpr auto Set = &JNIEnv::SetObjectField;
      static constexpr auto StaticSet = &JNIEnv::SetStaticObjectField;

      static DependentRef ToNative(JNIEnv* env, JNIType instance) {
        return DependentRef(instance);
      }

      static JNIType FromNative(JNIEnv*, const Ref& instance) {
        return instance.Get();
      }
    };

    template
    constexpr void (JNIEnv::*TypeAdapter>::Set)(jobject, jfieldID,
                                                            jobject);
    template
    constexpr void (JNIEnv::*TypeAdapter>::StaticSet)(jclass, jfieldID,
                                                                  jobject);

    // jstring has its own Param type.
    template <>
    struct TypeAdapter : public TypeAdapter {};

    template
    struct TypeAdapter : public TypeAdapter {};

    #define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName)           \
                                                                                  \
      template <>                                                                 \
      struct TypeAdapter {                                            \
        using JNI##Type = JNIType;                                                \
                                                                                  \
        static constexpr auto Call = &JNIEnv::Call##JNIName##MethodA;             \
        static constexpr auto StaticCall = &JNIEnv::CallStatic##JNIName##MethodA; \
        static constexpr auto Get = &JNIEnv::Get##JNIName##Field;                 \
        static constexpr auto StaticGet = &JNIEnv::GetStatic##JNIName##Field;     \
        static constexpr auto Set = &JNIEnv::Set##JNIName##Field;                 \
        static constexpr auto StaticSet = &JNIEnv::SetStatic##JNIName##Field;     \
        static constexpr auto GetArray = &JNIEnv::Get##JNIName##ArrayRegion;      \
        static constexpr auto SetArray = &JNIEnv::Set##JNIName##ArrayRegion;      \
        static constexpr auto NewArray = &JNIEnv::New##JNIName##Array;            \
                                                                                  \
        static JNIType FromNative(JNIEnv*, NativeType val) {                      \
          return static_cast(val);                                       \
        }                                                                         \
        static NativeType ToNative(JNIEnv*, JNIType val) {                        \
          return static_cast(val);                                    \
        }                                                                         \
      }

    DEFINE_PRIMITIVE_TYPE_ADAPTER(bool, jboolean, Boolean);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(int8_t, jbyte, Byte);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(char16_t, jchar, Char);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(int16_t, jshort, Short);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(int32_t, jint, Int);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(int64_t, jlong, Long);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(float, jfloat, Float);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(double, jdouble, Double);

    #undef DEFINE_PRIMITIVE_TYPE_ADAPTER

    }  // namespace detail

    using namespace detail;

    }  // namespace jni

## Minimal test - lines (14, 158)

path: .spaces[0].metrics.loc.sloc
old: 41.0
new: 145.0
path: .spaces[0].metrics.loc.cloc
old: 15.0
new: 24.0
path: .spaces[0].metrics.loc.ploc
old: 19.0
new: 79.0
path: .spaces[0].metrics.loc.blank
old: 7.0
new: 42.0
path: .spaces[0].metrics.loc.lloc
old: 1.0
new: 14.0
path: .spaces[0].metrics.mi.mi_sei
old: 79.48924548681545
new: 20.895237683700927
path: .spaces[0].metrics.mi.mi_original
old: 79.28944036905776
new: 45.541454800155606
path: .spaces[0].metrics.mi.mi_visual_studio
old: 46.36809378307471
new: 26.632429707693337
path: .spaces[0].metrics.cyclomatic.average
old: 1.0
new: 1.0769230769230769
path: .spaces[0].metrics.cyclomatic.sum
old: 5.0
new: 14.0
path: .spaces[0].metrics.nargs.sum
old: 0.0
new: 8.0
path: .spaces[0].metrics.nargs.average
old: 0.0
new: 2.0
path: .spaces[0].metrics.halstead.level
old: 0.11965811965811964
new: 0.0427807486631016
path: .spaces[0].metrics.halstead.volume
old: 345.9474732050231
new: 2989.8329714380225
path: .spaces[0].metrics.halstead.effort
old: 2891.1324546419787
new: 69887.34570736377
path: .spaces[0].metrics.halstead.N1
old: 41.0
new: 293.0
path: .spaces[0].metrics.halstead.time
old: 160.61846970233216
new: 3882.630317075765
path: .spaces[0].metrics.halstead.vocabulary
old: 34.0
new: 75.0
path: .spaces[0].metrics.halstead.N2
old: 27.0
new: 187.0
path: .spaces[0].metrics.halstead.purity_ratio
old: 2.063887973738061
new: 0.860451655563831
path: .spaces[0].metrics.halstead.n1
old: 13.0
new: 15.0
path: .spaces[0].metrics.halstead.estimated_program_length
old: 140.34438221418816
new: 413.0167946706389
path: .spaces[0].metrics.halstead.bugs
old: 0.06764838057950412
new: 0.565558815536183
path: .spaces[0].metrics.halstead.difficulty
old: 8.357142857142858
new: 23.375
path: .spaces[0].metrics.halstead.n2
old: 21.0
new: 60.0
path: .spaces[0].metrics.halstead.length
old: 68.0
new: 480.0
path: .spaces[0].metrics.nexits.sum
old: 0.0
new: 4.0
path: .spaces[0].metrics.nexits.average
old: 0.0
new: 1.0
path: .spaces[0].metrics.nom.functions
old: 2.0
new: 4.0
path: .spaces[0].metrics.nom.total
old: 2.0
new: 4.0

### Code

    namespace mozilla {
    namespace jni {
    namespace detail {

    // TypeAdapter specializations are the interfaces between native/C++ types such
    // as int32_t and JNI types such as jint. The template parameter T is the native
    // type, and each TypeAdapter specialization can have the following members:
    //
    //  * Call: JNIEnv member pointer for making a method call that returns T.
    //  * StaticCall: JNIEnv member pointer for making a static call that returns T.
    //  * Get: JNIEnv member pointer for getting a field of type T.
    //  * StaticGet: JNIEnv member pointer for getting a static field of type T.
    //  * Set: JNIEnv member pointer for setting a field of type T.
    //  * StaticGet: JNIEnv member pointer for setting a static field of type T.
    //  * ToNative: static function that converts the JNI type to the native type.
    //  * FromNative: static function that converts the native type to the JNI type.

    template
    struct TypeAdapter;

    // TypeAdapter> applies when jobject is a return value.
    template
    struct TypeAdapter> {
      using JNIType = typename Cls::Ref::JNIType;

      static constexpr auto Call = &JNIEnv::CallObjectMethodA;
      static constexpr auto StaticCall = &JNIEnv::CallStaticObjectMethodA;
      static constexpr auto Get = &JNIEnv::GetObjectField;
      static constexpr auto StaticGet = &JNIEnv::GetStaticObjectField;

      // Declare instance as jobject because JNI methods return
      // jobject even if the return value is really jstring, etc.
      static LocalRef ToNative(JNIEnv* env, jobject instance) {
        return LocalRef::Adopt(env, JNIType(instance));
      }

      static JNIType FromNative(JNIEnv*, LocalRef&& instance) {
        return instance.Forget();
      }
    };

    // clang is picky about function types, including attributes that modify the
    // calling convention, lining up.  GCC appears to be somewhat less so.
    #ifdef __clang__
    #  define MOZ_JNICALL_ABI JNICALL
    #else
    #  define MOZ_JNICALL_ABI
    #endif

    // NDK r18 made jvalue* method parameters const. We detect the change directly
    // instead of using ndk-version.h in order to remain compatible with r15 for
    // now, which doesn't include those headers.
    class CallArgs {
      static const jvalue* test(void (JNIEnv::*)(jobject, jmethodID,
                                                 const jvalue*));
      static jvalue* test(void (JNIEnv::*)(jobject, jmethodID, jvalue*));

     public:
      using JValueType = decltype(test(&JNIEnv::CallVoidMethodA));
    };

    template
    constexpr jobject (JNIEnv::*TypeAdapter>::Call)(
        jobject, jmethodID, CallArgs::JValueType) MOZ_JNICALL_ABI;
    template
    constexpr jobject (JNIEnv::*TypeAdapter>::StaticCall)(
        jclass, jmethodID, CallArgs::JValueType) MOZ_JNICALL_ABI;
    template
    constexpr jobject (JNIEnv::*TypeAdapter>::Get)(jobject, jfieldID);
    template
    constexpr jobject (JNIEnv::*TypeAdapter>::StaticGet)(jclass,
                                                                       jfieldID);

    // TypeAdapter> applies when jobject is a parameter value.
    template
    struct TypeAdapter> {
      using JNIType = typename Ref::JNIType;

      static constexpr auto Set = &JNIEnv::SetObjectField;
      static constexpr auto StaticSet = &JNIEnv::SetStaticObjectField;

      static DependentRef ToNative(JNIEnv* env, JNIType instance) {
        return DependentRef(instance);
      }

      static JNIType FromNative(JNIEnv*, const Ref& instance) {
        return instance.Get();
      }
    };

    template
    constexpr void (JNIEnv::*TypeAdapter>::Set)(jobject, jfieldID,
                                                            jobject);
    template
    constexpr void (JNIEnv::*TypeAdapter>::StaticSet)(jclass, jfieldID,
                                                                  jobject);

    // jstring has its own Param type.
    template <>
    struct TypeAdapter : public TypeAdapter {};

    template
    struct TypeAdapter : public TypeAdapter {};

    #define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName)           \
                                                                                  \
      template <>                                                                 \
      struct TypeAdapter {                                            \
        using JNI##Type = JNIType;                                                \
                                                                                  \
        static constexpr auto Call = &JNIEnv::Call##JNIName##MethodA;             \
        static constexpr auto StaticCall = &JNIEnv::CallStatic##JNIName##MethodA; \
        static constexpr auto Get = &JNIEnv::Get##JNIName##Field;                 \
        static constexpr auto StaticGet = &JNIEnv::GetStatic##JNIName##Field;     \
        static constexpr auto Set = &JNIEnv::Set##JNIName##Field;                 \
        static constexpr auto StaticSet = &JNIEnv::SetStatic##JNIName##Field;     \
        static constexpr auto GetArray = &JNIEnv::Get##JNIName##ArrayRegion;      \
        static constexpr auto SetArray = &JNIEnv::Set##JNIName##ArrayRegion;      \
        static constexpr auto NewArray = &JNIEnv::New##JNIName##Array;            \
                                                                                  \
        static JNIType FromNative(JNIEnv*, NativeType val) {                      \
          return static_cast(val);                                       \
        }                                                                         \
        static NativeType ToNative(JNIEnv*, JNIType val) {                        \
          return static_cast(val);                                    \
        }                                                                         \
      }

    DEFINE_PRIMITIVE_TYPE_ADAPTER(bool, jboolean, Boolean);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(int8_t, jbyte, Byte);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(char16_t, jchar, Char);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(int16_t, jshort, Short);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(int32_t, jint, Int);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(int64_t, jlong, Long);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(float, jfloat, Float);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(double, jdouble, Double);

    #undef DEFINE_PRIMITIVE_TYPE_ADAPTER

    }  // namespace detail

    using namespace detail;

    }  // namespace jni
    }  // namespace mozilla

## Minimal test - lines (16, 153)

path: .spaces[0].spaces[0].spaces[0].metrics.cyclomatic.sum
old: 3.0
new: 12.0
path: .spaces[0].spaces[0].spaces[0].metrics.cyclomatic.average
old: 1.0
new: 1.0909090909090908
path: .spaces[0].spaces[0].spaces[0].metrics.nexits.average
old: 0.0
new: 1.0
path: .spaces[0].spaces[0].spaces[0].metrics.nexits.sum
old: 0.0
new: 4.0
path: .spaces[0].spaces[0].spaces[0].metrics.loc.lloc
old: 1.0
new: 14.0
path: .spaces[0].spaces[0].spaces[0].metrics.loc.sloc
old: 23.0
new: 138.0
path: .spaces[0].spaces[0].spaces[0].metrics.loc.cloc
old: 2.0
new: 22.0
path: .spaces[0].spaces[0].spaces[0].metrics.loc.blank
old: 6.0
new: 42.0
path: .spaces[0].spaces[0].spaces[0].metrics.loc.ploc
old: 15.0
new: 74.0
path: .spaces[0].spaces[0].spaces[0].metrics.nom.functions
old: 2.0
new: 4.0
path: .spaces[0].spaces[0].spaces[0].metrics.nom.total
old: 2.0
new: 4.0
path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 52.398605836289185
new: 27.42754219928862
path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_original
old: 89.6016159800545
new: 46.901097160783536
path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_sei
old: 75.92778273878668
new: 22.177839171276627
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.difficulty
old: 8.552631578947368
new: 23.79310344827586
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.time
old: 149.67105263157893
new: 3878.245249477584
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.length
old: 63.0
new: 474.0
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.n2
old: 19.0
new: 58.0
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.volume
old: 315.0
new: 2933.9768409091284
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.bugs
old: 0.06453851338086528
new: 0.5651329048360183
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.effort
old: 2694.078947368421
new: 69808.41449059651
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.N2
old: 25.0
new: 184.0
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 128.8163390912623
new: 398.3662566515269
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 2.0447037950994016
new: 0.8404351406150357
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.level
old: 0.11692307692307692
new: 0.04202898550724638
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.vocabulary
old: 32.0
new: 73.0
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.n1
old: 13.0
new: 15.0
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.N1
old: 38.0
new: 290.0
path: .spaces[0].spaces[0].spaces[0].metrics.nargs.average
old: 0.0
new: 2.0
path: .spaces[0].spaces[0].spaces[0].metrics.nargs.sum
old: 0.0
new: 8.0

### Code

    namespace detail {

    // TypeAdapter specializations are the interfaces between native/C++ types such
    // as int32_t and JNI types such as jint. The template parameter T is the native
    // type, and each TypeAdapter specialization can have the following members:
    //
    //  * Call: JNIEnv member pointer for making a method call that returns T.
    //  * StaticCall: JNIEnv member pointer for making a static call that returns T.
    //  * Get: JNIEnv member pointer for getting a field of type T.
    //  * StaticGet: JNIEnv member pointer for getting a static field of type T.
    //  * Set: JNIEnv member pointer for setting a field of type T.
    //  * StaticGet: JNIEnv member pointer for setting a static field of type T.
    //  * ToNative: static function that converts the JNI type to the native type.
    //  * FromNative: static function that converts the native type to the JNI type.

    template
    struct TypeAdapter;

    // TypeAdapter> applies when jobject is a return value.
    template
    struct TypeAdapter> {
      using JNIType = typename Cls::Ref::JNIType;

      static constexpr auto Call = &JNIEnv::CallObjectMethodA;
      static constexpr auto StaticCall = &JNIEnv::CallStaticObjectMethodA;
      static constexpr auto Get = &JNIEnv::GetObjectField;
      static constexpr auto StaticGet = &JNIEnv::GetStaticObjectField;

      // Declare instance as jobject because JNI methods return
      // jobject even if the return value is really jstring, etc.
      static LocalRef ToNative(JNIEnv* env, jobject instance) {
        return LocalRef::Adopt(env, JNIType(instance));
      }

      static JNIType FromNative(JNIEnv*, LocalRef&& instance) {
        return instance.Forget();
      }
    };

    // clang is picky about function types, including attributes that modify the
    // calling convention, lining up.  GCC appears to be somewhat less so.
    #ifdef __clang__
    #  define MOZ_JNICALL_ABI JNICALL
    #else
    #  define MOZ_JNICALL_ABI
    #endif

    // NDK r18 made jvalue* method parameters const. We detect the change directly
    // instead of using ndk-version.h in order to remain compatible with r15 for
    // now, which doesn't include those headers.
    class CallArgs {
      static const jvalue* test(void (JNIEnv::*)(jobject, jmethodID,
                                                 const jvalue*));
      static jvalue* test(void (JNIEnv::*)(jobject, jmethodID, jvalue*));

     public:
      using JValueType = decltype(test(&JNIEnv::CallVoidMethodA));
    };

    template
    constexpr jobject (JNIEnv::*TypeAdapter>::Call)(
        jobject, jmethodID, CallArgs::JValueType) MOZ_JNICALL_ABI;
    template
    constexpr jobject (JNIEnv::*TypeAdapter>::StaticCall)(
        jclass, jmethodID, CallArgs::JValueType) MOZ_JNICALL_ABI;
    template
    constexpr jobject (JNIEnv::*TypeAdapter>::Get)(jobject, jfieldID);
    template
    constexpr jobject (JNIEnv::*TypeAdapter>::StaticGet)(jclass,
                                                                       jfieldID);

    // TypeAdapter> applies when jobject is a parameter value.
    template
    struct TypeAdapter> {
      using JNIType = typename Ref::JNIType;

      static constexpr auto Set = &JNIEnv::SetObjectField;
      static constexpr auto StaticSet = &JNIEnv::SetStaticObjectField;

      static DependentRef ToNative(JNIEnv* env, JNIType instance) {
        return DependentRef(instance);
      }

      static JNIType FromNative(JNIEnv*, const Ref& instance) {
        return instance.Get();
      }
    };

    template
    constexpr void (JNIEnv::*TypeAdapter>::Set)(jobject, jfieldID,
                                                            jobject);
    template
    constexpr void (JNIEnv::*TypeAdapter>::StaticSet)(jclass, jfieldID,
                                                                  jobject);

    // jstring has its own Param type.
    template <>
    struct TypeAdapter : public TypeAdapter {};

    template
    struct TypeAdapter : public TypeAdapter {};

    #define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName)           \
                                                                                  \
      template <>                                                                 \
      struct TypeAdapter {                                            \
        using JNI##Type = JNIType;                                                \
                                                                                  \
        static constexpr auto Call = &JNIEnv::Call##JNIName##MethodA;             \
        static constexpr auto StaticCall = &JNIEnv::CallStatic##JNIName##MethodA; \
        static constexpr auto Get = &JNIEnv::Get##JNIName##Field;                 \
        static constexpr auto StaticGet = &JNIEnv::GetStatic##JNIName##Field;     \
        static constexpr auto Set = &JNIEnv::Set##JNIName##Field;                 \
        static constexpr auto StaticSet = &JNIEnv::SetStatic##JNIName##Field;     \
        static constexpr auto GetArray = &JNIEnv::Get##JNIName##ArrayRegion;      \
        static constexpr auto SetArray = &JNIEnv::Set##JNIName##ArrayRegion;      \
        static constexpr auto NewArray = &JNIEnv::New##JNIName##Array;            \
                                                                                  \
        static JNIType FromNative(JNIEnv*, NativeType val) {                      \
          return static_cast(val);                                       \
        }                                                                         \
        static NativeType ToNative(JNIEnv*, JNIType val) {                        \
          return static_cast(val);                                    \
        }                                                                         \
      }

    DEFINE_PRIMITIVE_TYPE_ADAPTER(bool, jboolean, Boolean);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(int8_t, jbyte, Byte);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(char16_t, jchar, Char);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(int16_t, jshort, Short);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(int32_t, jint, Int);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(int64_t, jlong, Long);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(float, jfloat, Float);
    DEFINE_PRIMITIVE_TYPE_ADAPTER(double, jdouble, Double);

    #undef DEFINE_PRIMITIVE_TYPE_ADAPTER

    }  // namespace detail

## Minimal test - lines (36, 53)

path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.nom.total
old: 1.0
new: 2.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.nom.functions
old: 1.0
new: 2.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.nexits.sum
old: 0.0
new: 2.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.nexits.average
old: 0.0
new: 1.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.halstead.length
old: 6.0
new: 84.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.halstead.purity_ratio
old: 1.9349400790728015
new: 1.6017175980188267
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.halstead.vocabulary
old: 6.0
new: 33.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.halstead.bugs
old: 0.00381864321284214
new: 0.09329229892206872
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.halstead.estimated_program_length
old: 11.60964047443681
new: 134.54427823358145
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.halstead.n2
old: 1.0
new: 20.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.halstead.effort
old: 38.77443751081734
new: 4682.206621588516
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.halstead.volume
old: 15.509775004326936
new: 423.72910602611006
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.halstead.difficulty
old: 2.5
new: 11.05
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.halstead.time
old: 2.1541354172676304
new: 260.1225900882509
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.halstead.N1
old: 5.0
new: 50.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.halstead.N2
old: 1.0
new: 34.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.halstead.level
old: 0.4
new: 0.09049773755656108
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.halstead.n1
old: 5.0
new: 13.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.loc.blank
old: 0.0
new: 3.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.loc.sloc
old: 1.0
new: 18.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.loc.lloc
old: 0.0
new: 2.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.loc.ploc
old: 1.0
new: 13.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.loc.cloc
old: 0.0
new: 2.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.nargs.average
old: 0.0
new: 2.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.nargs.sum
old: 0.0
new: 4.0
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.mi.mi_sei
old: 150.2034495661308
new: 81.83436542855061
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.mi.mi_visual_studio
old: 91.5288617268536
new: 53.684612222935066
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.mi.mi_original
old: 156.51435355291963
new: 91.80068690121897
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.cyclomatic.average
old: 1.0
new: 1.3333333333333333
path: .spaces[0].spaces[0].spaces[0].spaces[1].metrics.cyclomatic.sum
old: 1.0
new: 4.0

### Code

    struct TypeAdapter> {
      using JNIType = typename Cls::Ref::JNIType;

      static constexpr auto Call = &JNIEnv::CallObjectMethodA;
      static constexpr auto StaticCall = &JNIEnv::CallStaticObjectMethodA;
      static constexpr auto Get = &JNIEnv::GetObjectField;
      static constexpr auto StaticGet = &JNIEnv::GetStaticObjectField;

      // Declare instance as jobject because JNI methods return
      // jobject even if the return value is really jstring, etc.
      static LocalRef ToNative(JNIEnv* env, jobject instance) {
        return LocalRef::Adopt(env, JNIType(instance));
      }

      static JNIType FromNative(JNIEnv*, LocalRef&& instance) {
        return instance.Forget();
      }
    };