<commit_before>/*
 * sbt
 * Copyright 2011 - 2018, Lightbend, Inc.
 * Copyright 2008 - 2010, <NAME>
 * Licensed under Apache License 2.0 (see LICENSE)
 */

package sbt
package compiler

import scala.collection.mutable.ListBuffer
import scala.tools.nsc.{ ast, io, reporters, CompilerCommand, Global, Phase, Settings }
import io.{ AbstractFile, PlainFile, VirtualDirectory }
import ast.parser.Tokens
import reporters.{ ConsoleReporter, Reporter }
import scala.reflect.internal.util.{ AbstractFileClassLoader, BatchSourceFile }
import Tokens.{ EOF, NEWLINE, NEWLINES, SEMI }
import java.io.{ File, FileNotFoundException }
import java.nio.ByteBuffer
import java.net.URLClassLoader
import java.security.MessageDigest
import Eval.{ getModule, getValue, WrapValName }

import sbt.io.{ DirectoryFilter, FileFilter, GlobFilter, Hash, IO, Path }

// TODO: provide a way to cleanup backing directory

final class EvalImports(val strings: Seq[(String, Int)], val srcName: String)

/**
 * The result of evaluating a Scala expression.  The inferred type of the expression is given by `tpe`.
 * The value may be obtained from `getValue` by providing a parent class loader that provides the classes from the classpath
 * this expression was compiled against.  Each call to `getValue` constructs a new class loader and loads
 * the module from that class loader.  `generated` contains the compiled classes and cache files related
 * to the expression.  The name of the auto-generated module wrapping the expression is `enclosingModule`.
 */
final class EvalResult(
    val tpe: String,
    val getValue: ClassLoader => Any,
    val generated: Seq[File],
    val enclosingModule: String
)

/**
 * The result of evaluating a group of Scala definitions.  The definitions are wrapped in an auto-generated,
 * top-level module named `enclosingModule`.  `generated` contains the compiled classes and cache files related to the definitions.
 * A new class loader containing the module may be obtained from `loader` by passing the parent class loader providing the classes
 * from the classpath that the definitions were compiled against.  The list of vals with the requested types is `valNames`.
 * The values for these may be obtained by providing the parent class loader to `values` as is done with `loader`.
 */
final class EvalDefinitions(
    val loader: ClassLoader => ClassLoader,
    val generated: Seq[File],
    val enclosingModule: String,
    val valNames: Seq[String]
) {
  def values(parent: ClassLoader): Seq[Any] = {
    val module = getModule(enclosingModule, loader(parent))
    for (n <- valNames) yield module.getClass.getMethod(n).invoke(module)
  }
}

final class EvalException(msg: String) extends RuntimeException(msg)
// not thread safe, since it reuses a Global instance
final class Eval(
    optionsNoncp: Seq[String],
    classpath: Seq[File],
    mkReporter: Settings => Reporter,
    backing: Option[File]
) {
  def this(mkReporter: Settings => Reporter, backing: Option[File]) =
    this(Nil, IO.classLocationPath[Product].toFile :: Nil, mkReporter, backing)
  def this() = this(s => new ConsoleReporter(s), None)

  backing.foreach(IO.createDirectory)
  val classpathString = Path.makeString(classpath ++ backing.toList)
  val options = "-cp" +: classpathString +: optionsNoncp

  lazy val settings = {
    val s = new Settings(println)
    new CompilerCommand(options.toList, s) // this side-effects on Settings..
    s
  }
  lazy val reporter = mkReporter(settings)

  /**
   * Subclass of Global which allows us to mutate currentRun from outside.
   * See for rationale https://issues.scala-lang.org/browse/SI-8794
   */
  final class EvalGlobal(settings: Settings, reporter: Reporter)
      extends Global(settings, reporter) {
    override def currentRun: Run = curRun
    var curRun: Run = null
  }
  lazy val global: EvalGlobal = new EvalGlobal(settings, reporter)
  import global._

  private[sbt] def unlinkDeferred(): Unit = {
    toUnlinkLater foreach unlink
    toUnlinkLater = Nil
  }

  private[this] var toUnlinkLater = List[Symbol]()
  private[this] def unlink(sym: Symbol) = sym.owner.info.decls.unlink(sym)

  def eval(
      expression: String,
      imports: EvalImports = noImports,
      tpeName: Option[String] = None,
      srcName: String = "<setting>",
      line: Int = DefaultStartLine
  ): EvalResult = {
    val ev = new EvalType[String] {
      def makeUnit = mkUnit(srcName, line, expression)
      def unlink = true
      def unitBody(unit: CompilationUnit, importTrees: Seq[Tree], moduleName: String): Tree = {
        val (parser, tree) = parse(unit, settingErrorStrings, _.expr())
        val tpt: Tree = expectedType(tpeName)
        augment(parser, importTrees, tree, tpt, moduleName)
      }
      def extra(run: Run, unit: CompilationUnit) = enteringPhase(run.typerPhase.next) {
        (new TypeExtractor).getType(unit.body)<commit_msg>Avoid NPE on Run.<init><commit_after>/*
 * sbt
 * Copyright 2011 - 2018, Lightbend, Inc.
 * Copyright 2008 - 2010, <NAME>
 * Licensed under Apache License 2.0 (see LICENSE)
 */

package sbt
package compiler

import scala.collection.mutable.ListBuffer
import scala.tools.nsc.{ ast, io, reporters, CompilerCommand, Global, Phase, Settings }
import io.{ AbstractFile, PlainFile, VirtualDirectory }
import ast.parser.Tokens
import reporters.{ ConsoleReporter, Reporter }
import scala.reflect.internal.util.{ AbstractFileClassLoader, BatchSourceFile }
import Tokens.{ EOF, NEWLINE, NEWLINES, SEMI }
import java.io.{ File, FileNotFoundException }
import java.nio.ByteBuffer
import java.net.URLClassLoader
import java.security.MessageDigest
import Eval.{ getModule, getValue, WrapValName }

import sbt.io.{ DirectoryFilter, FileFilter, GlobFilter, Hash, IO, Path }

// TODO: provide a way to cleanup backing directory

final class EvalImports(val strings: Seq[(String, Int)], val srcName: String)

/**
 * The result of evaluating a Scala expression.  The inferred type of the expression is given by `tpe`.
 * The value may be obtained from `getValue` by providing a parent class loader that provides the classes from the classpath
 * this expression was compiled against.  Each call to `getValue` constructs a new class loader and loads
 * the module from that class loader.  `generated` contains the compiled classes and cache files related
 * to the expression.  The name of the auto-generated module wrapping the expression is `enclosingModule`.
 */
final class EvalResult(
    val tpe: String,
    val getValue: ClassLoader => Any,
    val generated: Seq[File],
    val enclosingModule: String
)

/**
 * The result of evaluating a group of Scala definitions.  The definitions are wrapped in an auto-generated,
 * top-level module named `enclosingModule`.  `generated` contains the compiled classes and cache files related to the definitions.
 * A new class loader containing the module may be obtained from `loader` by passing the parent class loader providing the classes
 * from the classpath that the definitions were compiled against.  The list of vals with the requested types is `valNames`.
 * The values for these may be obtained by providing the parent class loader to `values` as is done with `loader`.
 */
final class EvalDefinitions(
    val loader: ClassLoader => ClassLoader,
    val generated: Seq[File],
    val enclosingModule: String,
    val valNames: Seq[String]
) {
  def values(parent: ClassLoader): Seq[Any] = {
    val module = getModule(enclosingModule, loader(parent))
    for (n <- valNames) yield module.getClass.getMethod(n).invoke(module)
  }
}

final class EvalException(msg: String) extends RuntimeException(msg)
// not thread safe, since it reuses a Global instance
final class Eval(
    optionsNoncp: Seq[String],
    classpath: Seq[File],
    mkReporter: Settings => Reporter,
    backing: Option[File]
) {
  def this(mkReporter: Settings => Reporter, backing: Option[File]) =
    this(Nil, IO.classLocationPath[Product].toFile :: Nil, mkReporter, backing)
  def this() = this(s => new ConsoleReporter(s), None)

  backing.foreach(IO.createDirectory)
  val classpathString = Path.makeString(classpath ++ backing.toList)
  val options = "-cp" +: classpathString +: optionsNoncp

  lazy val settings = {
    val s = new Settings(println)
    new CompilerCommand(options.toList, s) // this side-effects on Settings..
    s
  }
  lazy val reporter = mkReporter(settings)

  /**
   * Subclass of Global which allows us to mutate currentRun from outside.
   * See for rationale https://issues.scala-lang.org/browse/SI-8794
   */
  final class EvalGlobal(settings: Settings, reporter: Reporter)
      extends Global(settings, reporter) {
    override def currentRun: Run = curRun match {
      case null => super.currentRun // https://github.com/scala/bug/issues/11381
      case r    => r
    }
    var curRun: Run = null
  }
  lazy val global: EvalGlobal = new EvalGlobal(settings, reporter)
  import global._

  private[sbt] def unlinkDeferred(): Unit = {
    toUnlinkLater foreach unlink
    toUnlinkLater = Nil
  }

  private[this] var toUnlinkLater = List[Symbol]()
  private[this] def unlink(sym: Symbol) = sym.owner.info.decls.unlink(sym)

  def eval(
      expression: String,
      imports: EvalImports = noImports,
      tpeName: Option[String] = None,
      srcName: String = "<setting>",
      line: Int = DefaultStartLine
  ): EvalResult = {
    val ev = new EvalType[String] {
      def makeUnit = mkUnit(srcName, line, expression)
      def unlink = true
      def unitBody(unit: CompilationUnit, importTrees: Seq[Tree], moduleName: String): Tree = {
        val (parser, tree) = parse(unit, settingErrorStrings, _.expr())
        val tpt: Tree = expectedType(tpeName)
        augment(parser, importTrees, tree, tpt, moduleName)
      }
      def extra(run: Run, unit: CompilationUnit) = enteringPhase(run.typerPhase.next) {
        (new TypeExtractor).getType(unit.body)
{'fraction_non_alphanumeric': 0.09417946645109135, 'fraction_numerical': 0.004951495553759094, 'mean_word_length': 3.975867269984917, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 20, 'https://': 3, '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': '3515898', 'n_tokens_mistral': 2898, 'n_tokens_neox': 2808, 'n_words': 1022}