<commit_before>/*
 * Scala (https://www.scala-lang.org)
 *
 * Copyright EPFL and Lightbend, Inc.
 *
 * Licensed under Apache License 2.0
 * (http://www.apache.org/licenses/LICENSE-2.0).
 *
 * See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 */

package scala.tools.nsc.transform.async

import scala.collection.mutable
import scala.reflect.internal.Flags._

trait Lifter extends ExprBuilder {
  import global._

  /**
   * Identify which DefTrees are used (including transitively) which are declared
   * in some state but used (including transitively) in another state.
   *
   * These will need to be lifted to class members of the state machine.
   */
  def liftables(asyncStates: List[AsyncState]): List[Tree] = {
    object companionship {
      private val companions = collection.mutable.Map[Symbol, Symbol]()

      def record(classes: Seq[Symbol], moduleClasses: Seq[Symbol]): Unit = {
        // Keep note of local companions so we rename them consistently when lifting.
        for {
          cd <- classes
          md <- moduleClasses
          if (cd.name == md.name)
        } {
          companions(cd) = md
          companions(md) = cd
        }
      }
      def companionOf(sym: Symbol): Symbol = {
        companions.getOrElse(sym, NoSymbol)
      }
    }


    val defs: mutable.LinkedHashMap[Tree, Int] = {
      /** Collect the DefTrees directly enclosed within `t` that have the same owner */
      object traverser extends Traverser {
        val childDefs = mutable.ArrayBuffer[Tree]()
        private val classesBuffer, moduleClassesBuffer = mutable.ArrayBuffer[Symbol]()
        override def traverse(tree: Tree): Unit = tree match {
          case _: LabelDef =>
          case _: DefTree => childDefs += tree
          case _: Function => Nil
          case Block(stats, expr) =>
            classesBuffer.clear()
            moduleClassesBuffer.clear()
            for (stat <- stats) {
              stat match {
                case _: ClassDef =>
                  val sym = stat.symbol
                  val buffer = if (sym.isModuleClass) moduleClassesBuffer else classesBuffer
                  buffer += sym
                case _ =>
              }
            }
            companionship.record(classesBuffer, moduleClassesBuffer)
            assert(!expr.isInstanceOf[ClassDef])
            super.traverse(tree)
          case _ =>
            super.traverse(tree)
        }
      }

      val result = mutable.LinkedHashMap[Tree, Int]()

      for (asyncState <- asyncStates) {
        traverser.childDefs.clear()
        traverser.traverse(Block(asyncState.allStats, EmptyTree))
        for (defTree <-traverser.childDefs) {
          result(defTree) = asyncState.state
        }
      }
      result
    }

    // In which block are these symbols defined?
    val symToDefiningState: mutable.LinkedHashMap[Symbol, Int] = defs.map {
      case (k, v) => (k.symbol, v)
    }

    // The definitions trees
    val symToTree: mutable.LinkedHashMap[Symbol, Tree] = defs.map {
      case (k, v) => (k.symbol, k)
    }

    // The direct references of each definition tree
    val defSymToReferenced: mutable.LinkedHashMap[Symbol, List[Symbol]] = defs.map {
      case (tree, _) => (tree.symbol, tree.collect {
        case rt: RefTree if symToDefiningState.contains(rt.symbol) => rt.symbol
      })
    }

    // The direct references of each block, excluding references of `DefTree`-s which
    // are already accounted for.
    val stateIdToDirectlyReferenced: mutable.LinkedHashMap[Int, List[Symbol]] = {
      val refs: List[(Int, Symbol)] = asyncStates.flatMap(
        asyncState => asyncState.stats.filterNot(t => t.isDef && !isLabel(t.symbol)).flatMap(_.collect {
          case rt: RefTree
            if symToDefiningState.contains(rt.symbol) => (asyncState.state, rt.symbol)
        })
      )
      toMultiMap(refs)
    }

    def liftableSyms: mutable.LinkedHashSet[Symbol] = {
      val liftableMutableSet = mutable.LinkedHashSet[Symbol]()
      def markForLift(sym: Symbol): Unit = {
        if (!liftableMutableSet(sym)) {
          liftableMutableSet += sym<commit_msg>Look for references in types as well as in terms.<commit_after>/*
 * Scala (https://www.scala-lang.org)
 *
 * Copyright EPFL and Lightbend, Inc.
 *
 * Licensed under Apache License 2.0
 * (http://www.apache.org/licenses/LICENSE-2.0).
 *
 * See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 */

package scala.tools.nsc.transform.async

import scala.collection.mutable
import scala.reflect.internal.Flags._

trait Lifter extends ExprBuilder {
  import global._

  /**
   * Identify which DefTrees are used (including transitively) which are declared
   * in some state but used (including transitively) in another state.
   *
   * These will need to be lifted to class members of the state machine.
   */
  def liftables(asyncStates: List[AsyncState]): List[Tree] = {
    object companionship {
      private val companions = collection.mutable.Map[Symbol, Symbol]()

      def record(classes: Seq[Symbol], moduleClasses: Seq[Symbol]): Unit = {
        // Keep note of local companions so we rename them consistently when lifting.
        for {
          cd <- classes
          md <- moduleClasses
          if (cd.name == md.name)
        } {
          companions(cd) = md
          companions(md) = cd
        }
      }
      def companionOf(sym: Symbol): Symbol = {
        companions.getOrElse(sym, NoSymbol)
      }
    }


    val defs: mutable.LinkedHashMap[Tree, Int] = {
      /** Collect the DefTrees directly enclosed within `t` that have the same owner */
      object traverser extends Traverser {
        val childDefs = mutable.ArrayBuffer[Tree]()
        private val classesBuffer, moduleClassesBuffer = mutable.ArrayBuffer[Symbol]()
        override def traverse(tree: Tree): Unit = tree match {
          case _: LabelDef =>
          case _: DefTree => childDefs += tree
          case _: Function => Nil
          case Block(stats, expr) =>
            classesBuffer.clear()
            moduleClassesBuffer.clear()
            for (stat <- stats) {
              stat match {
                case _: ClassDef =>
                  val sym = stat.symbol
                  val buffer = if (sym.isModuleClass) moduleClassesBuffer else classesBuffer
                  buffer += sym
                case _ =>
              }
            }
            companionship.record(classesBuffer, moduleClassesBuffer)
            assert(!expr.isInstanceOf[ClassDef])
            super.traverse(tree)
          case _ =>
            super.traverse(tree)
        }
      }

      val result = mutable.LinkedHashMap[Tree, Int]()

      for (asyncState <- asyncStates) {
        traverser.childDefs.clear()
        traverser.traverse(Block(asyncState.allStats, EmptyTree))
        for (defTree <-traverser.childDefs) {
          result(defTree) = asyncState.state
        }
      }
      result
    }

    // In which block are these symbols defined?
    val symToDefiningState: mutable.LinkedHashMap[Symbol, Int] = defs.map {
      case (k, v) => (k.symbol, v)
    }

    // The definitions trees
    val symToTree: mutable.LinkedHashMap[Symbol, Tree] = defs.map {
      case (k, v) => (k.symbol, k)
    }

    // The direct references of each definition tree
    val defSymToReferenced: mutable.LinkedHashMap[Symbol, List[Symbol]] = defs.map {
      case (tree, _) => (tree.symbol, tree.collect {
        case rt: RefTree if symToDefiningState.contains(rt.symbol) => rt.symbol
      } ::: tree.symbol.info.collect { case TypeRef(_, sym, _) if symToDefiningState.contains(sym) => sym })
    }

    // The direct references of each block, excluding references of `DefTree`-s which
    // are already accounted for.
    val stateIdToDirectlyReferenced: mutable.LinkedHashMap[Int, List[Symbol]] = {
      val refs: List[(Int, Symbol)] = asyncStates.flatMap(
        asyncState => asyncState.stats.filterNot(t => t.isDef && !isLabel(t.symbol)).flatMap(_.collect {
          case rt: RefTree
            if symToDefiningState.contains(rt.symbol) => (asyncState.state, rt.symbol)
        })
      )
      toMultiMap(refs)
    }

    def liftableSyms: mutable.LinkedHashSet[Symbol] = {
      val liftableMutableSet = mutable.LinkedHashSet[Symbol]()
      def markForLift(sym: Symbol): Unit = {
        if (!liftableMutableSet(sym)) {
          liftableMutableSet += sym
{'fraction_non_alphanumeric': 0.10345638372913238, 'fraction_numerical': 0.0009405125793557489, 'mean_word_length': 2.3217493166731744, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 32, 'https://': 2, 'lorem ipsum': 0, 'www.': 4, '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': '3399292', 'n_tokens_mistral': 2443, 'n_tokens_neox': 2384, 'n_words': 641}