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.smartcasts;
018
019 import org.jetbrains.annotations.NotNull;
020
021 public enum Nullability {
022 NULL(true, false),
023 NOT_NULL(false, true),
024 UNKNOWN(true, true),
025 IMPOSSIBLE(false, false);
026
027 @NotNull
028 public static Nullability fromFlags(boolean canBeNull, boolean canBeNonNull) {
029 if (!canBeNull && !canBeNonNull) return IMPOSSIBLE;
030 if (!canBeNull && canBeNonNull) return NOT_NULL;
031 if (canBeNull && !canBeNonNull) return NULL;
032 return UNKNOWN;
033 }
034
035 private final boolean canBeNull;
036 private final boolean canBeNonNull;
037
038 Nullability(boolean canBeNull, boolean canBeNonNull) {
039 this.canBeNull = canBeNull;
040 this.canBeNonNull = canBeNonNull;
041 }
042
043 public boolean canBeNull() {
044 return canBeNull;
045 }
046
047 public boolean canBeNonNull() {
048 return canBeNonNull;
049 }
050
051 @NotNull
052 public Nullability refine(@NotNull Nullability other) {
053 switch (this) {
054 case UNKNOWN:
055 return other;
056 case IMPOSSIBLE:
057 return other;
058 case NULL:
059 switch (other) {
060 case NOT_NULL: return NOT_NULL;
061 default: return NULL;
062 }
063 case NOT_NULL:
064 switch (other) {
065 case NULL: return NOT_NULL;
066 default: return NOT_NULL;
067 }
068 }
069 throw new IllegalStateException();
070 }
071
072 @NotNull
073 public Nullability invert() {
074 switch (this) {
075 case NULL:
076 return NOT_NULL;
077 case NOT_NULL:
078 return UNKNOWN;
079 case UNKNOWN:
080 return UNKNOWN;
081 case IMPOSSIBLE:
082 return UNKNOWN;
083 }
084 throw new IllegalStateException();
085 }
086
087 @NotNull
088 public Nullability and(@NotNull Nullability other) {
089 return fromFlags(this.canBeNull && other.canBeNull, this.canBeNonNull && other.canBeNonNull);
090 }
091
092 @NotNull
093 public Nullability or(@NotNull Nullability other) {
094 return fromFlags(this.canBeNull || other.canBeNull, this.canBeNonNull || other.canBeNonNull);
095 }
096 }