<commit_before>package dotty.tools.dotc
package transform

import core._
import Names._
import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.core.Phases.NeedsCompanions
import dotty.tools.dotc.transform.MegaPhase._
import ast.Trees._
import ast.untpd
import Flags._
import Types._
import Constants.Constant
import Contexts.Context
import Symbols._
import SymDenotations._
import Decorators._
import dotty.tools.dotc.core.Annotations.ConcreteAnnotation
import dotty.tools.dotc.core.Denotations.SingleDenotation
import scala.collection.mutable
import DenotTransformers._
import typer.Checking
import NameOps._
import NameKinds.{AvoidClashName, OuterSelectName}
import StdNames._


/** The first tree transform
 *   - ensures there are companion objects for all classes except module classes
 *   - eliminates some kinds of trees: Imports, NamedArgs
 *   - stubs out native methods
 *   - eliminates self tree in Template and self symbol in ClassInfo
 *   - collapses all type trees to trees of class TypeTree
 *   - converts idempotent expressions with constant types
 *   - drops branches of ifs using the rules
 *          if (true) A else B    ==> A
 *          if (false) A else B   ==> B
 */
class FirstTransform extends MiniPhase with InfoTransformer { thisPhase =>
  import ast.tpd._

  override def phaseName = "firstTransform"

  private[this] var addCompanionPhases: List[NeedsCompanions] = _

  override def changesMembers = true // the phase adds companion objects

  def needsCompanion(cls: ClassSymbol)(implicit ctx: Context) =
    addCompanionPhases.exists(_.isCompanionNeeded(cls))

  override def prepareForUnit(tree: Tree)(implicit ctx: Context) = {
    addCompanionPhases = ctx.phasePlan.flatMap(_ collect { case p: NeedsCompanions => p })
    ctx
  }

  /** eliminate self symbol in ClassInfo */
  override def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp match {
    case tp @ ClassInfo(_, _, _, _, self: Symbol) =>
      tp.derivedClassInfo(selfInfo = self.info)
    case _ =>
      tp
  }

  override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = {
    tree match {
      case Select(qual, name) if !name.is(OuterSelectName) && tree.symbol.exists =>
        assert(
          qual.tpe.derivesFrom(tree.symbol.owner) ||
            tree.symbol.is(JavaStatic) && qual.tpe.derivesFrom(tree.symbol.enclosingClass),
          i"non member selection of ${tree.symbol.showLocated} from ${qual.tpe} in $tree")
      case _: TypeTree =>
      case _: Import | _: NamedArg | _: TypTree =>
        assert(false, i"illegal tree: $tree")
      case _ =>
    }
  }

  /** Reorder statements so that module classes always come after their companion classes, add missing companion classes */
  private def reorderAndComplete(stats: List[Tree])(implicit ctx: Context): List[Tree] = {
    val moduleClassDefs, singleClassDefs = mutable.Map[Name, Tree]()

    /* Returns the result of reordering stats and prepending revPrefix in reverse order to it.
     * The result of reorder is equivalent to reorder(stats, revPrefix) = revPrefix.reverse ::: reorder(stats, Nil).
     * This implementation is tail recursive as long as the element is not a module TypeDef.
     */
    def reorder(stats: List[Tree], revPrefix: List[Tree]): List[Tree] = stats match {
      case (stat: TypeDef) :: stats1 if stat.symbol.isClass =>
        if (stat.symbol is Flags.Module) {
          def pushOnTop(xs: List[Tree], ys: List[Tree]): List[Tree] =
            (ys /: xs)((ys, x) => x :: ys)
          moduleClassDefs += (stat.name -> stat)
          singleClassDefs -= stat.name.stripModuleClassSuffix
          val stats1r = reorder(stats1, Nil)
          pushOnTop(revPrefix, if (moduleClassDefs contains stat.name) stat :: stats1r else stats1r)
        } else {
          reorder(
            stats1,
            moduleClassDefs remove stat.name.moduleClassName match {
              case Some(mcdef) =>
                mcdef :: stat :: revPrefix
              case None =>
                singleClassDefs += (stat.name -> stat)
                stat :: revPrefix
            }
          )
        }
      case stat :: stats1 => reorder(stats1, stat :: revPrefix)
      case Nil => revPrefix.reverse
    }

    def registerCompanion(name: TermName, forClass: Symbol): TermSymbol = {
      val (modul, mcCompanion, classCompanion) = newCompanion(name, forClass)
      if (ctx.owner.isClass) modul.enteredAfter(thisPhase)
      mcCompanion.enteredAfter(thisPhase)
      classCompanion.enteredAfter(thisPhase)
      modul
    }

    def addMissingCompanions(stats: List[Tree]): List[Tree] = stats map {
      case stat: TypeDef if (singleClassDefs contains stat.name) && needsCompanion(stat.symbol.asClass) =>
        val objName = stat.name.toTermName
        val nameClash = stats.exists {
          case other: MemberDef =>
            other.name == objName && other.symbol.info.isParameterless
          case _ =>
            false
        }
        val uniqueName = if (nameClash) AvoidClashName(objName) else objName
        Thicket(stat :: ModuleDef(registerCompanion(uniqueName, stat.symbol), Nil).trees)
      case stat => stat
    }

    addMissingCompanions(reorder(stats, Nil))
  }

  private def newCompanion(name: TermName, forClass: Symbol)(implicit ctx: Context) = {
    val modul = ctx.newCompleteModuleSymbol(forClass.owner, name, Synthetic, Synthetic,
      defn.ObjectType :: Nil, Scopes.newScope, assocFile = forClass.asClass.assocFile)
    val mc = modul.moduleClass

    val mcComp = ctx.synthesizeCompanionMethod(nme.COMPANION_CLASS_METHOD, forClass, mc)
    val classComp = ctx.synthesizeCompanionMethod(nme.COMPANION_MODULE_METHOD, mc, forClass)
    (modul, mcComp, classComp)
  }
<commit_msg>Remove dead code in FirstTransform<commit_after>package dotty.tools.dotc
package transform

import core._
import Names._
import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.core.Phases.NeedsCompanions
import dotty.tools.dotc.transform.MegaPhase._
import ast.Trees._
import ast.untpd
import Flags._
import Types._
import Constants.Constant
import Contexts.Context
import Symbols._
import SymDenotations._
import Decorators._
import dotty.tools.dotc.core.Annotations.ConcreteAnnotation
import dotty.tools.dotc.core.Denotations.SingleDenotation
import scala.collection.mutable
import DenotTransformers._
import typer.Checking
import NameOps._
import NameKinds.{AvoidClashName, OuterSelectName}
import StdNames._


/** The first tree transform
 *   - ensures there are companion objects for all classes except module classes
 *   - eliminates some kinds of trees: Imports, NamedArgs
 *   - stubs out native methods
 *   - eliminates self tree in Template and self symbol in ClassInfo
 *   - collapses all type trees to trees of class TypeTree
 *   - converts idempotent expressions with constant types
 *   - drops branches of ifs using the rules
 *          if (true) A else B    ==> A
 *          if (false) A else B   ==> B
 */
class FirstTransform extends MiniPhase with InfoTransformer { thisPhase =>
  import ast.tpd._

  override def phaseName = "firstTransform"

  private[this] var addCompanionPhases: List[NeedsCompanions] = _

  override def changesMembers = true // the phase adds companion objects

  def needsCompanion(cls: ClassSymbol)(implicit ctx: Context) =
    addCompanionPhases.exists(_.isCompanionNeeded(cls))

  override def prepareForUnit(tree: Tree)(implicit ctx: Context) = {
    addCompanionPhases = ctx.phasePlan.flatMap(_ collect { case p: NeedsCompanions => p })
    ctx
  }

  /** eliminate self symbol in ClassInfo */
  override def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp match {
    case tp @ ClassInfo(_, _, _, _, self: Symbol) =>
      tp.derivedClassInfo(selfInfo = self.info)
    case _ =>
      tp
  }

  override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = {
    tree match {
      case Select(qual, name) if !name.is(OuterSelectName) && tree.symbol.exists =>
        assert(
          qual.tpe.derivesFrom(tree.symbol.owner) ||
            tree.symbol.is(JavaStatic) && qual.tpe.derivesFrom(tree.symbol.enclosingClass),
          i"non member selection of ${tree.symbol.showLocated} from ${qual.tpe} in $tree")
      case _: TypeTree =>
      case _: Import | _: NamedArg | _: TypTree =>
        assert(false, i"illegal tree: $tree")
      case _ =>
    }
  }

  /** Reorder statements so that module classes always come after their companion classes */
  private def reorderAndComplete(stats: List[Tree])(implicit ctx: Context): List[Tree] = {
    val moduleClassDefs, singleClassDefs = mutable.Map[Name, Tree]()

    /* Returns the result of reordering stats and prepending revPrefix in reverse order to it.
     * The result of reorder is equivalent to reorder(stats, revPrefix) = revPrefix.reverse ::: reorder(stats, Nil).
     * This implementation is tail recursive as long as the element is not a module TypeDef.
     */
    def reorder(stats: List[Tree], revPrefix: List[Tree]): List[Tree] = stats match {
      case (stat: TypeDef) :: stats1 if stat.symbol.isClass =>
        if (stat.symbol is Flags.Module) {
          def pushOnTop(xs: List[Tree], ys: List[Tree]): List[Tree] =
            (ys /: xs)((ys, x) => x :: ys)
          moduleClassDefs += (stat.name -> stat)
          singleClassDefs -= stat.name.stripModuleClassSuffix
          val stats1r = reorder(stats1, Nil)
          pushOnTop(revPrefix, if (moduleClassDefs contains stat.name) stat :: stats1r else stats1r)
        } else {
          reorder(
            stats1,
            moduleClassDefs remove stat.name.moduleClassName match {
              case Some(mcdef) =>
                mcdef :: stat :: revPrefix
              case None =>
                singleClassDefs += (stat.name -> stat)
                stat :: revPrefix
            }
          )
        }
      case stat :: stats1 => reorder(stats1, stat :: revPrefix)
      case Nil => revPrefix.reverse
    }

    reorder(stats, Nil)
  }

{'fraction_non_alphanumeric': 0.0971571072319202, 'fraction_numerical': 0.0015960099750623442, 'mean_word_length': 3.07229894394801, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2890210', 'n_tokens_mistral': 3010, 'n_tokens_neox': 2909, 'n_words': 845}