<commit_before>package ammonite.repl.interp

import java.net.{URL, URLClassLoader}
import java.security.MessageDigest

import ammonite.ops.{stat, Path}
import ammonite.repl.{ImportData, Util}
import pprint.PPrint

import scala.collection.mutable
import scala.reflect.io.VirtualDirectory

object Frame{
  def delta(oldFrame: Frame, newFrame: Frame) = {
    import pprint.Config.Colors._
    def printDelta[T: PPrint](name: String, s1: Set[T], s2: Set[T]) = {
      val d = s1 -- s2
      if (d.nonEmpty){
        print(name + ":")
        pprint.pprintln(d)
      }
    }
    printDelta(
      "Removed Imports",
      oldFrame.previousImports.keySet.map(Symbol(_)),
      newFrame.previousImports.keySet.map(Symbol(_))
    )
    printDelta(
      "Added Imports",
      newFrame.previousImports.keySet.map(Symbol(_)),
      oldFrame.previousImports.keySet.map(Symbol(_))
    )
    printDelta(
      "Removed Jars",
      oldFrame.classloader.allJars.toSet,
      newFrame.classloader.allJars.toSet
    )
    printDelta(
      "Added Jars",
      newFrame.classloader.allJars.toSet,
      oldFrame.classloader.allJars.toSet
    )
  }
}
case class Frame(classloader: SpecialClassLoader,
                 pluginClassloader: SpecialClassLoader,
                 var previousImports: Map[String, ImportData],
                 var extraJars: Seq[java.io.File])

object SpecialClassLoader{
  def initialClasspathHash(classloader: ClassLoader) = {

    // Lol this is so hax. But it works! And is way faster than trying
    // to iterate over *every* file in the classpath, and way more
    // convenient than trying to futz around with java agents
    val allClasses = collection.mutable.Buffer.empty[Class[_]]
    val f = classOf[ClassLoader].getDeclaredField("classes")
    f.setAccessible(true)
    var current: ClassLoader = classloader
    while(current != null){
      val classes = f.get(current).asInstanceOf[java.util.Vector[Class[_]]]
      import collection.JavaConversions._
      allClasses.appendAll(classes)
      current = current.getParent<commit_msg>attempt to synchronize hacky reflective class scanning<commit_after>package ammonite.repl.interp

import java.net.{URL, URLClassLoader}
import java.security.MessageDigest

import ammonite.ops.{stat, Path}
import ammonite.repl.{ImportData, Util}
import pprint.PPrint

import scala.collection.mutable
import scala.reflect.io.VirtualDirectory

object Frame{
  def delta(oldFrame: Frame, newFrame: Frame) = {
    import pprint.Config.Colors._
    def printDelta[T: PPrint](name: String, s1: Set[T], s2: Set[T]) = {
      val d = s1 -- s2
      if (d.nonEmpty){
        print(name + ":")
        pprint.pprintln(d)
      }
    }
    printDelta(
      "Removed Imports",
      oldFrame.previousImports.keySet.map(Symbol(_)),
      newFrame.previousImports.keySet.map(Symbol(_))
    )
    printDelta(
      "Added Imports",
      newFrame.previousImports.keySet.map(Symbol(_)),
      oldFrame.previousImports.keySet.map(Symbol(_))
    )
    printDelta(
      "Removed Jars",
      oldFrame.classloader.allJars.toSet,
      newFrame.classloader.allJars.toSet
    )
    printDelta(
      "Added Jars",
      newFrame.classloader.allJars.toSet,
      oldFrame.classloader.allJars.toSet
    )
  }
}
case class Frame(classloader: SpecialClassLoader,
                 pluginClassloader: SpecialClassLoader,
                 var previousImports: Map[String, ImportData],
                 var extraJars: Seq[java.io.File])

object SpecialClassLoader{
  def initialClasspathHash(classloader: ClassLoader) = {

    // Lol this is so hax. But it works! And is way faster than trying
    // to iterate over *every* file in the classpath, and way more
    // convenient than trying to futz around with java agents
    val allClasses = collection.mutable.Buffer.empty[Class[_]]
    val f = classOf[ClassLoader].getDeclaredField("classes")
    f.setAccessible(true)
    var current: ClassLoader = classloader
    while(current != null){
      current.synchronized{
        val classes = f.get(current).asInstanceOf[java.util.Vector[Class[_]]]
        import collection.JavaConversions._
        allClasses.appendAll(classes)
      }
      current = current.getParent
{'fraction_non_alphanumeric': 0.10439952437574317, 'fraction_numerical': 0.0019024970273483948, 'mean_word_length': 3.0834951456310677, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, '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': '6343821', 'n_tokens_mistral': 1305, 'n_tokens_neox': 1303, 'n_words': 280}