function getWildcardDirectoryFromSpec(spec, useCaseSensitiveFileNames) {
    const match = wildcardDirectoryPattern.exec(spec);
    if (match) {
      const questionWildcardIndex = spec.indexOf("?");
      const starWildcardIndex = spec.indexOf("*");
      const lastDirectorySeperatorIndex = spec.lastIndexOf(directorySeparator);
      return {
        key: useCaseSensitiveFileNames ? match[0] : toFileNameLowerCase(match[0]),
        flags: questionWildcardIndex !== -1 && questionWildcardIndex < lastDirectorySeperatorIndex || starWildcardIndex !== -1 && starWildcardIndex < lastDirectorySeperatorIndex ? 1 /* Recursive */ : 0 /* None */
      };
    }
    if (isImplicitGlob(spec.substring(spec.lastIndexOf(directorySeparator) + 1))) {
      return {
        key: removeTrailingDirectorySeparator(useCaseSensitiveFileNames ? spec : toFileNameLowerCase(spec)),
        flags: 1 /* Recursive */
      };
    }
    return void 0;
  }
/");
    if (wildcardIndex === -1) {
      return false;
    }
    const lastDotIndex = endsWith(s, "/..") ? s.length : s.lastIndexOf("/../");
    return lastDotIndex > wildcardIndex;
  }
  function matchesExclude(pathToCheck, excludeSpecs, useCaseSensitiveFileNames, currentDirectory) {
    return matchesExcludeWorker(
      pathToCheck,
      filter(excludeSpecs, (spec) => !invalidDotDotAfterRecursiveWildcard(spec)),
      useCaseSensitiveFileNames,
      currentDirectory
    );
  }
  function matchesExcludeWorker(pathToCheck, excludeSpecs, useCaseSensitiveFileNames, currentDirectory, basePath) {
    const excludePattern = getRegularExpressionForWildcard(excludeSpecs, combinePaths(normalizePath(currentDirectory), basePath), "exclude");
    const excludeRegex = excludePattern && getRegexFromPattern(excludePattern, useCaseSensitiveFileNames);
    if (!excludeRegex)
      return false;
    if (excludeRegex.test(pathToCheck))
      return true;
    return !hasExtension(pathToCheck) && excludeRegex.test(ensureTrailingDirectorySeparator(pathToCheck));
  }
  function validateSpecs(specs, errors, disallowTrailingRecursion, jsonSourceFile, specKey) {
    return specs.filter((spec) => {
      if (!isString(spec))
        return false;
      const diag2 = specToDiagnostic(spec, disallowTrailingRecursion);
      if (diag2 !== void 0) {
        errors.push(createDiagnostic(...diag2));
      }
      return diag2 === void 0;
    });
    function createDiagnostic(message, spec) {
      const element = getTsConfigPropArrayElementValue(jsonSourceFile, specKey, spec);
      return element ? createDiagnosticForNodeInSourceFile(jsonSourceFile, element, message, spec) : createCompilerDiagnostic(message, spec);
    }
  }
  function specToDiagnostic(spec, disallowTrailingRecursion) {
    Debug.assert(typeof spec === "string");
    if (disallowTrailingRecursion && invalidTrailingRecursionPattern.test(spec)) {
      return [Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec];
    } else if (invalidDotDotAfterRecursiveWildcard(spec)) {
      return [Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec];
    }
  }
  function getWildcardDirectories({ validatedIncludeSpecs: include, validatedExcludeSpecs: exclude }, path, useCaseSensitiveFileNames) {
    const rawExcludeRegex = getRegularExpressionForWildcard(exclude, path, "exclude");
    const excludeRegex = rawExcludeRegex && new RegExp(rawExcludeRegex, useCaseSensitiveFileNames ? "" : "i");
    const wildcardDirectories = {};
    if (include !== void 0) {
      const recursiveKeys = [];
      for (const file of include) {
        const spec = normalizePath(combinePaths(path, file));
        if (excludeRegex && excludeRegex.test(spec)) {
          continue;
        }
        const match = getWildcardDirectoryFromSpec(spec, useCaseSensitiveFileNames);
        if (match) {
          const { key, flags } = match;
          const existingFlags = wildcardDirectories[key];
          if (existingFlags === void 0 || existingFlags < flags) {
            wildcardDirectories[key] = flags;
            if (flags === 1 /* Recursive