@NotNull
  static Direction fromInt(int directionKey) {
    if (directionKey < CONCRETE_DIRECTIONS_OFFSET) {
      return ourConcreteDirections.get(directionKey);
    }
    int paramKey = directionKey - CONCRETE_DIRECTIONS_OFFSET;
    int paramId = paramKey / DIRECTIONS_PER_PARAM_ID;
    int subDirectionId = paramKey % DIRECTIONS_PER_PARAM_ID;
    // 0 - 1 - @NotNull, @Nullable, parameter
    if (subDirectionId < IN_OUT_OFFSET) {
      return new In(paramId, subDirectionId == 1);
    }
    if (subDirectionId < IN_THROW_OFFSET) {
      int valueId = subDirectionId - IN_OUT_OFFSET;
      return new InOut(paramId, Value.values()[valueId]);
    }
    int valueId = subDirectionId - IN_THROW_OFFSET;
    return new InThrow(paramId, Value.values()[valueId]);
  }
@NotNull
  static Direction fromInt(int directionKey)