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

izumi.reflect.dottyreflection.DbInspector.scala Maven / Gradle / Ivy

There is a newer version: 2.3.10
Show newest version
package izumi.reflect.dottyreflection

import izumi.reflect.internal.fundamentals.collections.IzCollections.toRich
import izumi.reflect.macrortti.LightTypeTag.ParsedLightTypeTag.SubtypeDBs
import izumi.reflect.macrortti.LightTypeTagRef
import izumi.reflect.macrortti.LightTypeTagRef._
import scala.collection.mutable

import scala.quoted._

abstract class DbInspector(protected val shift: Int) extends InspectorBase {
  self =>

  // @formatter:off
  import qctx.reflect._
  private lazy val inspector = new Inspector(0) { val qctx: DbInspector.this.qctx.type = DbInspector.this.qctx }
  // @formatter:on

  def makeUnappliedInheritanceDb[T <: AnyKind: Type]: Map[NameReference, Set[NameReference]] = {
    val tpe = TypeRepr.of[T].dealias

    val allReferenceComponents = {
      allTypeReferences(tpe)
        .flatMap(breakRefinement)
    }

    val baseclassReferences = allReferenceComponents.flatMap {
      i =>
        val allbases = tpeBases(i).filter(!_._takesTypeArgs)
        val targetRef = {
          val tpef = i.dealias.simplified._resultType
          inspector.makeNameReferenceFromSymbol(tpef.typeSymbol)
        }
        allbases.map(b => (targetRef, inspector.makeNameReferenceFromSymbol(b.typeSymbol)))
    }

    baseclassReferences
      .toMultimap
      .map {
        case (t, parents) =>
          t -> parents.filterNot(_ == t)
      }
      .filterNot(_._2.isEmpty)
  }

  private def allTypeReferences(tpe0: TypeRepr): collection.Set[TypeRepr] = {
    val inh = mutable.HashSet.empty[TypeRepr]

    def extract(t: TypeRepr): Unit = {
      val resType = t.dealias.simplified._resultType
      inh += resType

      val next = t._typeArgs.iterator ++ resType._typeArgs.iterator
      next.foreach(extract)
    }

    inh += tpe0
    extract(tpe0)
    inh
  }

  private def breakRefinement(tpe0: TypeRepr): collection.Set[TypeRepr] = {
    val tpes = mutable.HashSet.empty[TypeRepr]

    def go(t: TypeRepr): Unit = t match {
      case tpe: AndOrType =>
        go(tpe.left)
        go(tpe.right)
      case _ =>
        tpes += t
    }

    go(tpe0)
    tpes
  }

  private def tpeBases(tpe0: TypeRepr): List[TypeRepr] = {
    val tpef = tpe0.dealias.simplified._resultType
    val higherBases = tpef.baseClasses
    val onlyParameterizedBases = {
      higherBases
        .filterNot {
          s =>
          !s.isType || (s.tree match {
            case tt: TypeTree => tt.tpe =:= tpef
            case _ => false
          })
        }
        .map(s => tpef.baseType(s))
    }

    val allbases = onlyParameterizedBases.filterNot(_ =:= tpef)
    allbases
  }

  extension (t: TypeRepr) {
    private def _resultType: TypeRepr = {
      t match {
        case l: LambdaType => l.resType
        case _ => t
      }
    }

    private def _typeArgs: List[TypeRepr] = {
      t match {
        case a: AppliedType => a.args
        case _ => Nil
      }
    }

    private def _takesTypeArgs: Boolean = {
      t match {
        case l: LambdaType => true
        case _ => false
      }
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy