All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.joern.javasrc2cpg.util.PackageRootFinder.scala Maven / Gradle / Ivy

There is a newer version: 4.0.80
Show newest version
package io.joern.javasrc2cpg.util

import better.files.File

import java.nio.file.Path
import scala.collection.mutable
import scala.util.matching.Regex

object PackageRootFinder {

  def packageRootsFromFiles(inputPath: Path, fileInfos: List[SourceParser.FileInfo]): List[Path] = {
    // Files are sorted by path length to efficiently handle the non-standard package structure case described
    // below. If the `parentDirectory` in that case is closest to the input path, then the largest number of
    // files will be removed from the `filesToCheck` list.
    var filesToCheck = mutable.ListBuffer.from(fileInfos).sortBy(_.relativePath.getNameCount)
    val discoveredRoots: mutable.ListBuffer[Path] = mutable.ListBuffer.empty

    while (filesToCheck.nonEmpty) {
      val fileInfo = filesToCheck.remove(0)
      // If filePath.getParent is null, then parent is actually the inputPath, but in this case
      // we don't want to "break out" of the specified input directory, so just use the relative
      // path `.`, which is equivalent to the inputPath since it is relative to the input path
      val dotPath         = Path.of(".")
      val parentDirectory = Option(fileInfo.relativePath.getParent).getOrElse(dotPath)

      val discoveredRoot = fileInfo.packageName match {
        case Some(packageName) =>
          val packageDirs = Path.of(packageName.replaceAll(raw"\.", "/"))

          if (parentDirectory.endsWith(packageDirs))
            parentDirectory.subpath(0, parentDirectory.getNameCount - packageDirs.getNameCount)
          else
            // In this case, the package name doesn't match the given directory structure, either
            // because the project doesn't follow convention or because the given inputPath is
            // already a subdirectory of the package tree (for example, `projectRoot/src/main/java/com/`)
            fileInfo.relativePath

        case None => fileInfo.relativePath
      }

      discoveredRoots.addOne(discoveredRoot)
      if (discoveredRoot != dotPath) {
        filesToCheck = filesToCheck.filterNot(info => info.relativePath.startsWith(discoveredRoot))
      }
    }

    discoveredRoots.toList
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy