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

org.checkerframework.framework.source.Result Maven / Gradle / Ivy

Go to download

The Checker Framework enhances Java's type system to make it more powerful and useful. This lets software developers detect and prevent errors in their Java programs. The Checker Framework includes compiler plug-ins ("checkers") that find bugs or verify their absence. It also permits you to write your own compiler plug-ins.

There is a newer version: 3.0.0-b2
Show newest version
package org.checkerframework.framework.source;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.qual.Pure;
import org.checkerframework.dataflow.qual.SideEffectFree;

/**
 * Represents the outcome of a type-checking operation (success, warning, or failure, plus a list of
 * explanatory messages). {@link Result}s created during type-checking can be reported using {@link
 * SourceChecker#report}, which ultimately delivers an error or warning message via the JSR 199
 * compiler interface.
 *
 * @see SourceChecker#report
 */
public final class Result {

    private static enum Type {
        SUCCESS,
        FAILURE,
        WARNING;

        /** @return whichever of the given types is most serious */
        public static final Type merge(Type a, Type b) {
            if (a == FAILURE || b == FAILURE) {
                return FAILURE;
            } else if (a == WARNING || b == WARNING) {
                return WARNING;
            } else {
                return SUCCESS;
            }
        }
    }

    /** The type of result (success, warning, failure). */
    private final Type type;

    /** The messages for the results. */
    private final List messages;

    /** The success result. */
    public static final Result SUCCESS = new Result(Type.SUCCESS, null);

    /**
     * Creates a new failure result with the given message key.
     *
     * @param messageKey the key representing the reason for failure
     * @param args optional arguments to be included in the message
     * @return the failure result
     */
    public static Result failure(@CompilerMessageKey String messageKey, @Nullable Object... args) {
        return new Result(Type.FAILURE, Collections.singleton(new DiagMessage(messageKey, args)));
    }

    /**
     * Creates a new warning result with the given message.
     *
     * @param messageKey the key for the warning message
     * @param args optional arguments to be included in the message
     * @return the warning result
     */
    public static Result warning(@CompilerMessageKey String messageKey, @Nullable Object... args) {
        return new Result(Type.WARNING, Collections.singleton(new DiagMessage(messageKey, args)));
    }

    private Result(Type type, Collection messagePairs) {
        this.type = type;
        this.messages = new ArrayList<>();
        if (messagePairs != null) {
            for (DiagMessage msg : messagePairs) {
                String message = msg.getMessageKey();
                @Nullable Object[] args = msg.getArgs();
                if (args != null) {
                    args = Arrays.copyOf(msg.getArgs(), args.length);
                }
                this.messages.add(new DiagMessage(message, args));
            }
        }
    }

    /**
     * Merges two results into one.
     *
     * @param r the result to merge with this result
     * @return a result that is the success result if both this and {@code r} are success results,
     *     or a result that has the more significant type (failure > warning > success) and
     *     the message keys of both this result and {@code r}
     */
    public Result merge(Result r) {
        if (r == null) {
            return this;
        }

        if (r.isSuccess() && this.isSuccess()) {
            return SUCCESS;
        }

        List messages = new ArrayList<>(this.messages.size() + r.messages.size());
        messages.addAll(this.messages);
        messages.addAll(r.messages);
        return new Result(Type.merge(r.type, this.type), messages);
    }

    /** @return true if the result is success (not a failure or warning) */
    public boolean isSuccess() {
        return type == Type.SUCCESS;
    }

    /** @return true if the result is a failure */
    public boolean isFailure() {
        return type == Type.FAILURE;
    }

    /** @return true if the result is a warning */
    public boolean isWarning() {
        return type == Type.WARNING;
    }

    /** @return the message keys associated with the result */
    public List getMessageKeys() {
        List msgKeys = new ArrayList<>(getDiagMessages().size());
        for (DiagMessage msg : getDiagMessages()) {
            msgKeys.add(msg.getMessageKey());
        }

        return Collections.unmodifiableList(msgKeys);
    }

    /** @return an unmodifiable list of the message pairs */
    public List getDiagMessages() {
        return Collections.unmodifiableList(messages);
    }

    @SideEffectFree
    @Override
    public String toString() {
        switch (type) {
            case FAILURE:
                return "FAILURE: " + messages;
            case WARNING:
                return "WARNING: " + messages;
            case SUCCESS:
            default:
                return "SUCCESS";
        }
    }

    /**
     * A class that represents diagnostic messages.
     *
     * 

{@code DiagMessage} encapsulates the message key which would identify the relevant * standard error message according to the user locale. * *

The optional arguments are possible custom strings for the error message. */ public static class DiagMessage { private final @CompilerMessageKey String message; private Object[] args; protected DiagMessage(@CompilerMessageKey String message, Object[] args) { this.message = message; if (args == null) { this.args = new Object[0]; /*null->nn*/ } else { this.args = Arrays.copyOf(args, args.length); } } /** @return the message key of this DiagMessage */ public @CompilerMessageKey String getMessageKey() { return this.message; } /** @return the customized optional arguments for the message */ public Object[] getArgs() { return this.args; } @Override public boolean equals(Object obj) { if (!(obj instanceof DiagMessage)) { return false; } DiagMessage other = (DiagMessage) obj; return (message.equals(other.message) && Arrays.equals(args, other.args)); } @Pure @Override public int hashCode() { return Objects.hash(this.message, Arrays.hashCode(this.args)); } @SideEffectFree @Override public String toString() { if (args.length == 0) { return message; } return message + " : " + Arrays.toString(args); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy