Global Metrics
path: .metrics.nargs.sum
old: 0.0
new: 33.0
path: .metrics.nargs.average
old: null
new: 1.65
path: .metrics.mi.mi_visual_studio
old: 42.09570801977544
new: 15.143763880818527
path: .metrics.mi.mi_sei
old: 73.84669056034508
new: -13.494321778142968
path: .metrics.mi.mi_original
old: 71.98366071381601
new: 25.895836236199685
path: .metrics.cognitive.average
old: null
new: 0.7
path: .metrics.cognitive.sum
old: 0.0
new: 14.0
path: .metrics.nom.total
old: 0.0
new: 20.0
path: .metrics.nom.functions
old: 0.0
new: 20.0
path: .metrics.loc.blank
old: 10.0
new: 46.0
path: .metrics.loc.sloc
old: 63.0
new: 251.0
path: .metrics.loc.lloc
old: 0.0
new: 51.0
path: .metrics.loc.cloc
old: 34.0
new: 19.0
path: .metrics.loc.ploc
old: 19.0
new: 186.0
path: .metrics.nexits.sum
old: 0.0
new: 7.0
path: .metrics.nexits.average
old: null
new: 0.35
path: .metrics.halstead.volume
old: 404.01548851040104
new: 7167.22808333876
path: .metrics.halstead.effort
old: 2168.925254108469
new: 337991.38750902785
path: .metrics.halstead.n2
old: 19.0
new: 95.0
path: .metrics.halstead.length
old: 87.0
new: 1047.0
path: .metrics.halstead.N2
old: 34.0
new: 448.0
path: .metrics.halstead.N1
old: 53.0
new: 599.0
path: .metrics.halstead.estimated_program_length
old: 96.22039775975506
new: 710.5748446891873
path: .metrics.halstead.level
old: 0.18627450980392157
new: 0.021205357142857144
path: .metrics.halstead.vocabulary
old: 25.0
new: 115.0
path: .metrics.halstead.difficulty
old: 5.368421052631579
new: 47.1578947368421
path: .metrics.halstead.bugs
old: 0.0558523951959655
new: 1.6173940257702415
path: .metrics.halstead.purity_ratio
old: 1.1059815834454605
new: 0.6786770245359955
path: .metrics.halstead.time
old: 120.49584745047048
new: 18777.299306057103
path: .metrics.halstead.n1
old: 6.0
new: 20.0
path: .metrics.cyclomatic.average
old: 1.0
new: 1.3666666666666667
path: .metrics.cyclomatic.sum
old: 3.0
new: 41.0
Spaces Data
Minimal test - lines (17, 249)
path: .spaces[0].metrics.nom.total
old: 0.0
new: 20.0
path: .spaces[0].metrics.nom.functions
old: 0.0
new: 20.0
path: .spaces[0].metrics.loc.blank
old: 0.0
new: 43.0
path: .spaces[0].metrics.loc.ploc
old: 6.0
new: 178.0
path: .spaces[0].metrics.loc.lloc
old: 0.0
new: 51.0
path: .spaces[0].metrics.loc.cloc
old: 0.0
new: 12.0
path: .spaces[0].metrics.loc.sloc
old: 6.0
new: 233.0
path: .spaces[0].metrics.cyclomatic.average
old: 1.0
new: 1.3793103448275863
path: .spaces[0].metrics.cyclomatic.sum
old: 1.0
new: 40.0
path: .spaces[0].metrics.cognitive.sum
old: 0.0
new: 14.0
path: .spaces[0].metrics.cognitive.average
old: null
new: 0.7
path: .spaces[0].metrics.halstead.level
old: 0.25925925925925924
new: 0.02036199095022624
path: .spaces[0].metrics.halstead.estimated_program_length
old: 35.161259458730164
new: 670.705340567418
path: .spaces[0].metrics.halstead.time
old: 23.788541045192737
new: 19260.819716706133
path: .spaces[0].metrics.halstead.difficulty
old: 3.857142857142857
new: 49.111111111111114
path: .spaces[0].metrics.halstead.N1
old: 21.0
new: 599.0
path: .spaces[0].metrics.halstead.N2
old: 9.0
new: 442.0
path: .spaces[0].metrics.halstead.n1
old: 6.0
new: 20.0
path: .spaces[0].metrics.halstead.purity_ratio
old: 1.1720419819576722
new: 0.6442894722069338
path: .spaces[0].metrics.halstead.bugs
old: 0.01893675761448613
new: 1.645041756242558
path: .spaces[0].metrics.halstead.n2
old: 7.0
new: 90.0
path: .spaces[0].metrics.halstead.vocabulary
old: 13.0
new: 110.0
path: .spaces[0].metrics.halstead.effort
old: 428.1937388134693
new: 346694.7549007104
path: .spaces[0].metrics.halstead.volume
old: 111.01319154423275
new: 7059.395461779171
path: .spaces[0].metrics.halstead.length
old: 30.0
new: 1041.0
path: .spaces[0].metrics.nexits.average
old: null
new: 0.35
path: .spaces[0].metrics.nexits.sum
old: 0.0
new: 7.0
path: .spaces[0].metrics.mi.mi_original
old: 117.25332160614748
new: 27.41018062171125
path: .spaces[0].metrics.mi.mi_sei
old: 93.56175347633943
new: -14.86466996308993
path: .spaces[0].metrics.mi.mi_visual_studio
old: 68.56919392172367
new: 16.029345392813596
path: .spaces[0].metrics.nargs.sum
old: 0.0
new: 33.0
path: .spaces[0].metrics.nargs.average
old: null
new: 1.65
Code
namespace mozilla {
namespace jni {
namespace detail {
// Helper class to convert an arbitrary type to a jvalue, e.g. Value(123).val.
struct Value {
explicit Value(jboolean z) { val.z = z; }
explicit Value(jbyte b) { val.b = b; }
explicit Value(jchar c) { val.c = c; }
explicit Value(jshort s) { val.s = s; }
explicit Value(jint i) { val.i = i; }
explicit Value(jlong j) { val.j = j; }
explicit Value(jfloat f) { val.f = f; }
explicit Value(jdouble d) { val.d = d; }
explicit Value(jobject l) { val.l = l; }
jvalue val;
};
} // namespace detail
using namespace detail;
// Base class for Method<>, Field<>, and Constructor<>.
class Accessor {
static void GetNsresult(JNIEnv* env, nsresult* rv) {
if (env->ExceptionCheck()) {
#ifdef MOZ_CHECK_JNI
env->ExceptionDescribe();
#endif
env->ExceptionClear();
*rv = NS_ERROR_FAILURE;
} else {
*rv = NS_OK;
}
}
protected:
// Called after making a JNIEnv call.
template
static void EndAccess(const typename Traits::Owner::Context& ctx,
nsresult* rv) {
if (Traits::exceptionMode == ExceptionMode::ABORT) {
MOZ_CATCH_JNI_EXCEPTION(ctx.Env());
} else if (Traits::exceptionMode == ExceptionMode::NSRESULT) {
GetNsresult(ctx.Env(), rv);
}
}
};
// Member<> is used to call a JNI method given a traits class.
template
class Method : public Accessor {
typedef Accessor Base;
typedef typename Traits::Owner::Context Context;
protected:
static jmethodID sID;
static void BeginAccess(const Context& ctx) {
MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
static_assert(Traits::dispatchTarget == DispatchTarget::CURRENT,
"Dispatching not supported for method call");
if (sID) {
return;
}
if (Traits::isStatic) {
MOZ_ALWAYS_TRUE(
sID = AndroidBridge::GetStaticMethodID(
ctx.Env(), ctx.ClassRef(), Traits::name, Traits::signature));
} else {
MOZ_ALWAYS_TRUE(
sID = AndroidBridge::GetMethodID(ctx.Env(), ctx.ClassRef(),
Traits::name, Traits::signature));
}
}
static void EndAccess(const Context& ctx, nsresult* rv) {
return Base::EndAccess(ctx, rv);
}
public:
template
static ReturnType Call(const Context& ctx, nsresult* rv,
const Args&... args) {
JNIEnv* const env = ctx.Env();
BeginAccess(ctx);
jvalue jargs[] = {Value(TypeAdapter::FromNative(env, args)).val...};
auto result = TypeAdapter::ToNative(
env, Traits::isStatic ? (env->*TypeAdapter::StaticCall)(
ctx.ClassRef(), sID, jargs)
: (env->*TypeAdapter::Call)(
ctx.Get(), sID, jargs));
EndAccess(ctx, rv);
return result;
}
};
// Define sID member.
template
jmethodID Method::sID;
// Specialize void because C++ forbids us from
// using a "void" temporary result variable.
template
class Method : public Method {
typedef Method Base;
typedef typename Traits::Owner::Context Context;
public:
template
static void Call(const Context& ctx, nsresult* rv, const Args&... args) {
JNIEnv* const env = ctx.Env();
Base::BeginAccess(ctx);
jvalue jargs[] = {Value(TypeAdapter::FromNative(env, args)).val...};
if (Traits::isStatic) {
env->CallStaticVoidMethodA(ctx.ClassRef(), Base::sID, jargs);
} else {
env->CallVoidMethodA(ctx.Get(), Base::sID, jargs);
}
Base::EndAccess(ctx, rv);
}
};
// Constructor<> is used to construct a JNI instance given a traits class.
template
class Constructor : protected Method {
typedef typename Traits::Owner::Context Context;
typedef typename Traits::ReturnType ReturnType;
typedef Method Base;
public:
template
static ReturnType Call(const Context& ctx, nsresult* rv,
const Args&... args) {
JNIEnv* const env = ctx.Env();
Base::BeginAccess(ctx);
jvalue jargs[] = {Value(TypeAdapter::FromNative(env, args)).val...};
auto result = TypeAdapter::ToNative(
env, env->NewObjectA(ctx.ClassRef(), Base::sID, jargs));
Base::EndAccess(ctx, rv);
return result;
}
};
// Field<> is used to access a JNI field given a traits class.
template
class Field : public Accessor {
typedef Accessor Base;
typedef typename Traits::Owner::Context Context;
typedef typename Traits::ReturnType GetterType;
typedef typename Traits::SetterType SetterType;
private:
static jfieldID sID;
static void BeginAccess(const Context& ctx) {
MOZ_ASSERT_JNI_THREAD(Traits::callingThread);
static_assert(Traits::dispatchTarget == DispatchTarget::CURRENT,
"Dispatching not supported for field access");
if (sID) {
return;
}
if (Traits::isStatic) {
MOZ_ALWAYS_TRUE(
sID = AndroidBridge::GetStaticFieldID(
ctx.Env(), ctx.ClassRef(), Traits::name, Traits::signature));
} else {
MOZ_ALWAYS_TRUE(sID = AndroidBridge::GetFieldID(ctx.Env(), ctx.ClassRef(),
Traits::name,
Traits::signature));
}
}
static void EndAccess(const Context& ctx, nsresult* rv) {
return Base::EndAccess(ctx, rv);
}
public:
static GetterType Get(const Context& ctx, nsresult* rv) {
JNIEnv* const env = ctx.Env();
BeginAccess(ctx);
auto result = TypeAdapter::ToNative(
env, Traits::isStatic
?
(env->*TypeAdapter::StaticGet)(ctx.ClassRef(), sID)
:
(env->*TypeAdapter::Get)(ctx.Get(), sID));
EndAccess(ctx, rv);
return result;
}
static void Set(const Context& ctx, nsresult* rv, SetterType val) {
JNIEnv* const env = ctx.Env();
BeginAccess(ctx);
if (Traits::isStatic) {
(env->*TypeAdapter::StaticSet)(
ctx.ClassRef(), sID, TypeAdapter::FromNative(env, val));
} else {
(env->*TypeAdapter::Set)(
ctx.Get(), sID, TypeAdapter::FromNative(env, val));
}
EndAccess(ctx, rv);
}
};
// Define sID member.
template
jfieldID Field::sID;
} // namespace jni
} // namespace mozilla