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

codacy.events.ScalaCompilerPlugin.scala Maven / Gradle / Ivy

There is a newer version: 12.2.5_akka_2.6_circe_0.14
Show newest version
package codacy.events

import scala.concurrent.Future
import scala.tools.nsc.plugins.{Plugin, PluginComponent}
import scala.tools.nsc.{Global, Phase}

class UnpublishedEventsPlugin(override val global: Global) extends Plugin {
  override val name: String = "codacy-unpublished-events-plugin"
  override val description: String =
    "a compiler plugin that checks code for events that aren't published"
  override val components: List[PluginComponent] = List(new ScalaCompilerPluginComponent(global))
}

class ScalaCompilerPluginComponent(val global: Global) extends PluginComponent {

  import global._

  override val phaseName = "find-unpublished-events"
  override val runsAfter = List("typer")

  override def newPhase(prev: Phase): Phase = new StdPhase(prev) {
    override def apply(unit: global.CompilationUnit): Unit =
      util.Try(typeOf[Event]).foreach { eventTpe =>
        def isApplyOfTpe(tree: Tree, targetTpe: Type): Boolean = tree match {
          case _: Apply =>
            Option(tree.tpe).exists(tpe => (!tpe.=:=(typeOf[Nothing])) && tpe <:< targetTpe)
          case _ => false
        }

        def isEventCtrCall(tree: Tree): Boolean = isApplyOfTpe(tree, eventTpe)

        def isEventPublish(tree: Tree): Boolean =
          isApplyOfTpe(tree, typeOf[Future[PublishedEvent]])

        def filterPublished(remainingEventTrees: Set[Tree], eventPublishTree: Tree): Set[Tree] = {
          eventPublishTree
            .find(remainingEventTrees.contains)
            .map(remainingEventTrees - _)
            .getOrElse(remainingEventTrees)
        }

        // 1) find all events
        // 2) find all published events
        // 3) tick all events that are contained in 2)
        // 4) warn about the others
        val events = unit.body.filter(isEventCtrCall)
        if (events.nonEmpty) {
          unit.body
            .filter(isEventPublish)
            .foldLeft(events.toSet)(filterPublished)
            .foreach(tree => warning(tree.pos, "looks like an event that lacks publishing"))
        }
      }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy