All Downloads are FREE. Search and download functionalities are using the official Maven repository.

global.namespace.neuron.di.scala.CachingAnnotation.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright © 2016 - 2019 Schlichtherle IT Services
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package global.namespace.neuron.di.scala

// The error checks in this class must match the error chacks in
// `global.namespace.neuron.di.internal.CachingProcessor`!
private trait CachingAnnotation extends MacroAnnotation {

  import c.universe._
  import Flag._

  def apply(inputs: List[Tree]): Tree = {
    val outputs = inputs match {
      case DefDef(mods, name, tparams, vparamss, tpt, rhs) :: rest =>
        val owner = c.internal.enclosingOwner
        if (!owner.annotations.exists(a => isNeuronAnnotation(a.tree))) {
          error("A caching method must be a member of a neuron type...")
          error("... but there is no @Neuron annotation here.")(owner.pos)
        }
        if (mods hasFlag MACRO) {
          error("A caching annotation cannot be applied to a macro.")
        }
        if (mods hasFlag FINAL) {
          error("A caching method cannot be final.")
        }
        if (mods hasFlag PRIVATE) {
          error("A caching method cannot be private.")
        }
        vparamss match {
          case Nil | List(Nil) =>
          case _ =>
            error("A caching method cannot have parameters.")
        }
        c.typecheck(rhs, mode = c.TYPEmode, silent = true).tpe match {
          case TypeRef(_, sym, _)
            if sym == c.symbolOf[Unit] || sym == c.symbolOf[Nothing] =>
            error("A caching method must have a return value.")(tpt.pos)
          case ConstantType(_) =>
            error("A caching method cannot have a constant return type.")(tpt.pos)
          case _ =>
        }
        val caching = {
          val Apply(_, args) = c.prefix.tree
          val Apply(fun, _) = newCachingAnnotationTerm
          Apply(fun, args map {
            case AssignOrNamedArg(lhs@q"value", rhs: Tree) => AssignOrNamedArg(lhs, scala2javaCachingStrategy(rhs))
            case tree => scala2javaCachingStrategy(tree)
          })
        }
        DefDef(mods.mapAnnotations(caching :: _), name, tparams, vparamss, tpt, rhs) :: rest
      case other => other
    }
    q"..$outputs"
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy