001 /*
002 * Copyright 2010-2015 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.kotlin.resolve.calls.results;
018
019 import org.jetbrains.annotations.NotNull;
020
021 import java.util.EnumSet;
022
023 public enum ResolutionStatus {
024 UNKNOWN_STATUS,
025 UNSAFE_CALL_ERROR,
026 OTHER_ERROR,
027 // '1.foo()' shouldn't be resolved to 'fun String.foo()'
028 // candidates with such error are treated specially
029 // (are mentioned in 'unresolved' error, if there are no other options)
030 RECEIVER_TYPE_ERROR,
031 // 'a.foo()' shouldn't be resolved to package level non-extension 'fun foo()'
032 // candidates with such error are thrown away completely
033 RECEIVER_PRESENCE_ERROR,
034 INCOMPLETE_TYPE_INFERENCE,
035 SUCCESS(true);
036
037 @SuppressWarnings("unchecked")
038 public static final EnumSet<ResolutionStatus>[] SEVERITY_LEVELS = new EnumSet[] {
039 EnumSet.of(UNSAFE_CALL_ERROR), // weakest
040 EnumSet.of(OTHER_ERROR),
041 EnumSet.of(RECEIVER_TYPE_ERROR),
042 EnumSet.of(RECEIVER_PRESENCE_ERROR), // most severe
043 };
044
045 private final boolean success;
046 private int severityIndex = -1;
047
048 private ResolutionStatus(boolean success) {
049 this.success = success;
050 }
051
052 private ResolutionStatus() {
053 this(false);
054 }
055
056 public boolean isSuccess() {
057 return success;
058 }
059
060 @NotNull
061 public ResolutionStatus combine(ResolutionStatus other) {
062 if (this == UNKNOWN_STATUS) return other;
063 if (SUCCESS.among(this, other)) {
064 return SUCCESS.chooseDifferent(this, other);
065 }
066 if (INCOMPLETE_TYPE_INFERENCE.among(this, other)) {
067 return INCOMPLETE_TYPE_INFERENCE.chooseDifferent(this, other);
068 }
069 if (this.getSeverityIndex() < other.getSeverityIndex()) return other;
070 return this;
071 }
072
073 private boolean among(ResolutionStatus first, ResolutionStatus second) {
074 return this == first || this == second;
075 }
076
077 private ResolutionStatus chooseDifferent(ResolutionStatus first, ResolutionStatus second) {
078 assert among(first, second);
079 return this == first ? second : first;
080 }
081
082 private int getSeverityIndex() {
083 if (severityIndex == -1) {
084 for (int i = 0; i < SEVERITY_LEVELS.length; i++) {
085 if (SEVERITY_LEVELS[i].contains(this)) {
086 severityIndex = i;
087 break;
088 }
089 }
090 }
091 assert severityIndex >= 0;
092
093 return severityIndex;
094 }
095 }