Completed
Pull Request — develop (#236)
by Xaver
47s
created

version.js ➔ ... ➔ Version.compareStrings   C

Complexity

Conditions 15
Paths 14

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 15
c 1
b 0
f 0
nc 14
dl 0
loc 25
rs 5.0504
nop 2

How to fix   Complexity   

Complexity

Complex classes like version.js ➔ ... ➔ Version.compareStrings often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
define(function () {
2
  'use strict';
3
4
  /*
5
    reimplate after node-deb-version-compare under MIT
6
    (https://github.com/sdumetz/node-deb-version-compare)
7
  */
8
9
  function Version(v) {
10
    var version = /^[a-zA-Z]?([0-9]*(?=:))?:(.*)/.exec(v);
11
    this.epoch = (version) ? version[1] : 0;
12
    version = (version && version[2]) ? version[2] : v;
13
    version = version.split('-');
14
    this.debian = (version.length > 1) ? version.pop() : '';
15
    this.upstream = version.join('-');
16
  }
17
18
  Version.prototype.compare = function (b) {
19
    if ((this.epoch > 0 || b.epoch > 0) && Math.sign(this.epoch - b.epoch) !== 0) {
20
      return Math.sign(this.epoch - b.epoch);
21
    }
22
    if (this.compareStrings(this.upstream, b.upstream) !== 0) {
23
      return this.compareStrings(this.upstream, b.upstream);
24
    }
25
    return this.compareStrings(this.debian, b.debian);
26
  };
27
28
  Version.prototype.charCode = function (c) { // the lower the charcode the lower the version.
29
    // if (c === '~') {return 0;} // tilde sort before anything
30
    // else
31
    if (/[a-zA-Z]/.test(c)) {
32
      return c.charCodeAt(0) - 'A'.charCodeAt(0) + 1;
33
    } else if (/[.:+-:]/.test(c)) {
34
      return c.charCodeAt(0) + 'z'.charCodeAt(0) + 1;
35
    } // charcodes are 46..58
36
    return 0;
37
  };
38
39
  // find index of "val" in "ar".
40
  Version.prototype.findIndex = function (ar, fn) {
41
    for (var i = 0; i < ar.length; i++) {
42
      if (fn(ar[i], i)) {
43
        return i;
44
      }
45
    }
46
    return -1;
47
  };
48
49
  Version.prototype.compareChunk = function (a, b) {
50
    var ca = a.split('');
51
    var cb = b.split('');
52
    var diff = this.findIndex(ca, function (c, index) {
53
      if (cb[index] && c === cb[index]) {
54
        return false;
55
      }
56
      return true;
57
    });
58
    if (diff === -1) {
59
      if (cb.length > ca.length) {
60
        if (cb[ca.length] === '~') {
61
          return 1;
62
        }
63
        return -1;
64
      }
65
      return 0; // no diff found and same length
66
    } else if (!cb[diff]) {
67
      return (ca[diff] === '~') ? -1 : 1;
68
    }
69
    return (this.charCode(ca[diff]) > this.charCode(cb[diff])) ? 1 : -1;
70
  };
71
72
  Version.prototype.compareStrings = function (a, b) {
73
    if (a === b) {
74
      return 0;
75
    }
76
    var parseA = /([^0-9]+|[0-9]+)/g;
77
    var parseB = /([^0-9]+|[0-9]+)/g;
78
    var ra = parseA.exec(a);
79
    var rb = parseB.exec(b);
80
    while (ra !== null && rb !== null) {
81
      if ((isNaN(ra[1]) || isNaN(rb[1])) && ra[1] !== rb[1]) { // a or b is not a number and they're not equal. Note : "" IS a number so both null is impossible
82
        return this.compareChunk(ra[1], rb[1]);
83
      } // both are numbers
84
      if (ra[1] !== rb[1]) {
85
        return (parseInt(ra[1], 10) > parseInt(rb[1], 10)) ? 1 : -1;
86
      }
87
      ra = parseA.exec(a);
88
      rb = parseB.exec(b);
89
    }
90
    if (!ra && rb) { // rb doesn't get exec-ed when ra == null
91
      return (parseB.exec(b)[1].split('')[0] === '~') ? 1 : -1;
92
    } else if (ra && !rb) {
93
      return (ra[1].split('')[0] === '~') ? -1 : 1;
94
    }
95
    return 0;
96
  };
97
  return function compare(a, b) {
98
    var va = new Version(a[0]);
99
    var vb = new Version(b[0]);
100
    return vb.compare(va);
101
  };
102
});
103