Permalink
Cannot retrieve contributors at this time
238 lines (204 sloc)
8.11 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
codeql-action/node_modules/@eslint/eslintrc/lib/config-array/ignore-pattern.js
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @fileoverview `IgnorePattern` class. | |
* | |
* `IgnorePattern` class has the set of glob patterns and the base path. | |
* | |
* It provides two static methods. | |
* | |
* - `IgnorePattern.createDefaultIgnore(cwd)` | |
* Create the default predicate function. | |
* - `IgnorePattern.createIgnore(ignorePatterns)` | |
* Create the predicate function from multiple `IgnorePattern` objects. | |
* | |
* It provides two properties and a method. | |
* | |
* - `patterns` | |
* The glob patterns that ignore to lint. | |
* - `basePath` | |
* The base path of the glob patterns. If absolute paths existed in the | |
* glob patterns, those are handled as relative paths to the base path. | |
* - `getPatternsRelativeTo(basePath)` | |
* Get `patterns` as modified for a given base path. It modifies the | |
* absolute paths in the patterns as prepending the difference of two base | |
* paths. | |
* | |
* `ConfigArrayFactory` creates `IgnorePattern` objects when it processes | |
* `ignorePatterns` properties. | |
* | |
* @author Toru Nagashima <https://github.com/mysticatea> | |
*/ | |
//------------------------------------------------------------------------------ | |
// Requirements | |
//------------------------------------------------------------------------------ | |
import assert from "assert"; | |
import path from "path"; | |
import ignore from "ignore"; | |
import debugOrig from "debug"; | |
const debug = debugOrig("eslintrc:ignore-pattern"); | |
/** @typedef {ReturnType<import("ignore").default>} Ignore */ | |
//------------------------------------------------------------------------------ | |
// Helpers | |
//------------------------------------------------------------------------------ | |
/** | |
* Get the path to the common ancestor directory of given paths. | |
* @param {string[]} sourcePaths The paths to calculate the common ancestor. | |
* @returns {string} The path to the common ancestor directory. | |
*/ | |
function getCommonAncestorPath(sourcePaths) { | |
let result = sourcePaths[0]; | |
for (let i = 1; i < sourcePaths.length; ++i) { | |
const a = result; | |
const b = sourcePaths[i]; | |
// Set the shorter one (it's the common ancestor if one includes the other). | |
result = a.length < b.length ? a : b; | |
// Set the common ancestor. | |
for (let j = 0, lastSepPos = 0; j < a.length && j < b.length; ++j) { | |
if (a[j] !== b[j]) { | |
result = a.slice(0, lastSepPos); | |
break; | |
} | |
if (a[j] === path.sep) { | |
lastSepPos = j; | |
} | |
} | |
} | |
let resolvedResult = result || path.sep; | |
// if Windows common ancestor is root of drive must have trailing slash to be absolute. | |
if (resolvedResult && resolvedResult.endsWith(":") && process.platform === "win32") { | |
resolvedResult += path.sep; | |
} | |
return resolvedResult; | |
} | |
/** | |
* Make relative path. | |
* @param {string} from The source path to get relative path. | |
* @param {string} to The destination path to get relative path. | |
* @returns {string} The relative path. | |
*/ | |
function relative(from, to) { | |
const relPath = path.relative(from, to); | |
if (path.sep === "/") { | |
return relPath; | |
} | |
return relPath.split(path.sep).join("/"); | |
} | |
/** | |
* Get the trailing slash if existed. | |
* @param {string} filePath The path to check. | |
* @returns {string} The trailing slash if existed. | |
*/ | |
function dirSuffix(filePath) { | |
const isDir = ( | |
filePath.endsWith(path.sep) || | |
(process.platform === "win32" && filePath.endsWith("/")) | |
); | |
return isDir ? "/" : ""; | |
} | |
const DefaultPatterns = Object.freeze(["/**/node_modules/*"]); | |
const DotPatterns = Object.freeze([".*", "!.eslintrc.*", "!../"]); | |
//------------------------------------------------------------------------------ | |
// Public | |
//------------------------------------------------------------------------------ | |
class IgnorePattern { | |
/** | |
* The default patterns. | |
* @type {string[]} | |
*/ | |
static get DefaultPatterns() { | |
return DefaultPatterns; | |
} | |
/** | |
* Create the default predicate function. | |
* @param {string} cwd The current working directory. | |
* @returns {((filePath:string, dot:boolean) => boolean) & {basePath:string; patterns:string[]}} | |
* The preficate function. | |
* The first argument is an absolute path that is checked. | |
* The second argument is the flag to not ignore dotfiles. | |
* If the predicate function returned `true`, it means the path should be ignored. | |
*/ | |
static createDefaultIgnore(cwd) { | |
return this.createIgnore([new IgnorePattern(DefaultPatterns, cwd)]); | |
} | |
/** | |
* Create the predicate function from multiple `IgnorePattern` objects. | |
* @param {IgnorePattern[]} ignorePatterns The list of ignore patterns. | |
* @returns {((filePath:string, dot?:boolean) => boolean) & {basePath:string; patterns:string[]}} | |
* The preficate function. | |
* The first argument is an absolute path that is checked. | |
* The second argument is the flag to not ignore dotfiles. | |
* If the predicate function returned `true`, it means the path should be ignored. | |
*/ | |
static createIgnore(ignorePatterns) { | |
debug("Create with: %o", ignorePatterns); | |
const basePath = getCommonAncestorPath(ignorePatterns.map(p => p.basePath)); | |
const patterns = [].concat( | |
...ignorePatterns.map(p => p.getPatternsRelativeTo(basePath)) | |
); | |
const ig = ignore({ allowRelativePaths: true }).add([...DotPatterns, ...patterns]); | |
const dotIg = ignore({ allowRelativePaths: true }).add(patterns); | |
debug(" processed: %o", { basePath, patterns }); | |
return Object.assign( | |
(filePath, dot = false) => { | |
assert(path.isAbsolute(filePath), "'filePath' should be an absolute path."); | |
const relPathRaw = relative(basePath, filePath); | |
const relPath = relPathRaw && (relPathRaw + dirSuffix(filePath)); | |
const adoptedIg = dot ? dotIg : ig; | |
const result = relPath !== "" && adoptedIg.ignores(relPath); | |
debug("Check", { filePath, dot, relativePath: relPath, result }); | |
return result; | |
}, | |
{ basePath, patterns } | |
); | |
} | |
/** | |
* Initialize a new `IgnorePattern` instance. | |
* @param {string[]} patterns The glob patterns that ignore to lint. | |
* @param {string} basePath The base path of `patterns`. | |
*/ | |
constructor(patterns, basePath) { | |
assert(path.isAbsolute(basePath), "'basePath' should be an absolute path."); | |
/** | |
* The glob patterns that ignore to lint. | |
* @type {string[]} | |
*/ | |
this.patterns = patterns; | |
/** | |
* The base path of `patterns`. | |
* @type {string} | |
*/ | |
this.basePath = basePath; | |
/** | |
* If `true` then patterns which don't start with `/` will match the paths to the outside of `basePath`. Defaults to `false`. | |
* | |
* It's set `true` for `.eslintignore`, `package.json`, and `--ignore-path` for backward compatibility. | |
* It's `false` as-is for `ignorePatterns` property in config files. | |
* @type {boolean} | |
*/ | |
this.loose = false; | |
} | |
/** | |
* Get `patterns` as modified for a given base path. It modifies the | |
* absolute paths in the patterns as prepending the difference of two base | |
* paths. | |
* @param {string} newBasePath The base path. | |
* @returns {string[]} Modifired patterns. | |
*/ | |
getPatternsRelativeTo(newBasePath) { | |
assert(path.isAbsolute(newBasePath), "'newBasePath' should be an absolute path."); | |
const { basePath, loose, patterns } = this; | |
if (newBasePath === basePath) { | |
return patterns; | |
} | |
const prefix = `/${relative(newBasePath, basePath)}`; | |
return patterns.map(pattern => { | |
const negative = pattern.startsWith("!"); | |
const head = negative ? "!" : ""; | |
const body = negative ? pattern.slice(1) : pattern; | |
if (body.startsWith("/") || body.startsWith("../")) { | |
return `${head}${prefix}${body}`; | |
} | |
return loose ? pattern : `${head}${prefix}/**/${body}`; | |
}); | |
} | |
} | |
export { IgnorePattern }; |