<commit_before>/* NSC -- new Scala compiler
 * Copyright 2007-2011 LAMP/EPFL
 * @author <NAME>
 */

package scala.tools.nsc
package plugins

import io.{ File, Path }
import java.net.URLClassLoader
import java.util.jar.JarFile
import java.util.zip.ZipException

import scala.collection.mutable
import mutable.ListBuffer
import scala.xml.XML

/** <p>
 *    Information about a plugin loaded from a jar file.
 *  </p>
 *  <p>
 *    The concrete subclass must have a one-argument constructor
 *    that accepts an instance of <code>Global</code>.
 *  </p><pre>
 *    (val global: Global)
 *  </pre>
 *
 *  @author <NAME>
 *  @version 1.0, 2007-5-21
 */
abstract class Plugin {
  /** The name of this plugin */
  val name: String

  /** The components that this phase defines */
  val components: List[PluginComponent]

  /** A one-line description of the plugin */
  val description: String

  /** The compiler that this plugin uses.  This is normally equated
   *  to a constructor parameter in the concrete subclass. */
  val global: Global

  /** Handle any plugin-specific options.  The -P:plugname: part
   *  will not be present. */
  def processOptions(options: List[String], error: String => Unit) {
    if (!options.isEmpty)
      error("Error: " + name + " has no options")
  }

  /** A description of this plugin's options, suitable as a response
   *  to the -help command-line option.  Conventionally, the
   *  options should be listed with the <code>-P:plugname:</code>
   *  part included.
   */
  val optionsHelp: Option[String] = None
}

/** ...
 *
 *  @author <NAME>
 *  @version 1.0, 2007-5-21
 */
object Plugin {

  private val PluginXML = "scalac-plugin.xml"

  /** Create a class loader with the specified file plus
   *  the loader that loaded the Scala compiler.
   */
  private def loaderFor(jarfiles: Seq[Path]): ClassLoader = {
    val compilerLoader = classOf[Plugin].getClassLoader
    val jarurls = jarfiles map (_.toURL)

    new URLClassLoader(jarurls.toArray, compilerLoader)
  }

  /** Try to load a plugin description from the specified
   *  file, returning <code>None</code> if it does not work.
   */
  private def loadDescription(jarfile: Path): Option[PluginDescription] =
    // XXX Return to this once we have some ARM support
    if (!jarfile.exists) None
    else try {
      val jar = new JarFile(jarfile.jfile)

      try {
        jar getEntry PluginXML match {
          case null  => None
          case entry =>
            val in = jar getInputStream entry
            val packXML = XML load in
            in.close()

            PluginDescription fromXML packXML
        }
      }
      finally jar.close()
    }
    catch {
      case _: ZipException => None
    }

  type AnyClass = Class[_]

  /** Loads a plugin class from the named jar file.

   *  @return <code>None</code> if the jar file has no plugin in it or
   *                            if the plugin is badly formed.
   */
  def loadFrom(jarfile: Path, loader: ClassLoader): Option[AnyClass] =
    loadDescription(jarfile) match {
      case None => None
      case Some(pdesc) =>
        try Some(loader loadClass pdesc.classname) catch {
        case _: Exception =>
          println("Warning: class not found for plugin in %s (%s)".format(jarfile, pdesc.classname))
          None
      }
    }

  /** Load all plugins found in the argument list, both in the
   *  jar files explicitly listed, and in the jar files in the
   *  directories specified. Skips all plugins in <code>ignoring</code>.
   *  A single classloader is created and used to load all of them.
   */
  def loadAllFrom(
    jars: List[Path],
    dirs: List[Path],
    ignoring: List[String]): List[AnyClass] =
  {
    val alljars = (jars ::: (for {
      dir <- dirs if dir.isDirectory
      entry <- dir.toDirectory.files.toList sortBy (_.name)
      if Path.isJarOrZip(entry)
      pdesc <- loadDescription(entry)
      if !(ignoring contains pdesc.name)
    } yield entry)).distinct
<commit_msg>Warn when the jar file cannot be found when loa...<commit_after>/* NSC -- new Scala compiler
 * Copyright 2007-2011 LAMP/EPFL
 * @author <NAME>
 */

package scala.tools.nsc
package plugins

import io.{ File, Path }
import java.net.URLClassLoader
import java.util.jar.JarFile
import java.util.zip.ZipException

import scala.collection.mutable
import mutable.ListBuffer
import scala.xml.XML

/** <p>
 *    Information about a plugin loaded from a jar file.
 *  </p>
 *  <p>
 *    The concrete subclass must have a one-argument constructor
 *    that accepts an instance of <code>Global</code>.
 *  </p><pre>
 *    (val global: Global)
 *  </pre>
 *
 *  @author <NAME>
 *  @version 1.0, 2007-5-21
 */
abstract class Plugin {
  /** The name of this plugin */
  val name: String

  /** The components that this phase defines */
  val components: List[PluginComponent]

  /** A one-line description of the plugin */
  val description: String

  /** The compiler that this plugin uses.  This is normally equated
   *  to a constructor parameter in the concrete subclass. */
  val global: Global

  /** Handle any plugin-specific options.  The -P:plugname: part
   *  will not be present. */
  def processOptions(options: List[String], error: String => Unit) {
    if (!options.isEmpty)
      error("Error: " + name + " has no options")
  }

  /** A description of this plugin's options, suitable as a response
   *  to the -help command-line option.  Conventionally, the
   *  options should be listed with the <code>-P:plugname:</code>
   *  part included.
   */
  val optionsHelp: Option[String] = None
}

/** ...
 *
 *  @author <NAME>
 *  @version 1.0, 2007-5-21
 */
object Plugin {

  private val PluginXML = "scalac-plugin.xml"

  /** Create a class loader with the specified file plus
   *  the loader that loaded the Scala compiler.
   */
  private def loaderFor(jarfiles: Seq[Path]): ClassLoader = {
    val compilerLoader = classOf[Plugin].getClassLoader
    val jarurls = jarfiles map (_.toURL)

    new URLClassLoader(jarurls.toArray, compilerLoader)
  }

  /** Try to load a plugin description from the specified
   *  file, returning <code>None</code> if it does not work.
   */
  private def loadDescription(jarfile: Path): Option[PluginDescription] =
    // XXX Return to this once we have some ARM support
    if (!jarfile.exists) None
    else try {
      val jar = new JarFile(jarfile.jfile)

      try {
        jar getEntry PluginXML match {
          case null  => None
          case entry =>
            val in = jar getInputStream entry
            val packXML = XML load in
            in.close()

            PluginDescription fromXML packXML
        }
      }
      finally jar.close()
    }
    catch {
      case _: ZipException => None
    }

  type AnyClass = Class[_]

  /** Loads a plugin class from the named jar file.

   *  @return <code>None</code> if the jar file has no plugin in it or
   *                            if the plugin is badly formed.
   */
  def loadFrom(jarfile: Path, loader: ClassLoader): Option[AnyClass] =
    loadDescription(jarfile) match {
      case None =>
        println("Warning: could not load descriptor for plugin %s".format(jarfile))
        None
      case Some(pdesc) =>
        try Some(loader loadClass pdesc.classname) catch {
        case _: Exception =>
          println("Warning: class not found for plugin in %s (%s)".format(jarfile, pdesc.classname))
          None
      }
    }

  /** Load all plugins found in the argument list, both in the
   *  jar files explicitly listed, and in the jar files in the
   *  directories specified. Skips all plugins in <code>ignoring</code>.
   *  A single classloader is created and used to load all of them.
   */
  def loadAllFrom(
    jars: List[Path],
    dirs: List[Path],
    ignoring: List[String]): List[AnyClass] =
  {
    val alljars = (jars ::: (for {
      dir <- dirs if dir.isDirectory
      entry <- dir.toDirectory.files.toList sortBy (_.name)
      if Path.isJarOrZip(entry)
      pdesc <- loadDescription(entry)
      if !(ignoring contains pdesc.name)
    } yield entry)).distinct

{'fraction_non_alphanumeric': 0.10371650821089023, 'fraction_numerical': 0.006420545746388443, 'mean_word_length': 2.584070796460177, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2134705', 'n_tokens_mistral': 2471, 'n_tokens_neox': 2382, 'n_words': 852}