Skip to content

Added annotatedWithName to ScalaModule #19

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

Merged
merged 3 commits into from
May 29, 2014
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -15,7 +15,10 @@
*/
package net.codingwell.scalaguice

import com.google.inject._
import javax.inject.Provider

import com.google.inject.Binder
import com.google.inject.name.Names

/**
* Extensions for Guice's binding DSL.
@@ -70,6 +73,7 @@ object BindingExtensions {

class ScalaAnnotatedConstantBindingBuilder(b: AnnotatedConstantBindingBuilder) {
def annotatedWithType[TAnn <: JAnnotation : Manifest] = b annotatedWith cls[TAnn]
def annotatedWithName(name: String) = b annotatedWith Names.named(name)
}

implicit def enrichAnnotatedConstantBindingBuilder(b: AnnotatedConstantBindingBuilder) = {
2 changes: 2 additions & 0 deletions src/main/scala/net/codingwell/scalaguice/KeyExtensions.scala
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
package net.codingwell.scalaguice

import com.google.inject._
import com.google.inject.name.Names

object KeyExtensions {

@@ -25,5 +26,6 @@ object KeyExtensions {
def toKey: Key[T] = Key.get(t)
def annotatedWith(annotation: JAnnotation): Key[T] = Key.get(t, annotation)
def annotatedWith[TAnn <: JAnnotation : Manifest]: Key[T] = Key.get(t, cls[TAnn])
def annotatedWithName(name: String) = annotatedWith(Names.named(name))
}
}
19 changes: 9 additions & 10 deletions src/main/scala/net/codingwell/scalaguice/ScalaModule.scala
Original file line number Diff line number Diff line change
@@ -15,14 +15,14 @@
*/
package net.codingwell.scalaguice

import com.google.inject._
import com.google.inject.{PrivateModule, PrivateBinder, Binder, Scope, AbstractModule}
import binder._
import java.lang.annotation.Annotation
import javax.inject.Provider

/**
* Allows binding via type parameters. Mix into <code>AbstractModule</code>
* (or subclass) to allow using a type parameter instead of
* (or subclass) to allow using a type parameter instead of
* <code>classOf[Foo]</code> or <code>new TypeLiteral[Bar[Foo]] {}</code>.
*
* For example, instead of
@@ -77,7 +77,7 @@ trait ScalaModule extends AbstractModule with InternalModule[Binder] {
//Hack, no easy way to exclude the bind method that gets added to classes inheriting ScalaModule
//So we experimentally figured out how many calls up is the source, so we use that
//Commit 52c2e92f8f6131e4a9ea473f58be3e32cd172ce6 has better class exclusion
protected[this] def binderAccess = super.binder.withSource( (new Throwable).getStackTrace()(4) ) // should not need super
protected[this] def binderAccess = super.binder.withSource((new Throwable).getStackTrace()(4)) // should not need super
}

trait ScalaPrivateModule extends PrivateModule with InternalModule[PrivateBinder] {
@@ -90,11 +90,11 @@ trait ScalaPrivateModule extends PrivateModule with InternalModule[PrivateBinder
//Hack, no easy way to exclude the bind method that gets added to classes inheriting ScalaModule
//So we experimentally figured out how many calls up is the source, so we use that
//Commit 52c2e92f8f6131e4a9ea473f58be3e32cd172ce6 has better class exclusion
protected[this] def binderAccess = super.binder.withSource( (new Throwable).getStackTrace()(5) ) // should not need super
protected[this] def binderAccess = super.binder.withSource((new Throwable).getStackTrace()(5)) // should not need super

protected[this] def expose[T: Manifest] = new ScalaAnnotatedElementBuilder[T] {
val myBinder = binderAccess
val self = myBinder.expose(typeLiteral[T])
val myBinder = binderAccess
val self = myBinder.expose(typeLiteral[T])
}
}

@@ -105,18 +105,17 @@ object ScalaModule {
def in[TAnn <: JAnnotation : Manifest]() = self in cls[TAnn]
}

trait ScalaLinkedBindingBuilder[T] extends ScalaScopedBindingBuilder
with LinkedBindingBuilderProxy[T] { outer =>
trait ScalaLinkedBindingBuilder[T] extends ScalaScopedBindingBuilder with LinkedBindingBuilderProxy[T] { outer =>
def to[TImpl <: T : Manifest] = new ScalaScopedBindingBuilder {
val self = outer.self to typeLiteral[TImpl]
}

def toProvider[TProvider <: Provider[_ <: T] : Manifest] = new ScalaScopedBindingBuilder {
val self = outer.self toProvider typeLiteral[TProvider]
}
}

trait ScalaAnnotatedBindingBuilder[T] extends ScalaLinkedBindingBuilder[T]
with AnnotatedBindingBuilderProxy[T] { outer =>
trait ScalaAnnotatedBindingBuilder[T] extends ScalaLinkedBindingBuilder[T] with AnnotatedBindingBuilderProxy[T] { outer =>
def annotatedWith[TAnn <: JAnnotation : Manifest] = new ScalaLinkedBindingBuilder[T] {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a style perspective, I'd prefer the trait definition to be on a single line. There are no other multi-line definitions in this project, and there are definitely longer lines (in this file even) than the ones created by squashing lines 109-110 and 118-119. So I suggest:

trait ScalaAnnotatedBindingBuilder[T] extends ScalaLinkedBindingBuilder[T] with AnnotatedBindingBuilderProxy[T] {
  outer =>

  def annotatedWith[...

val self = outer.self annotatedWith cls[TAnn]
}
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ import com.google.inject.binder._
import java.lang.annotation.{Annotation => JAnnotation}
import java.lang.reflect.{Constructor => JConstructor}
import net.codingwell.scalaguice.ScalaModule.{ScalaLinkedBindingBuilder, ScalaScopedBindingBuilder}
import com.google.inject.name.Names

/**
* Proxy for [[com.google.inject.binder.ScopedBindingBuilder]]
@@ -66,6 +67,7 @@ trait AnnotatedBindingBuilderProxy[T] extends AnnotatedBindingBuilder[T] with Li

def annotatedWith(annotation: JAnnotation) = newBuilder(self annotatedWith annotation)
def annotatedWith(annotationType: Class[_ <: JAnnotation]) = newBuilder(self annotatedWith annotationType)
def annotatedWithName(name: String) = annotatedWith(Names.named(name))

private[this] def newBuilder(underlying: LinkedBindingBuilder[T]) = new ScalaLinkedBindingBuilder[T] {
val self = underlying
@@ -80,4 +82,5 @@ trait AnnotatedElementBuilderProxy[T] extends AnnotatedElementBuilder with Proxy

def annotatedWith(annotation: JAnnotation) = self annotatedWith annotation
def annotatedWith(annotationType: Class[_ <: JAnnotation]) = self annotatedWith annotationType
def annotatedWithName(name: String) = annotatedWith(Names.named(name))
}
Original file line number Diff line number Diff line change
@@ -15,9 +15,8 @@
*/
package net.codingwell.scalaguice

import com.google.inject.Inject
import com.google.inject.Provider
import com.google.inject.TypeLiteral
import javax.inject.{Provider, Inject, Named}

object Outer {
trait A
@@ -67,3 +66,5 @@ class FooProviderWithJavax extends javax.inject.Provider[Foo] {
def foo() = "foo"
}
}

case class TwoStrings @Inject()(@Named("first") first: String, @Named("second") second: String)
13 changes: 13 additions & 0 deletions src/test/scala/net/codingwell/scalaguice/ScalaModuleSpec.scala
Original file line number Diff line number Diff line change
@@ -111,6 +111,19 @@ class ScalaModuleSpec extends WordSpec with ShouldMatchers {
val sources = messages.iterator.next.getSource
assert( sources.contains("ScalaModuleSpec.scala") )
}

"allow use annotatedWithName" in {
import net.codingwell.scalaguice.BindingExtensions._
val module = new AbstractModule with ScalaModule {
def configure() = {
bind[String].annotatedWithName("first").toInstance("first")
bindConstant().annotatedWithName("second").to("second")
}
}
val twoStrings = Guice.createInjector(module).getInstance(classOf[TwoStrings])
twoStrings.first should be ("first")
twoStrings.second should be ("second")
}
}

}