ex2 typechecks
This commit is contained in:
parent
536148a0e4
commit
9c812f7158
5 changed files with 40 additions and 11 deletions
|
@ -9,3 +9,5 @@ lazy val root = project
|
||||||
scalaVersion := scala3Version,
|
scalaVersion := scala3Version,
|
||||||
libraryDependencies += "org.typelevel" %% "squants" % "1.8.3",
|
libraryDependencies += "org.typelevel" %% "squants" % "1.8.3",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
scalacOptions ++= Seq("-explain", "-explain-types")
|
|
@ -12,6 +12,21 @@ class DynamicShouldBeProperty extends AssertionProperty with Dynamic:
|
||||||
def applyDynamic(fieldName: String)(foo: Any*) = ???
|
def applyDynamic(fieldName: String)(foo: Any*) = ???
|
||||||
end DynamicShouldBeProperty
|
end DynamicShouldBeProperty
|
||||||
|
|
||||||
|
object satisfying:
|
||||||
|
def `===`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean =
|
||||||
|
something => ord.eq(something, toWhat)
|
||||||
|
def `!==`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean =
|
||||||
|
something => ord.ne(something, toWhat)
|
||||||
|
def `<`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean =
|
||||||
|
something => ord.lt(something, toWhat)
|
||||||
|
def `>`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean =
|
||||||
|
something => ord.gt(something, toWhat)
|
||||||
|
def `<=`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean =
|
||||||
|
something => ord.lteq(something, toWhat)
|
||||||
|
def `>=`[T](toWhat: T)(using ord: Ordering[T]): T => Boolean =
|
||||||
|
something => ord.gteq(something, toWhat)
|
||||||
|
end satisfying
|
||||||
|
|
||||||
class BePropertyTypeProvider[T](val subject: T) extends Selectable:
|
class BePropertyTypeProvider[T](val subject: T) extends Selectable:
|
||||||
def selectDynamic(fieldName: String): AssertionProperty = ???
|
def selectDynamic(fieldName: String): AssertionProperty = ???
|
||||||
def applyDynamic(fieldName: String)(foo: Any*): AssertionProperty = ???
|
def applyDynamic(fieldName: String)(foo: Any*): AssertionProperty = ???
|
||||||
|
|
|
@ -40,6 +40,8 @@ case class Box(label: String, weight: Mass, price: Money)
|
||||||
// assert(List(1,2,3).nonEmpty)
|
// assert(List(1,2,3).nonEmpty)
|
||||||
List(1, 2, 3) should be.nonEmpty
|
List(1, 2, 3) should be.nonEmpty
|
||||||
|
|
||||||
|
(person should have) age ((x: Int) => x == 10)
|
||||||
|
|
||||||
// New syntax for `be` with type provider
|
// New syntax for `be` with type provider
|
||||||
// either adult is a method with a dummy Unit parameter
|
// either adult is a method with a dummy Unit parameter
|
||||||
person should be_ adult()
|
person should be_ adult()
|
||||||
|
@ -47,13 +49,13 @@ case class Box(label: String, weight: Mass, price: Money)
|
||||||
(person should be_).adult
|
(person should be_).adult
|
||||||
|
|
||||||
/* should have assertions */
|
/* should have assertions */
|
||||||
// assert(List(1).head == 1, ...)
|
// // assert(List(1).head == 1, ...)
|
||||||
List(1) should have head 1
|
// List(1) should have head 1
|
||||||
// assert(box.weight == 30.kg, ...)
|
// // assert(box.weight == 30.kg, ...)
|
||||||
box should have weight 30.kg
|
// box should have weight 30.kg
|
||||||
// assert(person.age == 0x29, ...)
|
// // assert(person.age == 0x29, ...)
|
||||||
person should have age 0x29
|
// person should have age 0x29
|
||||||
List(2, 3) should have tail List(3)
|
// List(2, 3) should have tail List(3)
|
||||||
3.i + 1 should have re 1.0
|
// 3.i + 1 should have re 1.0
|
||||||
|
|
||||||
end assertionsExample
|
end assertionsExample
|
||||||
|
|
|
@ -53,7 +53,7 @@ object ShouldBeTypeProvider:
|
||||||
members
|
members
|
||||||
)
|
)
|
||||||
|
|
||||||
println(refinedType)
|
// println(refinedType)
|
||||||
|
|
||||||
// This is the way to extract a (reflection) type to a
|
// This is the way to extract a (reflection) type to a
|
||||||
// type that can be used in some quoted code.
|
// type that can be used in some quoted code.
|
||||||
|
|
|
@ -25,6 +25,14 @@ object ShouldHaveTypeProvider:
|
||||||
// The type of the field, or the return type of the method.
|
// The type of the field, or the return type of the method.
|
||||||
val fieldTypeRepr = subjectTypeRepr.memberType(symbol).widen
|
val fieldTypeRepr = subjectTypeRepr.memberType(symbol).widen
|
||||||
|
|
||||||
|
// hack to get the equivalent of `TypeRepr.of[Function1[?, ?]]` (i.e. an arity-1 function type constructor).
|
||||||
|
// Getting it as is returns an applied type with useless bounds (Nothing to Any), and the returned TypeRepr,
|
||||||
|
// if re-applied to some `I` input type and `O` output type would be incompatible with `TypeRepr.of[I => O]` for
|
||||||
|
// some reason
|
||||||
|
val function1TypeConstructor = AppliedType.unapply(TypeRepr.of[? => ?].asInstanceOf[AppliedType])._1
|
||||||
|
|
||||||
|
val appliedType = AppliedType(function1TypeConstructor, List(fieldTypeRepr, TypeRepr.of[Boolean]))
|
||||||
|
|
||||||
// Generates the "type" of the method to be generated for the refinement.
|
// Generates the "type" of the method to be generated for the refinement.
|
||||||
// The first parameter is the list of arguments, the second is a function returning
|
// The first parameter is the list of arguments, the second is a function returning
|
||||||
// the type of arguments, and the third one is a function returning the return type
|
// the type of arguments, and the third one is a function returning the return type
|
||||||
|
@ -33,9 +41,9 @@ object ShouldHaveTypeProvider:
|
||||||
// _ => List(fieldTypeRepr) returns a list with the type of arg;
|
// _ => List(fieldTypeRepr) returns a list with the type of arg;
|
||||||
// _ => TypeRepr.of[AssertionProperty] returns the (reflection) type of the method.
|
// _ => TypeRepr.of[AssertionProperty] returns the (reflection) type of the method.
|
||||||
val methodType = MethodType(List("arg"))(
|
val methodType = MethodType(List("arg"))(
|
||||||
_ => List(fieldTypeRepr),
|
_ => List(appliedType),
|
||||||
_ => TypeRepr.of[AssertionProperty]
|
_ => TypeRepr.of[AssertionProperty]
|
||||||
)
|
).widen
|
||||||
// returns the refinement of currentTypeRepr -
|
// returns the refinement of currentTypeRepr -
|
||||||
// symbol.name is the name of the method,
|
// symbol.name is the name of the method,
|
||||||
// methodType is its type.
|
// methodType is its type.
|
||||||
|
@ -71,6 +79,8 @@ object ShouldHaveTypeProvider:
|
||||||
fields ++ arityZeroMethods
|
fields ++ arityZeroMethods
|
||||||
)
|
)
|
||||||
|
|
||||||
|
println(refinedType.show)
|
||||||
|
|
||||||
// This is the way to extract a (reflection) type to a
|
// This is the way to extract a (reflection) type to a
|
||||||
// type that can be used in some quoted code.
|
// type that can be used in some quoted code.
|
||||||
// it's the equivalent of .asExpr for expressions,
|
// it's the equivalent of .asExpr for expressions,
|
||||||
|
|
Loading…
Reference in a new issue