mirror of
https://github.com/Eyre-S/Coeur-Morny-Cono.git
synced 2024-11-22 11:14:55 +08:00
fix EventEnv stackTrack problem, new method for GivenContext
This commit is contained in:
parent
6b961a3de3
commit
9574dd299b
@ -8,7 +8,7 @@ object MornyConfiguration {
|
|||||||
val MORNY_CODE_STORE = "https://github.com/Eyre-S/Coeur-Morny-Cono"
|
val MORNY_CODE_STORE = "https://github.com/Eyre-S/Coeur-Morny-Cono"
|
||||||
val MORNY_COMMIT_PATH = "https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s"
|
val MORNY_COMMIT_PATH = "https://github.com/Eyre-S/Coeur-Morny-Cono/commit/%s"
|
||||||
|
|
||||||
val VERSION = "2.0.0-alpha5"
|
val VERSION = "2.0.0-alpha6"
|
||||||
val VERSION_DELTA: Option[String] = None
|
val VERSION_DELTA: Option[String] = None
|
||||||
val CODENAME = "guanggu"
|
val CODENAME = "guanggu"
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ import cc.sukazyo.messiva.utils.StackUtils
|
|||||||
import com.pengrad.telegrambot.model.Update
|
import com.pengrad.telegrambot.model.Update
|
||||||
|
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
import scala.reflect.{classTag, ClassTag}
|
|
||||||
|
|
||||||
class EventEnv (
|
class EventEnv (
|
||||||
|
|
||||||
@ -29,11 +28,11 @@ class EventEnv (
|
|||||||
|
|
||||||
//noinspection UnitMethodIsParameterless
|
//noinspection UnitMethodIsParameterless
|
||||||
def setEventOk: Unit =
|
def setEventOk: Unit =
|
||||||
_status += State.OK(StackUtils.getStackTrace(1)(1))
|
_status += State.OK(StackUtils.getStackTrace(1).head)
|
||||||
|
|
||||||
//noinspection UnitMethodIsParameterless
|
//noinspection UnitMethodIsParameterless
|
||||||
def setEventCanceled: Unit =
|
def setEventCanceled: Unit =
|
||||||
_status += State.CANCELED(StackUtils.getStackTrace(1)(1))
|
_status += State.CANCELED(StackUtils.getStackTrace(1).head)
|
||||||
|
|
||||||
def state: State|Null =
|
def state: State|Null =
|
||||||
_status.lastOption match
|
_status.lastOption match
|
||||||
|
@ -1,9 +1,55 @@
|
|||||||
package cc.sukazyo.cono.morny.util
|
package cc.sukazyo.cono.morny.util
|
||||||
|
|
||||||
|
import cc.sukazyo.cono.morny.util.GivenContext.ContextNotGivenException
|
||||||
|
|
||||||
import scala.annotation.targetName
|
import scala.annotation.targetName
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
import scala.reflect.{classTag, ClassTag}
|
import scala.reflect.{classTag, ClassTag}
|
||||||
|
|
||||||
|
object GivenContext {
|
||||||
|
class ContextNotGivenException extends NoSuchElementException
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A mutable collection that can store(provide) any typed value and read(use/consume) that value by type.
|
||||||
|
*
|
||||||
|
* ## Simple Guide
|
||||||
|
* {{{
|
||||||
|
* val cxt = GivenContext()
|
||||||
|
* class BaseClass {}
|
||||||
|
* class MyImplementation extends BaseClass {}
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* cxt.provide(true) // this provides a Boolean
|
||||||
|
* cxt.provide[BaseClass](new MyImplementation()) // although this object is of type MyImplementation, but it is stored
|
||||||
|
* // as BaseClass so you can (and actually can only) read it using BaseClass
|
||||||
|
* cxt << "string"
|
||||||
|
* cxt << classOf[Int] -> 1 // you can also manually set the stored type using this method
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* cxt >> { (i: Int) => println(i) } || { println("no Int data in the context") }
|
||||||
|
* val bool =
|
||||||
|
* cxt.use[String, Boolean] { s => println(s); true } || { false } // when using .use, the return value must declared
|
||||||
|
* cxt.consume[String] { s => println(s) } // you can use .consume if you don't care the return
|
||||||
|
* // and this will return a cxt.ConsumeResult[Any]
|
||||||
|
* val cxtResultOpt = // use toOption if you do not want fallback calculation
|
||||||
|
* cxt.use[Int, String](int => s"int: $int").toOption // this returns Option[String]
|
||||||
|
* val cxtResultOpt2 =
|
||||||
|
* cxt >> { (int: Int) => s"int: $int" } |? // this returns Option[String] too
|
||||||
|
* // cxt >> { (int: Int) => cxt >> { (str: String) => { str + int } } } |? // this below is not good to use due to .flatUse
|
||||||
|
* // is not supported yet. It will return a
|
||||||
|
* // cxt.ConsumeResult[Option[String]] which is very bad
|
||||||
|
*
|
||||||
|
* try { // for now, you can use this way to use multiple data
|
||||||
|
* val int = cxt.use[Int] // this returns CxtOption[Int] which is Either[ContextNotGivenException, Int]
|
||||||
|
* .toTry.get
|
||||||
|
* val str = cxt >> classOf[String] match // this >> returns the same with the .use above
|
||||||
|
* case Right(s) => s
|
||||||
|
* case Left(err) => throw err // this is ContextNotGivenException
|
||||||
|
* val bool = cxt >!> classOf[Boolean] // the easier way to do the above
|
||||||
|
* } catch case e: ContextNotGivenException => // if any of the above val is not available, it will catch the exception
|
||||||
|
* e.printStackTrace()
|
||||||
|
* }}}
|
||||||
|
*/
|
||||||
class GivenContext {
|
class GivenContext {
|
||||||
|
|
||||||
private type ImplicitsMap [T <: Any] = mutable.HashMap[Class[?], T]
|
private type ImplicitsMap [T <: Any] = mutable.HashMap[Class[?], T]
|
||||||
@ -11,19 +57,31 @@ class GivenContext {
|
|||||||
private val variables: ImplicitsMap[Any] = mutable.HashMap.empty
|
private val variables: ImplicitsMap[Any] = mutable.HashMap.empty
|
||||||
private val variablesWithOwner: ImplicitsMap[ImplicitsMap[Any]] = mutable.HashMap.empty
|
private val variablesWithOwner: ImplicitsMap[ImplicitsMap[Any]] = mutable.HashMap.empty
|
||||||
|
|
||||||
def provide (i: Any): Unit =
|
def provide [T: ClassTag] (i: T): Unit =
|
||||||
variables += (i.getClass -> i)
|
variables += (classTag[T].runtimeClass -> i)
|
||||||
def << (i: Any): Unit =
|
def << [T: ClassTag] (is: (Class[T], T)): Unit =
|
||||||
this.provide(i)
|
val (_, i) = is
|
||||||
|
this.provide[T](i)
|
||||||
|
def << [T: ClassTag] (i: T): Unit =
|
||||||
|
this.provide[T](i)
|
||||||
|
|
||||||
def >>[T: ClassTag] (consumer: T => Unit): ConsumeResult =
|
private type CxtOption[T] = Either[ContextNotGivenException, T]
|
||||||
this.use[T](consumer)
|
def use [T: ClassTag]: CxtOption[T] =
|
||||||
def use [T: ClassTag] (consumer: T => Unit): ConsumeResult =
|
|
||||||
variables get classTag[T].runtimeClass match
|
variables get classTag[T].runtimeClass match
|
||||||
case Some(i) => consumer(i.asInstanceOf[T]); ConsumeResult(true)
|
case Some(i) => Right(i.asInstanceOf[T])
|
||||||
case None => ConsumeResult(false)
|
case None => Left(ContextNotGivenException())
|
||||||
def consume [T: ClassTag] (consume: T => Unit): ConsumeResult =
|
def use [T: ClassTag, U] (consumer: T => U): ConsumeResult[U] =
|
||||||
this.use[T](consume)
|
this.use[T] match
|
||||||
|
case Left(_) => ConsumeFailed[U]()
|
||||||
|
case Right(i) => ConsumeSucceed[U](consumer(i))
|
||||||
|
def >> [T: ClassTag] (t: Class[T]): CxtOption[T] =
|
||||||
|
this.use[T]
|
||||||
|
def >!> [T: ClassTag] (t: Class[T]): T =
|
||||||
|
this.use[T].toTry.get
|
||||||
|
def >>[T: ClassTag, U] (consumer: T => U): ConsumeResult[U] =
|
||||||
|
this.use[T,U](consumer)
|
||||||
|
def consume [T: ClassTag] (consume: T => Any): ConsumeResult[Any] =
|
||||||
|
this.use[T,Any](consume)
|
||||||
|
|
||||||
@targetName("ownedBy")
|
@targetName("ownedBy")
|
||||||
def / [O: ClassTag] (owner: O): OwnedContext[O] =
|
def / [O: ClassTag] (owner: O): OwnedContext[O] =
|
||||||
@ -33,26 +91,46 @@ class GivenContext {
|
|||||||
|
|
||||||
class OwnedContext [O: ClassTag] {
|
class OwnedContext [O: ClassTag] {
|
||||||
|
|
||||||
def provide (i: Any): Unit =
|
def provide [T: ClassTag] (i: T): Unit =
|
||||||
(variablesWithOwner getOrElseUpdate (classTag[O].runtimeClass, mutable.HashMap.empty))
|
(variablesWithOwner getOrElseUpdate (classTag[O].runtimeClass, mutable.HashMap.empty))
|
||||||
.addOne(i.getClass -> i)
|
.addOne(classTag[T].runtimeClass -> i)
|
||||||
def << (i: Any): Unit =
|
def << [T: ClassTag] (is: (Class[T], T)): Unit =
|
||||||
this.provide(i)
|
val (_, i) = is
|
||||||
|
this.provide[T](i)
|
||||||
|
def << [T: ClassTag] (i: T): Unit =
|
||||||
|
this.provide[T](i)
|
||||||
|
|
||||||
def >> [T: ClassTag] (consumer: T => Unit): ConsumeResult =
|
def use [T: ClassTag]: CxtOption[T] =
|
||||||
this.use[T](consumer)
|
|
||||||
def use [T: ClassTag] (consumer: T => Unit): ConsumeResult =
|
|
||||||
variablesWithOwner(classTag[O].runtimeClass) get classTag[T].runtimeClass match
|
variablesWithOwner(classTag[O].runtimeClass) get classTag[T].runtimeClass match
|
||||||
case Some(i) => consumer(i.asInstanceOf[T]); ConsumeResult(true)
|
case Some(i) => Right(i.asInstanceOf[T])
|
||||||
case None => ConsumeResult(false)
|
case None => Left(ContextNotGivenException())
|
||||||
|
def use [T: ClassTag, U] (consumer: T => U): ConsumeResult[U] =
|
||||||
|
use[T] match
|
||||||
|
case Left(_) => ConsumeFailed[U]()
|
||||||
|
case Right(i) => ConsumeSucceed[U](consumer(i))
|
||||||
|
def >> [T: ClassTag] (t: Class[T]): CxtOption[T] =
|
||||||
|
this.use[T]
|
||||||
|
def >!> [T: ClassTag] (t: Class[T]): T =
|
||||||
|
this.use[T].toTry.get
|
||||||
|
def >> [T: ClassTag, U] (consumer: T => U): ConsumeResult[U] =
|
||||||
|
this.use[T,U](consumer)
|
||||||
|
def consume [T: ClassTag] (consume: T => Any): ConsumeResult[Any] =
|
||||||
|
this.use[T,Any](consume)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConsumeResult (success: Boolean) {
|
trait ConsumeResult[U]:
|
||||||
|
def toOption: Option[U]
|
||||||
|
def |? : Option[U] = toOption
|
||||||
@targetName("orElse")
|
@targetName("orElse")
|
||||||
def || (processor: => Unit): Unit = {
|
def || (processor: =>U): U
|
||||||
if !success then processor
|
private class ConsumeSucceed[U] (succeedValue: U) extends ConsumeResult[U]:
|
||||||
}
|
override def toOption: Option[U] = Some(succeedValue)
|
||||||
}
|
@targetName("orElse")
|
||||||
|
override def || (processor: => U): U = succeedValue
|
||||||
|
private class ConsumeFailed[U] extends ConsumeResult[U]:
|
||||||
|
override def toOption: Option[U] = None
|
||||||
|
@targetName("orElse")
|
||||||
|
override def || (processor: => U): U = processor
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user