diff options
author | Jon Pretty <jon.pretty@propensive.com> | 2017-11-30 20:45:22 +0000 |
---|---|---|
committer | Jon Pretty <jon.pretty@propensive.com> | 2017-11-30 20:45:22 +0000 |
commit | fba0c1cb94d4d67c48db8fb283c5dc1fedbf215a (patch) | |
tree | 25158dcdef93b1e7a58c961e3e20cc54c02129c7 /core/shared/src/main | |
parent | e1bb3f9c514a2b473076e5fd98b87c26885cd223 (diff) | |
parent | 7df3e96d3137e78813d5bdcb4daac8531db6b860 (diff) | |
download | magnolia-fba0c1cb94d4d67c48db8fb283c5dc1fedbf215a.tar.gz magnolia-fba0c1cb94d4d67c48db8fb283c5dc1fedbf215a.tar.bz2 magnolia-fba0c1cb94d4d67c48db8fb283c5dc1fedbf215a.zip |
Merge branch 'patch-1' of https://github.com/shadaj/magnolia
Diffstat (limited to 'core/shared/src/main')
-rw-r--r-- | core/shared/src/main/scala/magnolia.scala | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/core/shared/src/main/scala/magnolia.scala b/core/shared/src/main/scala/magnolia.scala index a748561..f55dfa7 100644 --- a/core/shared/src/main/scala/magnolia.scala +++ b/core/shared/src/main/scala/magnolia.scala @@ -201,6 +201,56 @@ object Magnolia { } } + // From Shapeless: https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/generic.scala#L698 + // Cut-n-pasted (with most original comments) and slightly adapted from + // https://github.com/scalamacros/paradise/blob/c14c634923313dd03f4f483be3d7782a9b56de0e/plugin/src/main/scala/org/scalamacros/paradise/typechecker/Namers.scala#L568-L613 + def patchedCompanionSymbolOf(original: c.Symbol): c.Symbol = { + // see https://github.com/scalamacros/paradise/issues/7 + // also see https://github.com/scalamacros/paradise/issues/64 + + val global = c.universe.asInstanceOf[scala.tools.nsc.Global] + val typer = c.asInstanceOf[scala.reflect.macros.runtime.Context].callsiteTyper.asInstanceOf[global.analyzer.Typer] + val ctx = typer.context + val owner = original.owner + + import global.analyzer.Context + + original.companion.orElse { + import global.{ abort => aabort, _ } + implicit class PatchedContext(ctx: Context) { + trait PatchedLookupResult { def suchThat(criterion: Symbol => Boolean): Symbol } + def patchedLookup(name: Name, expectedOwner: Symbol) = new PatchedLookupResult { + override def suchThat(criterion: Symbol => Boolean): Symbol = { + var res: Symbol = NoSymbol + var ctx = PatchedContext.this.ctx + while (res == NoSymbol && ctx.outer != ctx) { + // NOTE: original implementation says `val s = ctx.scope lookup name` + // but we can't use it, because Scope.lookup returns wrong results when the lookup is ambiguous + // and that triggers https://github.com/scalamacros/paradise/issues/64 + val s = { + val lookupResult = ctx.scope.lookupAll(name).filter(criterion).toList + lookupResult match { + case Nil => NoSymbol + case List(unique) => unique + case _ => aabort(s"unexpected multiple results for a companion symbol lookup for $original#{$original.id}") + } + } + if (s != NoSymbol && s.owner == expectedOwner) + res = s + else + ctx = ctx.outer + } + res + } + } + } + ctx.patchedLookup(original.asInstanceOf[global.Symbol].name.companionName, owner.asInstanceOf[global.Symbol]).suchThat(sym => + (original.isTerm || sym.hasModuleFlag) && + (sym isCoDefinedWith original.asInstanceOf[global.Symbol]) + ).asInstanceOf[c.universe.Symbol] + } + } + def directInferImplicit(genericType: c.Type, typeConstructor: Type): Option[Typeclass] = { val genericTypeName: String = genericType.typeSymbol.name.decodedName.toString.toLowerCase @@ -288,7 +338,7 @@ object Magnolia { val preAssignments = caseParams.map(_.typeclass) val defaults = if (!isValueClass) { - val caseClassCompanion = genericType.companion + val caseClassCompanion = patchedCompanionSymbolOf(genericType.typeSymbol).asModule.info // If a companion object is defined with alternative apply methods // it is needed get all the alternatives |