# Global Metrics

path: .metrics.halstead.N2
old: 186.0
new: 290.0
path: .metrics.halstead.estimated_program_length
old: 316.1839163704497
new: 746.3477154631084
path: .metrics.halstead.time
old: 3693.016598721668
new: 9945.521983479792
path: .metrics.halstead.bugs
old: 0.5469923532661695
new: 1.0587956210253442
path: .metrics.halstead.n1
old: 13.0
new: 26.0
path: .metrics.halstead.difficulty
old: 25.1875
new: 39.68421052631579
path: .metrics.halstead.length
old: 445.0
new: 652.0
path: .metrics.halstead.level
old: 0.03970223325062035
new: 0.02519893899204244
path: .metrics.halstead.volume
old: 2639.1781152154845
new: 4511.098830703036
path: .metrics.halstead.N1
old: 259.0
new: 362.0
path: .metrics.halstead.effort
old: 66474.29877699002
new: 179019.39570263625
path: .metrics.halstead.n2
old: 48.0
new: 95.0
path: .metrics.halstead.purity_ratio
old: 0.7105256547650555
new: 1.1447050850661171
path: .metrics.halstead.vocabulary
old: 61.0
new: 121.0
path: .metrics.loc.lloc
old: 5.0
new: 56.0
path: .metrics.loc.sloc
old: 158.0
new: 207.0
path: .metrics.loc.blank
old: 27.0
new: 37.0
path: .metrics.loc.ploc
old: 104.0
new: 134.0
path: .metrics.loc.cloc
old: 27.0
new: 36.0
path: .metrics.nargs.sum
old: 6.0
new: 18.0
path: .metrics.nargs.average
old: 0.5
new: 1.5
path: .metrics.cyclomatic.average
old: 1.0
new: 2.0625
path: .metrics.cyclomatic.sum
old: 21.0
new: 33.0
path: .metrics.mi.mi_original
old: 43.18920176104744
new: 33.26561610994288
path: .metrics.mi.mi_visual_studio
old: 25.256843135115464
new: 19.45357667248122
path: .metrics.mi.mi_sei
old: 18.622475304416284
new: 5.753531510842887
path: .metrics.cognitive.average
old: 0.0
new: 0.75
path: .metrics.cognitive.sum
old: 0.0
new: 9.0
path: .metrics.nexits.sum
old: 5.0
new: 11.0
path: .metrics.nexits.average
old: 0.4166666666666667
new: 0.9166666666666666

# Spaces Data

## Minimal test - lines (33, 53)

path: .spaces[0].spaces[0].metrics.mi.mi_sei
old: 18.472850423126204
new: 53.62150385269314
path: .spaces[0].spaces[0].metrics.mi.mi_original
old: 45.38810238831371
new: 89.42769789171422
path: .spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 26.54274993468638
new: 52.29689935187966
path: .spaces[0].spaces[0].metrics.loc.lloc
old: 5.0
new: 7.0
path: .spaces[0].spaces[0].metrics.loc.blank
old: 26.0
new: 3.0
path: .spaces[0].spaces[0].metrics.loc.ploc
old: 98.0
new: 18.0
path: .spaces[0].spaces[0].metrics.loc.sloc
old: 143.0
new: 21.0
path: .spaces[0].spaces[0].metrics.loc.cloc
old: 19.0
new: 0.0
path: .spaces[0].spaces[0].metrics.nexits.average
old: 0.4166666666666667
new: 3.0
path: .spaces[0].spaces[0].metrics.nexits.sum
old: 5.0
new: 3.0
path: .spaces[0].spaces[0].metrics.cyclomatic.sum
old: 19.0
new: 3.0
path: .spaces[0].spaces[0].metrics.cyclomatic.average
old: 1.0
new: 3.0
path: .spaces[0].spaces[0].metrics.cognitive.average
old: 0.0
new: 2.0
path: .spaces[0].spaces[0].metrics.cognitive.sum
old: 0.0
new: 2.0
path: .spaces[0].spaces[0].metrics.nargs.sum
old: 6.0
new: 3.0
path: .spaces[0].spaces[0].metrics.nargs.average
old: 0.5
new: 3.0
path: .spaces[0].spaces[0].metrics.halstead.N2
old: 182.0
new: 34.0
path: .spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 0.67099796743334
new: 1.6389880198771285
path: .spaces[0].spaces[0].metrics.halstead.difficulty
old: 26.288888888888888
new: 13.421052631578949
path: .spaces[0].spaces[0].metrics.halstead.length
old: 440.0
new: 85.0
path: .spaces[0].spaces[0].metrics.halstead.volume
old: 2577.5116378561315
new: 432.4343415062788
path: .spaces[0].spaces[0].metrics.halstead.effort
old: 67759.91705741786
new: 5803.724057057952
path: .spaces[0].spaces[0].metrics.halstead.time
old: 3764.439836523214
new: 322.42911428099734
path: .spaces[0].spaces[0].metrics.halstead.N1
old: 258.0
new: 51.0
path: .spaces[0].spaces[0].metrics.halstead.bugs
old: 0.5540223976157168
new: 0.10765063158981984
path: .spaces[0].spaces[0].metrics.halstead.n1
old: 13.0
new: 15.0
path: .spaces[0].spaces[0].metrics.halstead.vocabulary
old: 58.0
new: 34.0
path: .spaces[0].spaces[0].metrics.halstead.level
old: 0.03803888419273035
new: 0.07450980392156863
path: .spaces[0].spaces[0].metrics.halstead.n2
old: 45.0
new: 19.0
path: .spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 295.2391056706696
new: 139.3139816895559
path: .spaces[0].spaces[0].metrics.nom.functions
old: 12.0
new: 1.0
path: .spaces[0].spaces[0].metrics.nom.total
old: 12.0
new: 1.0

### Code

    static int32_t GetPathFromFd(int32_t aFd, char* aBuf, size_t aBufSize) {
    #ifdef XP_MACOSX
      NS_ASSERTION(aBufSize >= MAXPATHLEN,
                   "aBufSize should be a least MAXPATHLEN long");

      return fcntl(aFd, F_GETPATH, aBuf);
    #else
      char procPath[32];
      if (PR_snprintf(procPath, sizeof(procPath), "/proc/self/fd/%i", aFd) ==
          (PRUint32)-1) {
        return -1;
      }

      int32_t ret = readlink(procPath, aBuf, aBufSize - 1);
      if (ret > -1) {
        aBuf[ret] = '\0';
      }

      return ret;
    #endif
    }

## Minimal test - lines (23, 132)

path: .spaces[0].metrics.loc.lloc
old: 5.0
new: 24.0
path: .spaces[0].metrics.loc.ploc
old: 100.0
new: 77.0
path: .spaces[0].metrics.loc.cloc
old: 20.0
new: 11.0
path: .spaces[0].metrics.loc.sloc
old: 145.0
new: 110.0
path: .spaces[0].metrics.loc.blank
old: 25.0
new: 22.0
path: .spaces[0].metrics.nargs.sum
old: 6.0
new: 18.0
path: .spaces[0].metrics.nargs.average
old: 0.5
new: 1.8
path: .spaces[0].metrics.nexits.average
old: 0.4166666666666667
new: 0.9
path: .spaces[0].metrics.nexits.sum
old: 5.0
new: 9.0
path: .spaces[0].metrics.nom.total
old: 12.0
new: 10.0
path: .spaces[0].metrics.nom.functions
old: 12.0
new: 10.0
path: .spaces[0].metrics.mi.mi_original
old: 44.887669958624855
new: 49.795021505548235
path: .spaces[0].metrics.mi.mi_sei
old: 18.30143787298541
new: 21.395908323821786
path: .spaces[0].metrics.mi.mi_visual_studio
old: 26.25009939100869
new: 29.11989561727967
path: .spaces[0].metrics.cyclomatic.average
old: 1.0
new: 1.4166666666666667
path: .spaces[0].metrics.cyclomatic.sum
old: 20.0
new: 17.0
path: .spaces[0].metrics.cognitive.sum
old: 0.0
new: 5.0
path: .spaces[0].metrics.cognitive.average
old: 0.0
new: 0.5
path: .spaces[0].metrics.halstead.effort
old: 67235.92449977026
new: 77706.21435976328
path: .spaces[0].metrics.halstead.level
old: 0.03867171080285834
new: 0.035162746495604656
path: .spaces[0].metrics.halstead.purity_ratio
old: 0.683686801616418
new: 1.36121128996583
path: .spaces[0].metrics.halstead.time
old: 3735.329138876126
new: 4317.011908875738
path: .spaces[0].metrics.halstead.volume
old: 2600.1282278179337
new: 2732.3639166654707
path: .spaces[0].metrics.halstead.N1
old: 259.0
new: 231.0
path: .spaces[0].metrics.halstead.estimated_program_length
old: 302.1895663144568
new: 563.5414740458536
path: .spaces[0].metrics.halstead.n2
old: 46.0
new: 74.0
path: .spaces[0].metrics.halstead.vocabulary
old: 59.0
new: 97.0
path: .spaces[0].metrics.halstead.length
old: 442.0
new: 414.0
path: .spaces[0].metrics.halstead.bugs
old: 0.5511625056702443
new: 0.6069914585407531
path: .spaces[0].metrics.halstead.n1
old: 13.0
new: 23.0
path: .spaces[0].metrics.halstead.difficulty
old: 25.85869565217391
new: 28.43918918918919

### Code

    namespace {

    /* Original IO methods */
    PRCloseFN sCloseFn = nullptr;
    PRReadFN sReadFn = nullptr;
    PRWriteFN sWriteFn = nullptr;
    PRFsyncFN sFSyncFn = nullptr;
    PRFileInfoFN sFileInfoFn = nullptr;
    PRFileInfo64FN sFileInfo64Fn = nullptr;

    static int32_t GetPathFromFd(int32_t aFd, char* aBuf, size_t aBufSize) {
    #ifdef XP_MACOSX
      NS_ASSERTION(aBufSize >= MAXPATHLEN,
                   "aBufSize should be a least MAXPATHLEN long");

      return fcntl(aFd, F_GETPATH, aBuf);
    #else
      char procPath[32];
      if (PR_snprintf(procPath, sizeof(procPath), "/proc/self/fd/%i", aFd) ==
          (PRUint32)-1) {
        return -1;
      }

      int32_t ret = readlink(procPath, aBuf, aBufSize - 1);
      if (ret > -1) {
        aBuf[ret] = '\0';
      }

      return ret;
    #endif
    }

    /**
     * RAII class for timing the duration of an NSPR I/O call and reporting the
     * result to the mozilla::IOInterposeObserver API.
     */
    class NSPRIOAutoObservation : public mozilla::IOInterposeObserver::Observation {
     public:
      explicit NSPRIOAutoObservation(mozilla::IOInterposeObserver::Operation aOp,
                                     PRFileDesc* aFd)
          : mozilla::IOInterposeObserver::Observation(aOp, "NSPRIOInterposer") {
        char filename[MAXPATHLEN];
        if (mShouldReport && aFd &&
            GetPathFromFd(PR_FileDesc2NativeHandle(aFd), filename,
                          sizeof(filename)) != -1) {
          CopyUTF8toUTF16(mozilla::MakeStringSpan(filename), mFilename);
        } else {
          mFilename.Truncate();
        }
      }

      void Filename(nsAString& aFilename) override { aFilename = mFilename; }

      ~NSPRIOAutoObservation() override { Report(); }

     private:
      nsString mFilename;
    };

    PRStatus PR_CALLBACK interposedClose(PRFileDesc* aFd) {
      // If we don't have a valid original function pointer something is very wrong.
      NS_ASSERTION(sCloseFn, "NSPR IO Interposing: sCloseFn is NULL");

      NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpClose, aFd);
      return sCloseFn(aFd);
    }

    int32_t PR_CALLBACK interposedRead(PRFileDesc* aFd, void* aBuf, int32_t aAmt) {
      // If we don't have a valid original function pointer something is very wrong.
      NS_ASSERTION(sReadFn, "NSPR IO Interposing: sReadFn is NULL");

      NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpRead, aFd);
      return sReadFn(aFd, aBuf, aAmt);
    }

    int32_t PR_CALLBACK interposedWrite(PRFileDesc* aFd, const void* aBuf,
                                        int32_t aAmt) {
      // If we don't have a valid original function pointer something is very wrong.
      NS_ASSERTION(sWriteFn, "NSPR IO Interposing: sWriteFn is NULL");

      NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpWrite, aFd);
      return sWriteFn(aFd, aBuf, aAmt);
    }

    PRStatus PR_CALLBACK interposedFSync(PRFileDesc* aFd) {
      // If we don't have a valid original function pointer something is very wrong.
      NS_ASSERTION(sFSyncFn, "NSPR IO Interposing: sFSyncFn is NULL");

      NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpFSync, aFd);
      return sFSyncFn(aFd);
    }

    PRStatus PR_CALLBACK interposedFileInfo(PRFileDesc* aFd, PRFileInfo* aInfo) {
      // If we don't have a valid original function pointer something is very wrong.
      NS_ASSERTION(sFileInfoFn, "NSPR IO Interposing: sFileInfoFn is NULL");

      NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpStat, aFd);
      return sFileInfoFn(aFd, aInfo);
    }

    PRStatus PR_CALLBACK interposedFileInfo64(PRFileDesc* aFd,
                                              PRFileInfo64* aInfo) {
      // If we don't have a valid original function pointer something is very wrong.
      NS_ASSERTION(sFileInfo64Fn, "NSPR IO Interposing: sFileInfo64Fn is NULL");

      NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpStat, aFd);
      return sFileInfo64Fn(aFd, aInfo);
    }

    }  // namespace