-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement wireResource for scala 2 #175
Conversation
One more naming idea: |
@adamw actually in this case |
Hmm well but Another candidate: |
And yes, sure, we do want to support instances wrapped in effects :) |
Looks good :) There's a lot of tests to add, though. Maybe I'll just add them and then we'll have sth like TDD ;) One thing that we'll need to decide is how to re-use instances. Right now we are re-using anything that is created by a resource - and this makes sense. When creating an instance of a class, do we want to re-use it? That is, should the following (assuming not only case class A
case class B(a1: A, a2: A)
val b = wireX[B] generate either (1): val b = B(A(), A()) or (2): val b = {
val x = A()
B(x, x)
} Here it doesn't make a difference, but maybe for some cases it does make a difference whether a dependency is a singleton and re-used, or not. Probably (1) is the better default, as it follows other DI frameworks where "dependent" scope is the default. And we could achieve singleton by explicitly passing in the instance. So I guess that's solved, or do you have another opinion? :) |
macrosCatsEffectTests/src/test/resources/test-cases/simpleMultiLevelProvidedParameter.success
Outdated
Show resolved
Hide resolved
macrosCatsEffectTests/src/test/resources/test-cases/simpleMultiLevelNoParameters.success
Outdated
Show resolved
Hide resolved
6b43819
to
ee50b16
Compare
ee50b16
to
42b5eea
Compare
build.sbt
Outdated
@@ -167,6 +171,21 @@ lazy val macrosAkkaTests = projectMatrix | |||
.dependsOn(macrosAkka, testUtil) | |||
.jvmPlatform(scalaVersions = scala2) | |||
|
|||
lazy val macrosCatsEffect = projectMatrix |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd rename this to macrosAutoCats
, and similarly, the package to .auto.cats
. The current package name is way too long ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about .auto.catssupport
? .auto.cats
clashes with the cats
package
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm it conflicts, how? I guess import macwire.auto.cats._
or import macwire.auto.cats.autowire
should work just fine? I've got a tapir.integ.cats
package and as far as I know it works just fine ;)
We can come up with a different name, though ... however catssupport
looks cumbersome. Maybe .autocats
? ;)
!name.startsWith("java.lang.") && !name.startsWith("scala.") | ||
} | ||
|
||
def findeProvider(tpe: Type): Option[Tree] = findInstance(tpe) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[typo] -> findProvider
README.md
Outdated
In case you need to build an instance from some particular instances and factory methods it's recommended to use `autowire`. This feature is intended to interpolate with fp libraries (currently we support `cats`). | ||
|
||
`autowire` takes as an argument a list which may contain: | ||
* instances (e.g. `new A()`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think values
would be more correct. Any value will do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact ... do we have tests, that you can use a sub-type, where the dependency is of a super-type? E.g. I declare that I need a dependency of type trait A
, but I provide a value of type class AA extends A
. Same for resources etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now we don't have tests for this case and we do not currently support it. I will add it to todo list
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe let's keep the todo as issues :) I've created #183 for this
* factory methods (e.g. `C.create _`) | ||
* cats.effect.Resource (e.g. `cats.effect.Resource[IO].pure(new A())`) | ||
* cats.effect.IO (e.g. `cats.effect.IO.pure(new A())`) | ||
Based on the given list it creates a set of available instances and performs `wireRec` bypassing the instances search phase. The result of the wiring is always wrapped in `cats.effect.Resource`. For example: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if multiple values for a given type are found? E.g. through a value and a resource? I think it should be an error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently it searches for instances, then resources, then effects. I agree that is should fail in such case, also it may be worth to check if all passed instances/resources/factory methods are used in the generated code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
val theDatabaseAccess: Resource[IO, DatabaseAccess] = Resource.pure(new DatabaseAccess()) | ||
|
||
val theUserStatusReader: Resource[IO, UserStatusReader] = autowire[UserStatusReader](theDatabaseAccess) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️ this looks nice :)
Actually I'm still not sure if we want to support no parameters constructors. import cats.effect._
import cats.effect.unsafe.implicits.global
class MutableConfig() {
var port: Option[Int] = None
var host: Option[String] = None
}
class Service(cfg: MutableConfig) {
println(s"[${cfg.host}]:[${cfg.port}]")
}
object Main extends App {
def loadConfig(): Resource[IO, MutableConfig] = Resource.pure {
val mc = new MutableConfig()
mc.host = Some("xyz")
mc.port = Some(8080)
mc
}
val cfg = loadConfig()
val service = autowire[Service]()
service.allocated.unsafeRunSync()._1
} it works and prints |
2bc32fb
to
53cdea2
Compare
No description provided.