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
017 package org.jetbrains.jet.lang.resolve.calls.results;
018
019 import java.util.EnumSet;
020
021 public 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 }