fun reallyGlob()

in plugin-bazel/src/main/kotlin/org/jetbrains/bazel/languages/starlark/globbing/StarlarkGlob.kt [466:575]


    fun reallyGlob(
      base: VirtualFile,
      baseIsDirectory: Boolean,
      patternParts: Array<String>,
      idx: Int,
      excludeDirectories: Boolean,
      results: MutableCollection<VirtualFile>,
      cache: Cache<String, Pattern>,
      dirPred: Predicate<VirtualFile>,
    ) {
      ProgressManager.checkCanceled()
      if (baseIsDirectory && !dirPred.test(base)) {
        return
      }

      if (idx == patternParts.size) { // Base case.
        if (!(excludeDirectories && baseIsDirectory)) {
          results.add(base)
        }
        return
      }

      if (!baseIsDirectory) {
        // Nothing to find here.
        return
      }

      val pattern = patternParts[idx]

      // ** is special: it can match nothing at all.
      // For example, x/** matches x, **/y matches y, and x/**/y matches x/y.
      if ("**" == pattern) {
        queueGlob(
          base,
          baseIsDirectory,
          patternParts,
          idx + 1,
          excludeDirectories,
          results,
          cache,
          dirPred,
        )
      }

      if (!pattern.contains("*") && !pattern.contains("?")) {
        val child = base.findChild(pattern)
        if (child == null) return
        val childIsDir = child.isDirectory
        if (!childIsDir && !child.isFile) {
          // The file is a dangling symlink, fifo, does not exist, etc.
          return
        }

        queueGlob(
          child,
          childIsDir,
          patternParts,
          idx + 1,
          excludeDirectories,
          results,
          cache,
          dirPred,
        )
        return
      }

      val children = getChildren(base)
      if (children == null) {
        return
      }
      for (child in children) {
        val childIsDir = child.isDirectory

        if ("**" == pattern) {
          // Recurse without shifting the pattern.
          if (childIsDir) {
            queueGlob(
              child,
              childIsDir,
              patternParts,
              idx,
              excludeDirectories,
              results,
              cache,
              dirPred,
            )
          }
        }
        if (matches(pattern, child.name, cache)) {
          // Recurse and consume one segment of the pattern.
          if (childIsDir) {
            queueGlob(
              child,
              childIsDir,
              patternParts,
              idx + 1,
              excludeDirectories,
              results,
              cache,
              dirPred,
            )
          } else {
            // Instead of using an async call, just repeat the base case above.
            if (idx + 1 == patternParts.size) {
              results.add(child)
            }
          }
        }
      }
    }