001/*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.jetbrains.jet.lang.resolve.calls.results;
018
019import java.util.EnumSet;
020
021public enum ResolutionStatus {
022    UNKNOWN_STATUS,
023    UNSAFE_CALL_ERROR,
024    OTHER_ERROR,
025    // '1.foo()' shouldn't be resolved to 'fun String.foo()'
026    // candidates with such error are treated specially
027    // (are mentioned in 'unresolved' error, if there are no other options)
028    RECEIVER_TYPE_ERROR,
029    // 'a.foo()' shouldn't be resolved to package level non-extension 'fun foo()'
030    // candidates with such error are thrown away completely
031    RECEIVER_PRESENCE_ERROR,
032    INCOMPLETE_TYPE_INFERENCE,
033    SUCCESS(true);
034
035    @SuppressWarnings("unchecked")
036    public static final EnumSet<ResolutionStatus>[] SEVERITY_LEVELS = new EnumSet[] {
037            EnumSet.of(UNSAFE_CALL_ERROR), // weakest
038            EnumSet.of(OTHER_ERROR),
039            EnumSet.of(RECEIVER_TYPE_ERROR),
040            EnumSet.of(RECEIVER_PRESENCE_ERROR), // most severe
041    };
042
043    private final boolean success;
044    private int severityIndex = -1;
045
046    private ResolutionStatus(boolean success) {
047        this.success = success;
048    }
049
050    private ResolutionStatus() {
051        this(false);
052    }
053
054    public boolean isSuccess() {
055        return success;
056    }
057
058    public ResolutionStatus combine(ResolutionStatus other) {
059        if (this == UNKNOWN_STATUS) return other;
060        if (SUCCESS.among(this, other)) {
061            return SUCCESS.chooseDifferent(this, other);
062        }
063        if (INCOMPLETE_TYPE_INFERENCE.among(this, other)) {
064            return INCOMPLETE_TYPE_INFERENCE.chooseDifferent(this, other);
065        }
066        if (this.getSeverityIndex() < other.getSeverityIndex()) return other;
067        return this;
068    }
069
070    private boolean among(ResolutionStatus first, ResolutionStatus second) {
071        return this == first || this == second;
072    }
073
074    private ResolutionStatus chooseDifferent(ResolutionStatus first, ResolutionStatus second) {
075        assert among(first, second);
076        return this == first ? second : first;
077    }
078
079    private int getSeverityIndex() {
080        if (severityIndex == -1) {
081            for (int i = 0; i < SEVERITY_LEVELS.length; i++) {
082                if (SEVERITY_LEVELS[i].contains(this)) {
083                    severityIndex = i;
084                    break;
085                }
086            }
087        }
088        assert severityIndex >= 0;
089
090        return severityIndex;
091    }
092}