<commit_before>package scala.meta
package internal.hosts.scalac
package backend

import scala.collection.mutable
import scala.reflect.internal.util.Statistics
import scala.tools.nsc.Phase
import scala.tools.nsc.{Global => NscGlobal}
import scala.tools.asm
import scala.tools.asm.tree.ClassNode
import scala.tools.nsc.backend.jvm.opt.LocalOpt
import scala.meta.internal.hosts.scalac.tasty._
import org.scalameta.reflection._
import scala.tools.nsc.backend.jvm._
import scala.meta.internal.hosts.scalac.{PluginBase => ScalahostPlugin}

// NOTE: mostly copy/pasted from https://github.com/VladimirNik/tasty/blob/7b45111d066ddbc43d859c9f6c0a81978111cf90/plugin/src/main/scala/scala/tasty/internal/scalac/Plugin.scala
abstract class ScalahostGenBCode(override val global: NscGlobal) extends scala.tools.nsc.Global$genBCode$(global) with GlobalToolkit {
  import global._
  import bTypes._
  import coreBTypes._

  override val phaseName = "jvm"

  override def newPhase(prev: Phase) = {
    new BCodePhase2(prev)
  }

  final class PlainClassBuilder(cunit: CompilationUnit) extends SyncAndTryBuilder(cunit)

  class BCodePhase2(prev: Phase) extends BCodePhase(prev) {

    override def name = phaseName
    override def description = "Generate bytecode from ASTs using the ASM library"
    override def erasedTypes = true

    private var bytecodeWriter: BytecodeWriter = null
    private var mirrorCodeGen: JMirrorBuilder = null
    private var beanInfoCodeGen: JBeanInfoBuilder = null

    /* ---------------- q1 ---------------- */

    //      case class Item1(arrivalPos: Int, cd: ClassDef, cunit: CompilationUnit) {
    //        def isPoison = { arrivalPos == Int.MaxValue }
    //      }
    private val poison1 = Item1(Int.MaxValue, null, null)
    private val q1 = new java.util.LinkedList[Item1]

    /* ---------------- q2 ---------------- */

    //      case class Item2(arrivalPos: Int,
    //                       mirror: asm.tree.ClassNode,
    //                       plain: asm.tree.ClassNode,
    //                       bean: asm.tree.ClassNode,
    //                       outFolder: scala.tools.nsc.io.AbstractFile) {
    //        def isPoison = { arrivalPos == Int.MaxValue }
    //      }

    private val poison2 = Item2(Int.MaxValue, null, null, null, null)
    private val q2 = new _root_.java.util.LinkedList[Item2]

    /* ---------------- q3 ---------------- */

    /*
   *  An item of queue-3 (the last queue before serializing to disk) contains three of these
   *  (one for each of mirror, plain, and bean classes).
   *
   *  @param jclassName  internal name of the class
   *  @param jclassBytes bytecode emitted for the class SubItem3 represents
   */
    //      case class SubItem3(
    //        jclassName: String,
    //        jclassBytes: Array[Byte])
    //
    //      case class Item3(arrivalPos: Int,
    //                       mirror: SubItem3,
    //                       plain: SubItem3,
    //                       bean: SubItem3,
    //                       outFolder: scala.tools.nsc.io.AbstractFile) {
    //
    //        def isPoison = { arrivalPos == Int.MaxValue }
    //      }
    private val i3comparator = new java.util.Comparator[Item3] {
      override def compare(a: Item3, b: Item3) = {
        if (a.arrivalPos < b.arrivalPos) -1
        else if (a.arrivalPos == b.arrivalPos) 0
        else 1
      }
    }
    private val poison3 = Item3(Int.MaxValue, null, null, null, null)
    private val q3 = new java.util.PriorityQueue[Item3](1000, i3comparator)

    /*
   *  Pipeline that takes ClassDefs from queue-1, lowers them into an intermediate form, placing them on queue-2
   */
    class Worker1(needsOutFolder: Boolean) {

      val caseInsensitively = mutable.Map.empty[String, Symbol]

      def run() {
        while (true) {
          val item = q1.poll
          if (item.isPoison) {
            q2 add poison2
            return
          } else {
            try { withCurrentUnit(item.cunit)(visit(item)) }
            catch {
              case ex: Throwable =>
                ex.printStackTrace()
                error(s"Error while emitting ${item.cunit.source}\n${ex.getMessage}")
            }
          }
        }
      }

      /*
     *  Checks for duplicate internal names case-insensitively,
     *  builds ASM ClassNodes for mirror, plain, and bean classes;
     *  enqueues them in queue-2.
     *
     */
      def visit(item: Item1) {
        val Item1(arrivalPos, cd, cunit) = item
        val claszSymbol = cd.symbol

        // GenASM checks this before classfiles are emitted, https://github.com/scala/scala/commit/e4d1d930693ac75d8eb64c2c3c69f2fc22bec739
        val lowercaseJavaClassName = claszSymbol.javaClassName.toLowerCase
        caseInsensitively.get(lowercaseJavaClassName) match {
          case None =>
            caseInsensitively.put(lowercaseJavaClassName, claszSymbol)
          case Some(dupClassSym) =>
            reporter.warning(
              claszSymbol.pos,
              s"Class ${claszSymbol.javaClassName} differs only in case from ${dupClassSym.javaClassName}. " +
                "Such classes will overwrite one another on case-insensitive filesystems.")
        }

        // -------------- mirror class, if needed --------------
        val mirrorC =
          if (isTopLevelModuleClass(claszSymbol)) {
            if (claszSymbol.companionClass == NoSymbol) {
              mirrorCodeGen.genMirrorClass(claszSymbol, cunit)
            } else {
              log(s"No mirror class for module with linked class: ${claszSymbol.fullName}")
              null
            }
          } else null

        // -------------- "plain" class --------------
        val pcb = new PlainClassBuilder(cunit)
        pcb.genPlainClass(cd)
        val outF = if (needsOutFolder) getOutFolder(claszSymbol, pcb.thisName, cunit) else null;
        val plainC = pcb.cnode

        import scala.tools.asm.CustomAttr
        if (claszSymbol.isClass) // @DarkDimius is this test needed here?
          for (meta <- cunit.body.metadata.get("scalameta")) {
            val binary = {
              if (cunit.body.hasMetadata("tastyWritten")) new Array[Byte](0)
              else meta.asInstanceOf[Source].toTasty
            }
            val dataAttr = new CustomAttr("TASTY", binary)
            plainC.visitAttribute(dataAttr)
            cunit.body.appendMetadata("tastyWritten" -> true)
          }

        // -------------- bean info class, if needed --------------
        val beanC =
          if (claszSymbol hasAnnotation BeanInfoAttr) {
            beanInfoCodeGen.genBeanInfoClass(
              claszSymbol, cunit,
              fieldSymbols(claszSymbol),
              methodSymbols(cd))<commit_msg>persists merged trees, not the immediate results of conversion<commit_after>package scala.meta
package internal.hosts.scalac
package backend

import scala.collection.mutable
import scala.reflect.internal.util.Statistics
import scala.tools.nsc.Phase
import scala.tools.nsc.{Global => NscGlobal}
import scala.tools.asm
import scala.tools.asm.tree.ClassNode
import scala.tools.nsc.backend.jvm.opt.LocalOpt
import scala.meta.internal.hosts.scalac.tasty._
import org.scalameta.reflection._
import scala.tools.nsc.backend.jvm._
import scala.meta.internal.hosts.scalac.{PluginBase => ScalahostPlugin}

// NOTE: mostly copy/pasted from https://github.com/VladimirNik/tasty/blob/7b45111d066ddbc43d859c9f6c0a81978111cf90/plugin/src/main/scala/scala/tasty/internal/scalac/Plugin.scala
abstract class ScalahostGenBCode(override val global: NscGlobal) extends scala.tools.nsc.Global$genBCode$(global) with GlobalToolkit {
  import global._
  import bTypes._
  import coreBTypes._

  override val phaseName = "jvm"

  override def newPhase(prev: Phase) = {
    new BCodePhase2(prev)
  }

  final class PlainClassBuilder(cunit: CompilationUnit) extends SyncAndTryBuilder(cunit)

  class BCodePhase2(prev: Phase) extends BCodePhase(prev) {

    override def name = phaseName
    override def description = "Generate bytecode from ASTs using the ASM library"
    override def erasedTypes = true

    private var bytecodeWriter: BytecodeWriter = null
    private var mirrorCodeGen: JMirrorBuilder = null
    private var beanInfoCodeGen: JBeanInfoBuilder = null

    /* ---------------- q1 ---------------- */

    //      case class Item1(arrivalPos: Int, cd: ClassDef, cunit: CompilationUnit) {
    //        def isPoison = { arrivalPos == Int.MaxValue }
    //      }
    private val poison1 = Item1(Int.MaxValue, null, null)
    private val q1 = new java.util.LinkedList[Item1]

    /* ---------------- q2 ---------------- */

    //      case class Item2(arrivalPos: Int,
    //                       mirror: asm.tree.ClassNode,
    //                       plain: asm.tree.ClassNode,
    //                       bean: asm.tree.ClassNode,
    //                       outFolder: scala.tools.nsc.io.AbstractFile) {
    //        def isPoison = { arrivalPos == Int.MaxValue }
    //      }

    private val poison2 = Item2(Int.MaxValue, null, null, null, null)
    private val q2 = new _root_.java.util.LinkedList[Item2]

    /* ---------------- q3 ---------------- */

    /*
   *  An item of queue-3 (the last queue before serializing to disk) contains three of these
   *  (one for each of mirror, plain, and bean classes).
   *
   *  @param jclassName  internal name of the class
   *  @param jclassBytes bytecode emitted for the class SubItem3 represents
   */
    //      case class SubItem3(
    //        jclassName: String,
    //        jclassBytes: Array[Byte])
    //
    //      case class Item3(arrivalPos: Int,
    //                       mirror: SubItem3,
    //                       plain: SubItem3,
    //                       bean: SubItem3,
    //                       outFolder: scala.tools.nsc.io.AbstractFile) {
    //
    //        def isPoison = { arrivalPos == Int.MaxValue }
    //      }
    private val i3comparator = new java.util.Comparator[Item3] {
      override def compare(a: Item3, b: Item3) = {
        if (a.arrivalPos < b.arrivalPos) -1
        else if (a.arrivalPos == b.arrivalPos) 0
        else 1
      }
    }
    private val poison3 = Item3(Int.MaxValue, null, null, null, null)
    private val q3 = new java.util.PriorityQueue[Item3](1000, i3comparator)

    /*
   *  Pipeline that takes ClassDefs from queue-1, lowers them into an intermediate form, placing them on queue-2
   */
    class Worker1(needsOutFolder: Boolean) {

      val caseInsensitively = mutable.Map.empty[String, Symbol]

      def run() {
        while (true) {
          val item = q1.poll
          if (item.isPoison) {
            q2 add poison2
            return
          } else {
            try { withCurrentUnit(item.cunit)(visit(item)) }
            catch {
              case ex: Throwable =>
                ex.printStackTrace()
                error(s"Error while emitting ${item.cunit.source}\n${ex.getMessage}")
            }
          }
        }
      }

      /*
     *  Checks for duplicate internal names case-insensitively,
     *  builds ASM ClassNodes for mirror, plain, and bean classes;
     *  enqueues them in queue-2.
     *
     */
      def visit(item: Item1) {
        val Item1(arrivalPos, cd, cunit) = item
        val claszSymbol = cd.symbol

        // GenASM checks this before classfiles are emitted, https://github.com/scala/scala/commit/e4d1d930693ac75d8eb64c2c3c69f2fc22bec739
        val lowercaseJavaClassName = claszSymbol.javaClassName.toLowerCase
        caseInsensitively.get(lowercaseJavaClassName) match {
          case None =>
            caseInsensitively.put(lowercaseJavaClassName, claszSymbol)
          case Some(dupClassSym) =>
            reporter.warning(
              claszSymbol.pos,
              s"Class ${claszSymbol.javaClassName} differs only in case from ${dupClassSym.javaClassName}. " +
                "Such classes will overwrite one another on case-insensitive filesystems.")
        }

        // -------------- mirror class, if needed --------------
        val mirrorC =
          if (isTopLevelModuleClass(claszSymbol)) {
            if (claszSymbol.companionClass == NoSymbol) {
              mirrorCodeGen.genMirrorClass(claszSymbol, cunit)
            } else {
              log(s"No mirror class for module with linked class: ${claszSymbol.fullName}")
              null
            }
          } else null

        // -------------- "plain" class --------------
        val pcb = new PlainClassBuilder(cunit)
        pcb.genPlainClass(cd)
        val outF = if (needsOutFolder) getOutFolder(claszSymbol, pcb.thisName, cunit) else null;
        val plainC = pcb.cnode

        import scala.tools.asm.CustomAttr
        if (claszSymbol.isClass) // @DarkDimius is this test needed here?
          for (meta <- cunit.body.metadata.get("scalametaSyntactic")) {
            val binary = {
              if (cunit.body.hasMetadata("tastyWritten")) new Array[Byte](0)
              else meta.asInstanceOf[Source].toTasty
            }
            val dataAttr = new CustomAttr("TASTY", binary)
            plainC.visitAttribute(dataAttr)
            cunit.body.appendMetadata("tastyWritten" -> true)
          }

        // -------------- bean info class, if needed --------------
        val beanC =
          if (claszSymbol hasAnnotation BeanInfoAttr) {
            beanInfoCodeGen.genBeanInfoClass(
              claszSymbol, cunit,
              fieldSymbols(claszSymbol),
              methodSymbols(cd))
{'fraction_non_alphanumeric': 0.11767751479289941, 'fraction_numerical': 0.014497041420118343, 'mean_word_length': 1.9736089729491972, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 15, 'https://': 4, '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': '5328042', 'n_tokens_mistral': 4064, 'n_tokens_neox': 3913, 'n_words': 939}