<commit_before>package scala.tools.eclipse

import scala.collection.mutable
import org.eclipse.jdt.core.IPackageFragmentRoot
import org.eclipse.jdt.core.IJavaProject
import org.eclipse.core.resources.IMarker
import org.eclipse.jdt.core.IJarEntryResource
import java.util.Properties
import org.eclipse.core.resources.IProject
import org.eclipse.jdt.core.IJavaModelMarker
import org.eclipse.core.runtime.IStatus
import org.eclipse.core.runtime.IProgressMonitor
import org.eclipse.core.runtime.jobs.Job
import org.eclipse.core.resources.IResource
import org.eclipse.core.runtime.Status
import ScalaPlugin.plugin
import org.eclipse.core.runtime.IPath
import org.eclipse.jdt.core.IClasspathEntry
import org.eclipse.jdt.launching.JavaRuntime
import org.eclipse.jdt.core.JavaCore
import org.eclipse.core.resources.IFile
import org.eclipse.core.resources.IStorage
import java.io.IOException
import org.eclipse.core.resources.IFolder
import org.eclipse.jdt.internal.core.JavaModelManager
import org.eclipse.core.runtime.Path
import scala.util.control.Exception._
import org.eclipse.jdt.core.JavaModelException
import scala.tools.eclipse.logging.HasLogger
import java.io.File
import org.eclipse.jdt.internal.core.JavaProject

/** The Scala classpath broken down in the JDK, Scala library and user library.
 *
 *  The Scala compiler needs these entries to be separated for proper setup.
 *
 *  @note All paths are file-system absolute paths. Any path variables or
 *        linked resources are resolved.
 */
case class ScalaClasspath(val jdkPaths: Seq[IPath], // JDK classpath
  val scalaLib: Option[IPath], // scala library
  val userCp: Seq[IPath], // user classpath, excluding the Scala library and JDK
  val scalaVersion: Option[String]) {
  override def toString =
    """
    jdkPaths: %s
    scalaLib: %s
    usercp: %s
    scalaVersion: %s
    
    """.format(jdkPaths, scalaLib, userCp, scalaVersion)

  def scalaLibraryFile: Option[File] =
    scalaLib.map(_.toFile.getAbsoluteFile)

  private def toPath(ps: Seq[IPath]): Seq[File] = ps map (_.toFile.getAbsoluteFile)

  /** Return the full classpath of this project.
   *
   *  It puts the JDK and the Scala library in front of the user classpath.
   */
  def fullClasspath: Seq[File] =
    toPath(jdkPaths) ++ scalaLibraryFile.toSeq ++ toPath(userCp)
}

/** A Scala library definition. 
 * 
 *  @param location  The file-system absolute path to the root of the Scala library
 *  @param version   An option version, retrieved from library.properties, if present
 *  @param isProject Whether the library is provided by a project inside the workspace
 * 
 */
case class ScalaLibrary(location: IPath, version: Option[String], isProject: Boolean)

/** Scala project classpath management. This class is responsible for breaking down the classpath in
 *  JDK entries, Scala library entries, and user entries. It also validates the classpath and
 *  manages the classpath error markers for the given Scala project.
 */
trait ClasspathManagement extends HasLogger { self: ScalaProject =>

  /** Return the Scala classpath breakdown for the managed project. */
  def scalaClasspath: ScalaClasspath = {
    val jdkEntries = jdkPaths
    val cp = javaClasspath.filterNot(jdkEntries.toSet)

    scalaLibraries match {
      case Seq(ScalaLibrary(pf, version, _), _*) => 
        new ScalaClasspath(jdkEntries, Some(pf), cp.filterNot(_ == pf), version)
      case _ => 
        new ScalaClasspath(jdkEntries, None, cp, None)
    }
  }

  /** Return the full classpath of this project.
   *  Each entry is an absolute file-system path.
   */
  @deprecated("Please use `scalaClasspath.fullClasspath instead", "2.1.0")
  def classpath: Seq[IPath] = 
    scalaClasspath.fullClasspath.map(p => new Path(p.getAbsolutePath))
  
  /** Return the classpath entries coming from the JDK.  */
  def jdkPaths: Seq[IPath] = {
    val rawClasspath = javaProject.getRawClasspath()

    rawClasspath.toSeq.flatMap(cp =>
      cp.getEntryKind match {
        case IClasspathEntry.CPE_CONTAINER =>
          val path0 = cp.getPath
          if (!path0.isEmpty && path0.segment(0) == JavaRuntime.JRE_CONTAINER) {
            val container = JavaCore.getClasspathContainer(path0, javaProject)
            Some(container.getClasspathEntries.toSeq.map(_.getPath))
          } else None

        case _ => None

      }).flatten
  }

  /** Return the fully resolved classpath of this project, including the 
   *  Scala library and the JDK entries, in the *project-defined order*.
   *  
   *  The Scala compiler needs the JDK and Scala library on the bootclasspath,
   *  meaning that during compilation the effective order is with these two
   *  components at the head of the list. This method *does not* move them
   *  in front.
   */
  private def javaClasspath: Seq[IPath] = {
    val path = new mutable.LinkedHashSet[IPath]

    def computeClasspath(project: IJavaProject, exportedOnly: Boolean): Unit = {
      val cpes = project.getResolvedClasspath(true)

      for (
        cpe <- cpes if !exportedOnly || cpe.isExported ||
          cpe.getEntryKind == IClasspathEntry.CPE_SOURCE
      ) cpe.getEntryKind match {
        case IClasspathEntry.CPE_PROJECT =>
          val depProject = plugin.workspaceRoot.getProject(cpe.getPath.lastSegment)
          if (JavaProject.hasJavaNature(depProject)) {
            computeClasspath(JavaCore.create(depProject), true)
          }<commit_msg>Gracefully handle unknown JDK classpath containers.<commit_after>package scala.tools.eclipse

import scala.collection.mutable
import org.eclipse.jdt.core.IPackageFragmentRoot
import org.eclipse.jdt.core.IJavaProject
import org.eclipse.core.resources.IMarker
import org.eclipse.jdt.core.IJarEntryResource
import java.util.Properties
import org.eclipse.core.resources.IProject
import org.eclipse.jdt.core.IJavaModelMarker
import org.eclipse.core.runtime.IStatus
import org.eclipse.core.runtime.IProgressMonitor
import org.eclipse.core.runtime.jobs.Job
import org.eclipse.core.resources.IResource
import org.eclipse.core.runtime.Status
import ScalaPlugin.plugin
import org.eclipse.core.runtime.IPath
import org.eclipse.jdt.core.IClasspathEntry
import org.eclipse.jdt.launching.JavaRuntime
import org.eclipse.jdt.core.JavaCore
import org.eclipse.core.resources.IFile
import org.eclipse.core.resources.IStorage
import java.io.IOException
import org.eclipse.core.resources.IFolder
import org.eclipse.jdt.internal.core.JavaModelManager
import org.eclipse.core.runtime.Path
import scala.util.control.Exception._
import org.eclipse.jdt.core.JavaModelException
import scala.tools.eclipse.logging.HasLogger
import java.io.File
import org.eclipse.jdt.internal.core.JavaProject

/** The Scala classpath broken down in the JDK, Scala library and user library.
 *
 *  The Scala compiler needs these entries to be separated for proper setup.
 *
 *  @note All paths are file-system absolute paths. Any path variables or
 *        linked resources are resolved.
 */
case class ScalaClasspath(val jdkPaths: Seq[IPath], // JDK classpath
  val scalaLib: Option[IPath], // scala library
  val userCp: Seq[IPath], // user classpath, excluding the Scala library and JDK
  val scalaVersion: Option[String]) {
  override def toString =
    """
    jdkPaths: %s
    scalaLib: %s
    usercp: %s
    scalaVersion: %s
    
    """.format(jdkPaths, scalaLib, userCp, scalaVersion)

  def scalaLibraryFile: Option[File] =
    scalaLib.map(_.toFile.getAbsoluteFile)

  private def toPath(ps: Seq[IPath]): Seq[File] = ps map (_.toFile.getAbsoluteFile)

  /** Return the full classpath of this project.
   *
   *  It puts the JDK and the Scala library in front of the user classpath.
   */
  def fullClasspath: Seq[File] =
    toPath(jdkPaths) ++ scalaLibraryFile.toSeq ++ toPath(userCp)
}

/** A Scala library definition. 
 * 
 *  @param location  The file-system absolute path to the root of the Scala library
 *  @param version   An option version, retrieved from library.properties, if present
 *  @param isProject Whether the library is provided by a project inside the workspace
 * 
 */
case class ScalaLibrary(location: IPath, version: Option[String], isProject: Boolean)

/** Scala project classpath management. This class is responsible for breaking down the classpath in
 *  JDK entries, Scala library entries, and user entries. It also validates the classpath and
 *  manages the classpath error markers for the given Scala project.
 */
trait ClasspathManagement extends HasLogger { self: ScalaProject =>

  /** Return the Scala classpath breakdown for the managed project. */
  def scalaClasspath: ScalaClasspath = {
    val jdkEntries = jdkPaths
    val cp = javaClasspath.filterNot(jdkEntries.toSet)

    scalaLibraries match {
      case Seq(ScalaLibrary(pf, version, _), _*) => 
        new ScalaClasspath(jdkEntries, Some(pf), cp.filterNot(_ == pf), version)
      case _ => 
        new ScalaClasspath(jdkEntries, None, cp, None)
    }
  }

  /** Return the full classpath of this project.
   *  Each entry is an absolute file-system path.
   */
  @deprecated("Please use `scalaClasspath.fullClasspath instead", "2.1.0")
  def classpath: Seq[IPath] = 
    scalaClasspath.fullClasspath.map(p => new Path(p.getAbsolutePath))
  
  /** Return the classpath entries coming from the JDK.  */
  def jdkPaths: Seq[IPath] = {
    val rawClasspath = javaProject.getRawClasspath()

    rawClasspath.toSeq.flatMap(cp =>
      cp.getEntryKind match {
        case IClasspathEntry.CPE_CONTAINER =>
          val path0 = cp.getPath
          if (!path0.isEmpty && path0.segment(0) == JavaRuntime.JRE_CONTAINER) {
            val container = JavaCore.getClasspathContainer(path0, javaProject)
            Option(container).map(_.getClasspathEntries.toSeq.map(_.getPath))
          } else None

        case _ => None

      }).flatten
  }

  /** Return the fully resolved classpath of this project, including the 
   *  Scala library and the JDK entries, in the *project-defined order*.
   *  
   *  The Scala compiler needs the JDK and Scala library on the bootclasspath,
   *  meaning that during compilation the effective order is with these two
   *  components at the head of the list. This method *does not* move them
   *  in front.
   */
  private def javaClasspath: Seq[IPath] = {
    val path = new mutable.LinkedHashSet[IPath]

    def computeClasspath(project: IJavaProject, exportedOnly: Boolean): Unit = {
      val cpes = project.getResolvedClasspath(true)

      for (
        cpe <- cpes if !exportedOnly || cpe.isExported ||
          cpe.getEntryKind == IClasspathEntry.CPE_SOURCE
      ) cpe.getEntryKind match {
        case IClasspathEntry.CPE_PROJECT =>
          val depProject = plugin.workspaceRoot.getProject(cpe.getPath.lastSegment)
          if (JavaProject.hasJavaNature(depProject)) {
            computeClasspath(JavaCore.create(depProject), true)
          }
{'fraction_non_alphanumeric': 0.08998067899530776, 'fraction_numerical': 0.001472076547980495, 'mean_word_length': 3.6334185848252343, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 19, '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': '4941795', 'n_tokens_mistral': 3314, 'n_tokens_neox': 3231, 'n_words': 929}