// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection.dataFlow;

import com.intellij.codeInsight.Nullability;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * Represents a value nullability within DFA. Unlike {@link Nullability} may additionally hold a {@link #FLUSHED} value
 * which means that non-stable variable declared as Nullable was checked for nullity and flushed afterwards (e.g. by unknown method call),
 * so we are unsure about its nullability anymore.
 *
 * @see DfaFactType#NULLABILITY
 */
public enum DfaNullability {
  NULL("Null", "null", Nullability.NULLABLE),
  NULLABLE("Nullable", "nullable", Nullability.NULLABLE),
  NOT_NULL("Not-null", "non-null", Nullability.NOT_NULL),
  UNKNOWN("Unknown", "", Nullability.UNKNOWN),
  FLUSHED("Flushed", "", Nullability.UNKNOWN);

  private final @NotNull String myInternalName;
  private final @NotNull String myPresentationalName;
  private final @NotNull Nullability myNullability;

  DfaNullability(@NotNull String internalName, @NotNull String presentationalName, @NotNull Nullability nullability) {
    myInternalName = internalName;
    myPresentationalName = presentationalName;
    myNullability = nullability;
  }

  @NotNull
  public String getInternalName() {
    return myInternalName;
  }

  @NotNull
  public String getPresentationName() {
    return myPresentationalName;
  }

  public static boolean isNullable(DfaFactMap map) {
    return toNullability(map.get(DfaFactType.NULLABILITY)) == Nullability.NULLABLE;
  }

  public static boolean isNotNull(DfaFactMap map) {
    return map.get(DfaFactType.NULLABILITY) == NOT_NULL;
  }

  @NotNull
  public static Nullability toNullability(@Nullable DfaNullability dfaNullability) {
    return dfaNullability == null ? Nullability.UNKNOWN : dfaNullability.myNullability;
  }

  @NotNull
  public static DfaNullability fromNullability(@NotNull Nullability nullability) {
    switch (nullability) {
      case NOT_NULL:
        return NOT_NULL;
      case NULLABLE:
        return NULLABLE;
      case UNKNOWN:
        return UNKNOWN;
    }
    throw new IllegalStateException("Unknown nullability: "+nullability);
  }
}

@@ -397,237 +397,297 @@
 may 
-additionally hold a %7B@link #FLUSHED%7D value%0A * which means that non-stable variable declared as Nullable was checked for nullity and flushed afterwards (e.g. by unknown method call),%0A * so we are unsure about it
+have more fine-grained%0A * values useful during the DFA. If you have a DfaNullability value (e.g. from %7B@link CommonDataflow%7D),%0A * and want to check if it's nullable, or not, it's advised to convert it to %7B@link Nullability%7D first,%0A * as more values could be introduced to thi
 s 
+e
 nu
-llability anymo
+m in futu
 re.%0A
@@ -754,16 +754,53 @@
 ility %7B%0A
+  /**%0A   * Means: exactly null%0A   */%0A
   NULL(%22
@@ -953,16 +953,16 @@
 _NULL),%0A
-
   UNKNOW
@@ -1000,16 +1000,212 @@
 KNOWN),%0A
+  /**%0A   * Means: non-stable variable declared as Nullable was checked for nullity and flushed afterwards (e.g. by unknown method call),%0A   * so we are unsure about its nullability anymore.%0A   */%0A
   FLUSHE

update JavaDoc