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

org.wartremover.test.WartTestTraverser.scala Maven / Gradle / Ivy

package org.wartremover.test

import org.wartremover.LogLevel
import org.wartremover.WartTraverser
import org.wartremover.WartUniverse
import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.core.Contexts.FreshContext
import dotty.tools.dotc.reporting.Diagnostic
import dotty.tools.dotc.reporting.Reporter
import dotty.tools.dotc.interfaces.Diagnostic as DiagnosticInterface
import scala.collection.mutable.ListBuffer
import scala.quoted.Expr
import scala.quoted.Quotes
import scala.quoted.ToExpr
import scala.quoted.Type
import scala.quoted.runtime.impl.QuotesImpl
import scala.reflect.NameTransformer

class WartReporter extends Reporter {
  private val lock = new Object
  private val values = ListBuffer.empty[Diagnostic]
  override def doReport(diagnostic: Diagnostic)(using Context): Unit = {
    lock.synchronized {
      values += diagnostic
    }
  }

  def result: List[Diagnostic] = lock.synchronized {
    values.result()
  }
}

object WartTestTraverser {
  case class Result(errors: List[String], warnings: List[String])
  object Result {
    implicit val toExprInstance: ToExpr[Result] =
      new ToExpr[Result] {
        override def apply(x: Result)(using Quotes) = '{
          Result(
            errors = ${ Expr(x.errors) },
            warnings = ${ Expr(x.warnings) }
          )
        }
      }
  }

  inline def apply[A <: WartTraverser](inline t: A)(inline a: Any): Result = ${ applyImpl[A]('t, 'a) }

  private def applyImpl[A <: WartTraverser: Type](t: Expr[A], expr: Expr[Any])(using q1: Quotes): Expr[Result] = {
    val q2 = q1.asInstanceOf[QuotesImpl]
    val reporter = new WartReporter
    q2.ctx.asInstanceOf[FreshContext].setReporter(reporter)
    val wart = {
      val name = q1.reflect.TypeRepr
        .of[A]
        .classSymbol
        .fold(q1.reflect.TypeRepr.of[A].show + NameTransformer.MODULE_SUFFIX_STRING)(_.fullName.replace("$.", "$"))
      val clazz = Class.forName(name)
      clazz.getField(NameTransformer.MODULE_INSTANCE_NAME).get(null).asInstanceOf[WartTraverser]
    }
    val universe = WartUniverse(
      onlyWarning = false,
      logLevel = LogLevel.Info,
      quotes = q1
    )
    val x = wart.apply(universe)
    val term = x.q.reflect.asTerm(expr)
    x.traverseTree(term)(term.symbol)
    val result1 = reporter.result
    val warnings = result1.collect { case a if a.level() == DiagnosticInterface.WARNING => a.message() }
    val errors = result1.collect { case a if a.level() == DiagnosticInterface.ERROR => a.message() }
    Expr(Result(errors = errors, warnings = warnings))
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy