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

pmd / pmd / 4509

21 Mar 2025 11:23AM UTC coverage: 77.757% (-0.004%) from 77.761%
4509

push

github

adangel
[doc] Use full class name for deprecation in release notes

17505 of 23464 branches covered (74.6%)

Branch coverage included in aggregate %.

38318 of 48328 relevant lines covered (79.29%)

0.8 hits per line

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

45.26
/pmd-core/src/main/java/net/sourceforge/pmd/util/AssertionUtil.java
1
/*
2
 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3
 */
4

5
package net.sourceforge.pmd.util;
6

7

8
import java.util.Collection;
9
import java.util.function.Function;
10
import java.util.regex.Pattern;
11

12
import org.apache.commons.lang3.StringUtils;
13
import org.apache.commons.lang3.exception.ContextedRuntimeException;
14
import org.checkerframework.checker.nullness.qual.NonNull;
15

16
public final class AssertionUtil {
17

18
    private static final Pattern PACKAGE_PATTERN = Pattern.compile("[\\w$]+(\\.[\\w$]+)*|");
1✔
19
    private static final Pattern BINARY_NAME_PATTERN = Pattern.compile("[\\w$]+(?:\\.[\\w$]+)*(?:\\[])*");
1✔
20
    private static final Pattern BINARY_NAME_NO_ARRAY = Pattern.compile("[\\w$]++(?:\\.[\\w$]++)*");
1✔
21

22
    private static final boolean ASSERT_ENABLED;
23

24
    static {
25
        boolean assertEnabled = false;
1✔
26
        //noinspection AssertWithSideEffects
27
        assert assertEnabled = true; // SUPPRESS CHECKSTYLE now
1!
28
        ASSERT_ENABLED = assertEnabled;
1✔
29
    }
1✔
30

31
    private AssertionUtil() {
32
        // utility class
33
    }
34

35
    /**
36
     * Return true if the VM runs with assertions enabled.
37
     */
38
    public static boolean isAssertEnabled() {
39
        return ASSERT_ENABLED;
×
40
    }
41

42
    /** @throws NullPointerException if any item is null */
43
    public static void requireContainsNoNullValue(String name, Collection<?> c) {
44
        int i = 0;
1✔
45
        for (Object o : c) {
1✔
46
            if (o == null) {
1!
47
                throw new NullPointerException(name + " contains a null element at index " + i);
×
48
            }
49
            i++;
1✔
50
        }
1✔
51
    }
1✔
52

53
    /** @throws IllegalArgumentException if empty */
54
    public static void requireNotEmpty(String name, Collection<?> c) {
55
        if (c.isEmpty()) {
1!
56
            throw new IllegalArgumentException(name + " is empty");
×
57
        }
58
    }
1✔
59

60
    public static boolean isValidJavaPackageName(CharSequence name) {
61
        requireParamNotNull("name", name);
×
62
        return PACKAGE_PATTERN.matcher(name).matches();
×
63
    }
64

65
    /**
66
     * @throws IllegalArgumentException if the name is not a binary name
67
     */
68
    public static void assertValidJavaBinaryName(CharSequence name) {
69
        if (!isJavaBinaryName(name)) {
×
70
            throw new IllegalArgumentException("Not a Java binary name '" + name + "'");
×
71
        }
72
    }
×
73

74
    /**
75
     * @throws IllegalArgumentException if the name is not a binary name
76
     */
77
    public static void assertValidJavaBinaryNameNoArray(CharSequence name) {
78
        if (!BINARY_NAME_NO_ARRAY.matcher(name).matches()) {
×
79
            throw new IllegalArgumentException("Not a Java binary name '" + name + "'");
×
80
        }
81
    }
×
82

83
    private static boolean isJavaBinaryName(CharSequence name) {
84
        return name.length() > 0 && BINARY_NAME_PATTERN.matcher(name).matches();
×
85
    }
86

87
    private static boolean isValidRange(int startInclusive, int endExclusive, int minIndex, int maxIndex) {
88
        return startInclusive <= endExclusive && minIndex <= startInclusive && endExclusive <= maxIndex;
×
89
    }
90

91
    private static String invalidRangeMessage(int startInclusive, int endExclusive, int minIndex, int maxIndex) {
92
        return "Invalid range [" + startInclusive + "," + endExclusive + "[ in [" + minIndex + "," + maxIndex + "[";
×
93
    }
94

95

96
    /** Throws {@link IllegalStateException} if the condition is false. */
97
    public static void validateState(boolean condition, String failed) {
98
        if (!condition) {
1✔
99
            throw new IllegalStateException(failed);
1✔
100
        }
101
    }
1✔
102

103

104
    /**
105
     * @throws IllegalArgumentException if [startInclusive,endExclusive[ is
106
     *                                  not a valid substring range for the given string
107
     */
108
    public static void validateStringRange(CharSequence string, int startInclusive, int endExclusive) {
109
        if (!isValidRange(startInclusive, endExclusive, 0, string.length())) {
×
110
            throw new IllegalArgumentException(invalidRangeMessage(startInclusive, endExclusive, 0, string.length()));
×
111
        }
112
    }
×
113

114
    /**
115
     * Like {@link #validateStringRange(CharSequence, int, int)} but eliminated
116
     * at runtime if running without assertions.
117
     */
118
    public static void assertValidStringRange(CharSequence string, int startInclusive, int endExclusive) {
119
        assert isValidRange(startInclusive, endExclusive, 0, string.length())
×
120
            : invalidRangeMessage(startInclusive, endExclusive, 0, string.length());
×
121
    }
×
122

123
    /**
124
     * Returns true if the charsequence is a valid java identifier.
125
     *
126
     * @param name Name (non-null)
127
     *
128
     * @throws NullPointerException If the name is null
129
     */
130
    public static boolean isJavaIdentifier(CharSequence name) {
131
        int len = name.length();
×
132
        if (len == 0 || !Character.isJavaIdentifierStart(name.charAt(0))) {
×
133
            return false;
×
134
        }
135

136
        for (int i = 1; i < len; i++) {
×
137
            if (!Character.isJavaIdentifierPart(name.charAt(i))) {
×
138
                return false;
×
139
            }
140
        }
141

142
        return true;
×
143
    }
144

145
    public static int requireOver1(String name, final int value) {
146
        if (value < 1) {
1!
147
            throw mustBe(name, value, ">= 1");
×
148
        }
149
        return value;
1✔
150
    }
151

152

153
    /**
154
     * @throws IllegalArgumentException If {@code value < 0}
155
     */
156
    public static int requireNonNegative(String name, int value) {
157
        if (value < 0) {
1✔
158
            throw mustBe(name, value, "non-negative");
1✔
159
        }
160
        return value;
1✔
161
    }
162

163

164
    /**
165
     * @throws IndexOutOfBoundsException If {@code value < 0}
166
     */
167
    public static int requireIndexNonNegative(String name, int value) {
168
        if (value < 0) {
1!
169
            throw mustBe(name, value, "non-negative", IndexOutOfBoundsException::new);
×
170
        }
171
        return value;
1✔
172
    }
173

174
    /**
175
     * @throws IndexOutOfBoundsException If {@code value < 0 || value >= maxValue}
176
     */
177
    public static int requireInNonNegativeRange(String name, int value, int maxValue) {
178
        return requireInExclusiveRange(name, value, 0, maxValue);
×
179
    }
180

181
    /**
182
     * @throws IndexOutOfBoundsException If {@code value < 1 || value >= maxValue}
183
     */
184
    public static int requireInPositiveRange(String name, int value, int maxValue) {
185
        return requireInExclusiveRange(name, value, 1, maxValue);
1✔
186
    }
187

188
    // the difference between those two is the message
189

190
    /**
191
     * @throws IndexOutOfBoundsException If {@code value < minValue || value > maxValue}
192
     */
193
    public static int requireInInclusiveRange(String name, int value, int minValue, int maxValue) {
194
        return requireInRange(name, value, minValue, maxValue, true);
1✔
195
    }
196

197
    /**
198
     * @throws IndexOutOfBoundsException If {@code value < minValue || value > maxValue}
199
     */
200
    public static int requireInExclusiveRange(String name, int value, int minValue, int maxValue) {
201
        return requireInRange(name, value, minValue, maxValue, false);
1✔
202
    }
203

204
    public static int requireInRange(String name, int value, int minValue, int maxValue, boolean inclusive) {
205
        if (value < 0 || inclusive && value > maxValue || !inclusive && value >= maxValue) {
1!
206
            String message = "in range [" + minValue + "," + maxValue;
1✔
207
            message += inclusive ? "]" : "[";
1!
208
            throw mustBe(name, value, message, IndexOutOfBoundsException::new);
1✔
209
        }
210
        return value;
1✔
211
    }
212

213
    public static RuntimeException mustBe(String name, Object value, String condition) {
214
        return mustBe(name, value, condition, IllegalArgumentException::new);
1✔
215
    }
216

217
    public static <E extends RuntimeException> E mustBe(String name, Object value, String condition, Function<String, E> exceptionMaker) {
218
        return exceptionMaker.apply(String.format("%s must be %s, got %s", name, condition, value));
1✔
219
    }
220

221
    @NonNull
222
    public static <T> T requireParamNotNull(String paramName, T obj) {
223
        if (obj == null) {
1!
224
            throw new NullPointerException("Parameter " + paramName + " is null");
×
225
        }
226

227
        return obj;
1✔
228
    }
229

230
    public static @NonNull AssertionError shouldNotReachHere(String message) {
231
        return shouldNotReachHere(message, null);
×
232
    }
233

234
    public static @NonNull AssertionError shouldNotReachHere(String message, Throwable cause) {
235
        String prefix = "This should be unreachable";
×
236
        message = StringUtils.isBlank(message) ? prefix
×
237
                                               : prefix + ": " + message;
×
238
        return new AssertionError(message, cause);
×
239
    }
240

241
    public static @NonNull ContextedAssertionError contexted(AssertionError e) {
242
        return ContextedAssertionError.wrap(e);
1✔
243
    }
244

245
    public static @NonNull ContextedStackOverflowError contexted(StackOverflowError e) {
246
        return ContextedStackOverflowError.wrap(e);
×
247
    }
248

249
    public static @NonNull ContextedRuntimeException contexted(RuntimeException e) {
250
        return e instanceof ContextedRuntimeException ? (ContextedRuntimeException) e
1!
251
                                                      : new ContextedRuntimeException(e);
1✔
252
    }
253

254
}
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