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