• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Camelcade / Perl5-IDEA / #525521660

24 Aug 2025 01:28PM UTC coverage: 75.89% (-6.3%) from 82.227%
#525521660

push

github

hurricup
Migrated coverage reporting to https://github.com/nbaztec/coveralls-jacoco-gradle-plugin

See: https://github.com/kt3k/coveralls-gradle-plugin/issues/119

14751 of 22639 branches covered (65.16%)

Branch coverage included in aggregate %.

31091 of 37767 relevant lines covered (82.32%)

0.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.16
/plugin/common/src/main/java/com/perl5/lang/perl/internals/PerlVersion.java
1
/*
2
 * Copyright 2015-2025 Alexandr Evstigneev
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 * http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package com.perl5.lang.perl.internals;
18

19
import com.intellij.openapi.diagnostic.Logger;
20
import com.intellij.openapi.util.NlsSafe;
21
import com.intellij.openapi.util.text.StringUtil;
22
import com.intellij.util.xmlb.annotations.Tag;
23
import com.perl5.PerlBundle;
24
import com.perl5.lang.perl.util.PerlUtil;
25
import org.apache.groovy.util.Maps;
26
import org.jetbrains.annotations.Nls;
27
import org.jetbrains.annotations.NotNull;
28

29
import java.util.ArrayList;
30
import java.util.Collections;
31
import java.util.List;
32
import java.util.Map;
33
import java.util.function.Predicate;
34
import java.util.regex.Matcher;
35

36
import static com.perl5.lang.perl.internals.PerlVersionRegexps.*;
37

38
/**
39
 * Represents perl version
40
 */
41
public final class PerlVersion implements Comparable<PerlVersion> {
42
  private static final Logger LOG = Logger.getInstance(PerlVersion.class);
1✔
43
  public static final PerlVersion V5_10 = new PerlVersion(5.010);
1✔
44
  public static final PerlVersion V5_12 = new PerlVersion(5.012);
1✔
45
  public static final PerlVersion V5_14 = new PerlVersion(5.014);
1✔
46
  public static final PerlVersion V5_16 = new PerlVersion(5.016);
1✔
47
  public static final PerlVersion V5_18 = new PerlVersion(5.018);
1✔
48
  public static final PerlVersion V5_20 = new PerlVersion(5.020);
1✔
49
  public static final PerlVersion V5_22 = new PerlVersion(5.022);
1✔
50
  public static final PerlVersion V5_24 = new PerlVersion(5.024);
1✔
51
  public static final PerlVersion V5_26 = new PerlVersion(5.026);
1✔
52
  public static final PerlVersion V5_28 = new PerlVersion(5.028);
1✔
53
  public static final PerlVersion V5_30 = new PerlVersion(5.030);
1✔
54
  public static final PerlVersion V5_32 = new PerlVersion(5.032);
1✔
55
  public static final PerlVersion V5_34 = new PerlVersion(5.034);
1✔
56
  public static final PerlVersion V5_36 = new PerlVersion(5.036);
1✔
57
  public static final PerlVersion V5_38 = new PerlVersion(5.038);
1✔
58
  public static final PerlVersion V5_40 = new PerlVersion(5.036);
1✔
59
  public static final PerlVersion V5_42 = new PerlVersion(5.038);
1✔
60
  public static final Predicate<PerlVersion> GREATER_OR_EQUAL_V520 = version -> !version.lesserThan(V5_20);
1✔
61
  public static final Predicate<PerlVersion> GREATER_OR_EQUAL_V522 = version -> !version.lesserThan(V5_22);
1✔
62
  public static final Predicate<PerlVersion> GREATER_OR_EQUAL_V532 = version -> !version.lesserThan(V5_32);
1✔
63
  public static final List<PerlVersion> ALL_VERSIONS = List.of(
1✔
64
    V5_10, V5_12, V5_14, V5_16, V5_18, V5_20, V5_22, V5_24, V5_26, V5_28, V5_30, V5_32, V5_34, V5_36, V5_38, V5_40, V5_42
65
  );
66

67
  public static final Map<PerlVersion, @Nls String> PERL_VERSION_DESCRIPTIONS = Maps.of(
1✔
68
    V5_10, PerlBundle.message("perl.version.description.5.10"),
1✔
69
    V5_12, PerlBundle.message("perl.version.description.5.12"),
1✔
70
    V5_14, PerlBundle.message("perl.version.description.5.14"),
1✔
71
    V5_16, PerlBundle.message("perl.version.description.5.16"),
1✔
72
    V5_18, PerlBundle.message("perl.version.description.5.18"),
1✔
73
    V5_20, PerlBundle.message("perl.version.description.5.20"),
1✔
74
    V5_22, PerlBundle.message("perl.version.description.5.22"),
1✔
75
    V5_24, PerlBundle.message("perl.version.description.5.24"),
1✔
76
    V5_26, PerlBundle.message("perl.version.description.5.26"),
1✔
77
    V5_28, PerlBundle.message("perl.version.description.5.28"),
1✔
78
    V5_30, PerlBundle.message("perl.version.description.5.30"),
1✔
79
    V5_32, PerlBundle.message("perl.version.description.5.32"),
1✔
80
    V5_34, PerlBundle.message("perl.version.description.5.34"),
1✔
81
    V5_36, PerlBundle.message("perl.version.description.5.36"),
1✔
82
    V5_38, PerlBundle.message("perl.version.description.5.38")
1✔
83
  );
84

85
  @Tag("isAlpha")
86
  private boolean myIsAlpha;
87
  @Tag("isStrict")
88
  private boolean myIsStrict;
89
  @Tag("isValid")
90
  private boolean myIsValid;
91
  @Tag("revision")
92
  private int myRevision;
93
  @Tag("major")
94
  private int myMajor;
95
  @Tag("minor")
96
  private int myMinor;
97
  @Tag("extraChunks")
1✔
98
  private List<Integer> myExtraChunks = Collections.emptyList();
1✔
99

100
  @SuppressWarnings("unused")
101
  private PerlVersion() {
1✔
102
  }
1✔
103

104
  public PerlVersion(double version) {
1✔
105
    try {
106
      parseDoubleVersion(version);
1✔
107
    }
108
    catch (NumberFormatException e) {
×
109
      LOG.debug("Unable to parse version: ", version, "; message: ", e.getMessage());
×
110
    }
1✔
111
  }
1✔
112

113
  public PerlVersion(String versionString) {
1✔
114
    init(versionString);
1✔
115
  }
1✔
116

117
  private void init(String versionString) {
118
    try {
119
      Matcher matcher;
120

121
      if (NUMERIC_VERSION.matcher(versionString).matches()) {
1✔
122
        parseDoubleVersion(Double.parseDouble(versionString.replace("_", "")));
1✔
123
        myIsAlpha = versionString.contains("_");
1✔
124
      }
125
      else if ((matcher = DOTTED_VERSION.matcher(versionString)).matches()) {
1✔
126
        parseDottedVersion(versionString, matcher);
1✔
127
      }
128
      else {
129
        myIsValid = false;
1✔
130
        return;
1✔
131
      }
132
      myIsStrict = STRICT_VERSION_PATTERN.matcher(versionString).matches();
1✔
133
      myIsValid = true;
1✔
134
    }
135
    catch (NumberFormatException e) {
1✔
136
      myIsValid = myIsStrict = myIsAlpha = false;
1✔
137
      myRevision = myMajor = myMinor = 0;
1✔
138
    }
1✔
139
  }
1✔
140

141
  private void parseDottedVersion(String versionString, Matcher matcher) {
142
    List<String> versionChunks = PerlUtil.mutableList(versionString.replace("v", "").replace('_', '.').split("\\."));
1✔
143
    myIsAlpha = matcher.group(1) != null;
1✔
144
    myRevision = Integer.parseInt(versionChunks.removeFirst());
1✔
145

146
    if (versionChunks.isEmpty()) {
1✔
147
      return;
1✔
148
    }
149
    if (versionChunks.getFirst().length() > 3) {
1✔
150
      throw new NumberFormatException();
1✔
151
    }
152

153
    myMajor = Integer.parseInt(versionChunks.removeFirst());
1✔
154

155
    if (versionChunks.isEmpty()) {
1✔
156
      return;
1✔
157
    }
158
    if (versionChunks.getFirst().length() > 3) {
1!
159
      throw new NumberFormatException();
×
160
    }
161

162
    myMinor = Integer.parseInt(versionChunks.removeFirst());
1✔
163

164
    if (versionChunks.isEmpty()) {
1✔
165
      return;
1✔
166
    }
167
    myExtraChunks = new ArrayList<>();
1✔
168
    for (String chunk : versionChunks) {
1✔
169
      if (chunk.length() > 3) {
1!
170
        throw new NumberFormatException();
×
171
      }
172
      else {
173
        myExtraChunks.add(Integer.parseInt(chunk));
1✔
174
      }
175
    }
1✔
176
  }
1✔
177

178
  public void parseDoubleVersion(double version) throws NumberFormatException {
179
    if (version <= Integer.MAX_VALUE) {
1✔
180
      long longVersion = (long)(version * 1000000);
1✔
181
      myIsStrict = true;
1✔
182
      myIsAlpha = false;
1✔
183
      myIsValid = version > 0;
1✔
184
      if (myIsValid) {
1✔
185
        myRevision = (int)version;
1✔
186
        longVersion = (longVersion - myRevision * 1000000L);
1✔
187
        myMajor = (int)(longVersion / 1000);
1✔
188
        myMinor = (int)(longVersion % 1000);
1✔
189
      }
190
    }
1✔
191
    else {
192
      throw new NumberFormatException("Version is too big");
1✔
193
    }
194
  }
1✔
195

196
  public double getDoubleVersion() {
197
    double version = myRevision + ((double)myMajor / 1000) + ((double)myMinor / 1000000);
1✔
198

199
    if (!myExtraChunks.isEmpty()) {
1✔
200
      long divider = 1000000000;
1✔
201
      for (Integer chunk : myExtraChunks) {
1✔
202
        version += ((double)chunk) / divider;
1✔
203
        divider *= 1000;
1✔
204
      }
1✔
205
    }
206

207
    return version;
1✔
208
  }
209

210
  public @NlsSafe String getStrictDottedVersion() {
211
    List<String> result = new ArrayList<>(Collections.singletonList(Integer.toString(myRevision)));
1✔
212

213
    if (myMajor > 0 || myMinor > 0 || !myExtraChunks.isEmpty()) {
1!
214
      result.add(Integer.toString(myMajor));
1✔
215
    }
216

217
    if (myMinor > 0 || !myExtraChunks.isEmpty()) {
1!
218
      result.add(Integer.toString(myMinor));
1✔
219
    }
220

221
    for (Integer chunk : myExtraChunks) {
1✔
222
      result.add(Integer.toString(chunk));
1✔
223
    }
1✔
224

225
    return "v" + StringUtil.join(result, ".");
1✔
226
  }
227

228
  public int getRevision() {
229
    return myRevision;
1✔
230
  }
231

232
  public int getMajor() {
233
    return myMajor;
1✔
234
  }
235

236
  public int getMinor() {
237
    return myMinor;
1✔
238
  }
239

240
  public boolean isAlpha() {
241
    return myIsAlpha;
1✔
242
  }
243

244
  public boolean isStrict() {
245
    return myIsStrict;
1✔
246
  }
247

248
  public boolean isValid() {
249
    return myIsValid;
1✔
250
  }
251

252
  @Override
253
  public int compareTo(@NotNull PerlVersion o) {
254
    return Double.compare(getDoubleVersion(), o.getDoubleVersion());
1✔
255
  }
256

257
  @Override
258
  public boolean equals(Object o) {
259
    return o instanceof PerlVersion perlVersion && (this == o || this.getDoubleVersion() == perlVersion.getDoubleVersion());
1!
260
  }
261

262
  @Override
263
  public int hashCode() {
264
    return Double.hashCode(getDoubleVersion());
1✔
265
  }
266

267
  public boolean lesserThan(PerlVersion o) {
268
    return compareTo(o) < 0;
1✔
269
  }
270

271
  public boolean greaterThan(PerlVersion o) {
272
    return compareTo(o) > 0;
1✔
273
  }
274
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc