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();
  }
};