# 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