All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sourceforge.pmd.util.AssertionUtil Maven / Gradle / Ivy

Go to download

PMD is an extensible multilanguage static code analyzer. It finds common programming flaws like unused variables, empty catch blocks, unnecessary object creation, and so forth. It's mainly concerned with Java and Apex, but supports 16 other languages. It comes with 400+ built-in rules. It can be extended with custom rules. It uses JavaCC and Antlr to parse source files into abstract syntax trees (AST) and runs rules against them to find violations. Rules can be written in Java or using a XPath query. Currently, PMD supports Java, JavaScript, Salesforce.com Apex and Visualforce, Kotlin, Swift, Modelica, PLSQL, Apache Velocity, JSP, WSDL, Maven POM, HTML, XML and XSL. Scala is supported, but there are currently no Scala rules available. Additionally, it includes CPD, the copy-paste-detector. CPD finds duplicated code in Coco, C/C++, C#, Dart, Fortran, Gherkin, Go, Groovy, HTML, Java, JavaScript, JSP, Julia, Kotlin, Lua, Matlab, Modelica, Objective-C, Perl, PHP, PLSQL, Python, Ruby, Salesforce.com Apex and Visualforce, Scala, Swift, T-SQL, Typescript, Apache Velocity, WSDL, XML and XSL.

The newest version!
/*
 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
 */

package net.sourceforge.pmd.util;


import java.util.Collection;
import java.util.function.Function;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ContextedRuntimeException;
import org.checkerframework.checker.nullness.qual.NonNull;

public final class AssertionUtil {

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

    private AssertionUtil() {
        // utility class
    }


    /** @throws NullPointerException if any item is null */
    public static void requireContainsNoNullValue(String name, Collection c) {
        int i = 0;
        for (Object o : c) {
            if (o == null) {
                throw new NullPointerException(name + " contains a null element at index " + i);
            }
            i++;
        }
    }

    /** @throws IllegalArgumentException if empty */
    public static void requireNotEmpty(String name, Collection c) {
        if (c.isEmpty()) {
            throw new IllegalArgumentException(name + " is empty");
        }
    }

    public static boolean isValidJavaPackageName(CharSequence name) {
        requireParamNotNull("name", name);
        return PACKAGE_PATTERN.matcher(name).matches();
    }

    /**
     * @throws IllegalArgumentException if the name is not a binary name
     */
    public static void assertValidJavaBinaryName(CharSequence name) {
        if (!isJavaBinaryName(name)) {
            throw new IllegalArgumentException("Not a Java binary name '" + name + "'");
        }
    }

    /**
     * @throws IllegalArgumentException if the name is not a binary name
     */
    public static void assertValidJavaBinaryNameNoArray(CharSequence name) {
        if (!BINARY_NAME_NO_ARRAY.matcher(name).matches()) {
            throw new IllegalArgumentException("Not a Java binary name '" + name + "'");
        }
    }

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

    private static boolean isValidRange(int startInclusive, int endExclusive, int minIndex, int maxIndex) {
        return startInclusive <= endExclusive && minIndex <= startInclusive && endExclusive <= maxIndex;
    }

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


    /** Throws {@link IllegalStateException} if the condition is false. */
    public static void validateState(boolean condition, String failed) {
        if (!condition) {
            throw new IllegalStateException(failed);
        }
    }


    /**
     * @throws IllegalArgumentException if [startInclusive,endExclusive[ is
     *                                  not a valid substring range for the given string
     */
    public static void validateStringRange(CharSequence string, int startInclusive, int endExclusive) {
        if (!isValidRange(startInclusive, endExclusive, 0, string.length())) {
            throw new IllegalArgumentException(invalidRangeMessage(startInclusive, endExclusive, 0, string.length()));
        }
    }

    /**
     * Like {@link #validateStringRange(CharSequence, int, int)} but eliminated
     * at runtime if running without assertions.
     */
    public static void assertValidStringRange(CharSequence string, int startInclusive, int endExclusive) {
        assert isValidRange(startInclusive, endExclusive, 0, string.length())
            : invalidRangeMessage(startInclusive, endExclusive, 0, string.length());
    }

    /**
     * Returns true if the charsequence is a valid java identifier.
     *
     * @param name Name (non-null)
     *
     * @throws NullPointerException If the name is null
     */
    public static boolean isJavaIdentifier(CharSequence name) {
        int len = name.length();
        if (len == 0 || !Character.isJavaIdentifierStart(name.charAt(0))) {
            return false;
        }

        for (int i = 1; i < len; i++) {
            if (!Character.isJavaIdentifierPart(name.charAt(i))) {
                return false;
            }
        }

        return true;
    }

    public static int requireOver1(String name, final int value) {
        if (value < 1) {
            throw mustBe(name, value, ">= 1");
        }
        return value;
    }


    /**
     * @throws IllegalArgumentException If {@code value < 0}
     */
    public static int requireNonNegative(String name, int value) {
        if (value < 0) {
            throw mustBe(name, value, "non-negative");
        }
        return value;
    }


    /**
     * @throws IndexOutOfBoundsException If {@code value < 0}
     */
    public static int requireIndexNonNegative(String name, int value) {
        if (value < 0) {
            throw mustBe(name, value, "non-negative", IndexOutOfBoundsException::new);
        }
        return value;
    }

    /**
     * @throws IndexOutOfBoundsException If {@code value < 0 || value >= maxValue}
     */
    public static int requireInNonNegativeRange(String name, int value, int maxValue) {
        return requireInExclusiveRange(name, value, 0, maxValue);
    }

    /**
     * @throws IndexOutOfBoundsException If {@code value < 1 || value >= maxValue}
     */
    public static int requireInPositiveRange(String name, int value, int maxValue) {
        return requireInExclusiveRange(name, value, 1, maxValue);
    }

    // the difference between those two is the message

    /**
     * @throws IndexOutOfBoundsException If {@code value < minValue || value > maxValue}
     */
    public static int requireInInclusiveRange(String name, int value, int minValue, int maxValue) {
        return requireInRange(name, value, minValue, maxValue, true);
    }

    /**
     * @throws IndexOutOfBoundsException If {@code value < minValue || value > maxValue}
     */
    public static int requireInExclusiveRange(String name, int value, int minValue, int maxValue) {
        return requireInRange(name, value, minValue, maxValue, false);
    }

    public static int requireInRange(String name, int value, int minValue, int maxValue, boolean inclusive) {
        if (value < 0 || inclusive && value > maxValue || !inclusive && value >= maxValue) {
            String message = "in range [" + minValue + "," + maxValue;
            message += inclusive ? "]" : "[";
            throw mustBe(name, value, message, IndexOutOfBoundsException::new);
        }
        return value;
    }

    public static RuntimeException mustBe(String name, Object value, String condition) {
        return mustBe(name, value, condition, IllegalArgumentException::new);
    }

    public static  E mustBe(String name, Object value, String condition, Function exceptionMaker) {
        return exceptionMaker.apply(String.format("%s must be %s, got %s", name, condition, value));
    }

    @NonNull
    public static  T requireParamNotNull(String paramName, T obj) {
        if (obj == null) {
            throw new NullPointerException("Parameter " + paramName + " is null");
        }

        return obj;
    }

    public static @NonNull AssertionError shouldNotReachHere(String message) {
        return shouldNotReachHere(message, null);
    }

    public static @NonNull AssertionError shouldNotReachHere(String message, Throwable cause) {
        String prefix = "This should be unreachable";
        message = StringUtils.isBlank(message) ? prefix
                                               : prefix + ": " + message;
        return new AssertionError(message, cause);
    }

    public static @NonNull ContextedAssertionError contexted(AssertionError e) {
        return ContextedAssertionError.wrap(e);
    }

    public static @NonNull ContextedStackOverflowError contexted(StackOverflowError e) {
        return ContextedStackOverflowError.wrap(e);
    }

    public static @NonNull ContextedRuntimeException contexted(RuntimeException e) {
        return e instanceof ContextedRuntimeException ? (ContextedRuntimeException) e
                                                      : new ContextedRuntimeException(e);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy