diff options
Diffstat (limited to 'node_modules/tslint/lib/configuration.js')
-rw-r--r-- | node_modules/tslint/lib/configuration.js | 194 |
1 files changed, 118 insertions, 76 deletions
diff --git a/node_modules/tslint/lib/configuration.js b/node_modules/tslint/lib/configuration.js index a6064f015..1150d68da 100644 --- a/node_modules/tslint/lib/configuration.js +++ b/node_modules/tslint/lib/configuration.js @@ -17,11 +17,18 @@ */ Object.defineProperty(exports, "__esModule", { value: true }); var fs = require("fs"); +var yaml = require("js-yaml"); +var os = require("os"); var path = require("path"); var resolve = require("resolve"); var error_1 = require("./error"); var utils_1 = require("./utils"); -exports.CONFIG_FILENAME = "tslint.json"; +// Note: eslint prefers yaml over json, while tslint prefers json over yaml +// for backward-compatibility. +exports.JSON_CONFIG_FILENAME = "tslint.json"; +/** @deprecated use `JSON_CONFIG_FILENAME` or `CONFIG_FILENAMES` instead. */ +exports.CONFIG_FILENAME = exports.JSON_CONFIG_FILENAME; +exports.CONFIG_FILENAMES = [exports.JSON_CONFIG_FILENAME, "tslint.yaml", "tslint.yml"]; exports.DEFAULT_CONFIG = { defaultSeverity: "error", extends: ["tslint:recommended"], @@ -75,14 +82,15 @@ function findConfigurationPath(suppliedConfigFilePath, inputFilePath) { inputFilePath = path.dirname(inputFilePath); } // search for tslint.json from input file location - var configFilePath = findup(exports.CONFIG_FILENAME, path.resolve(inputFilePath)); + var configFilePath = findup(exports.CONFIG_FILENAMES, path.resolve(inputFilePath)); if (configFilePath !== undefined) { return configFilePath; } // search for tslint.json in home directory - var homeDir = getHomeDir(); - if (homeDir != undefined) { - configFilePath = path.join(homeDir, exports.CONFIG_FILENAME); + var homeDir = os.homedir(); + for (var _i = 0, CONFIG_FILENAMES_1 = exports.CONFIG_FILENAMES; _i < CONFIG_FILENAMES_1.length; _i++) { + var configFilename = CONFIG_FILENAMES_1[_i]; + configFilePath = path.join(homeDir, configFilename); if (fs.existsSync(configFilePath)) { return path.resolve(configFilePath); } @@ -93,10 +101,11 @@ function findConfigurationPath(suppliedConfigFilePath, inputFilePath) { } exports.findConfigurationPath = findConfigurationPath; /** - * Find a file by name in a directory or any ancestory directory. + * Find a file by names in a directory or any ancestor directory. + * Will try each filename in filenames before recursing to a parent directory. * This is case-insensitive, so it can find 'TsLiNt.JsOn' when searching for 'tslint.json'. */ -function findup(filename, directory) { +function findup(filenames, directory) { while (true) { var res = findFile(directory); if (res !== undefined) { @@ -109,17 +118,27 @@ function findup(filename, directory) { directory = parent; } function findFile(cwd) { - if (fs.existsSync(path.join(cwd, filename))) { - return filename; - } - // TODO: remove in v6.0.0 - // Try reading in the entire directory and looking for a file with different casing. - var filenameLower = filename.toLowerCase(); - var result = fs.readdirSync(cwd).find(function (entry) { return entry.toLowerCase() === filenameLower; }); - if (result !== undefined) { - error_1.showWarningOnce("Using mixed case tslint.json is deprecated. Found: " + path.join(cwd, result)); + var dirFiles = fs.readdirSync(cwd); + var _loop_1 = function (filename) { + var index = dirFiles.indexOf(filename); + if (index > -1) { + return { value: filename }; + } + // TODO: remove in v6.0.0 + // Try reading in the entire directory and looking for a file with different casing. + var result = dirFiles.find(function (entry) { return entry.toLowerCase() === filename; }); + if (result !== undefined) { + error_1.showWarningOnce("Using mixed case " + filename + " is deprecated. Found: " + path.join(cwd, result)); + return { value: result }; + } + }; + for (var _i = 0, filenames_1 = filenames; _i < filenames_1.length; _i++) { + var filename = filenames_1[_i]; + var state_1 = _loop_1(filename); + if (typeof state_1 === "object") + return state_1.value; } - return result; + return undefined; } } /** @@ -129,46 +148,53 @@ function findup(filename, directory) { * './path/to/config' will be treated as a relative path * 'path/to/config' will attempt to load a to/config file inside a node module named path * @param configFilePath The configuration to load - * @param originalFilePath The entry point configuration file + * @param originalFilePath (deprecated) The entry point configuration file * @returns a configuration object for TSLint loaded from the file at configFilePath */ -function loadConfigurationFromPath(configFilePath, originalFilePath) { - if (originalFilePath === void 0) { originalFilePath = configFilePath; } +function loadConfigurationFromPath(configFilePath, _originalFilePath) { if (configFilePath == undefined) { return exports.DEFAULT_CONFIG; } else { var resolvedConfigFilePath = resolveConfigurationPath(configFilePath); - var rawConfigFile = void 0; - if (path.extname(resolvedConfigFilePath) === ".json") { - var fileContent = utils_1.stripComments(fs.readFileSync(resolvedConfigFilePath) - .toString() - .replace(/^\uFEFF/, "")); - try { - rawConfigFile = JSON.parse(fileContent); + var rawConfigFile = readConfigurationFile(resolvedConfigFilePath); + return parseConfigFile(rawConfigFile, path.dirname(resolvedConfigFilePath), readConfigurationFile); + } +} +exports.loadConfigurationFromPath = loadConfigurationFromPath; +/** Reads the configuration file from disk and parses it as raw JSON, YAML or JS depending on the extension. */ +function readConfigurationFile(filepath) { + var resolvedConfigFileExt = path.extname(filepath); + if (/\.(json|ya?ml)/.test(resolvedConfigFileExt)) { + var fileContent = fs.readFileSync(filepath, "utf8").replace(/^\uFEFF/, ""); + try { + if (resolvedConfigFileExt === ".json") { + return JSON.parse(utils_1.stripComments(fileContent)); } - catch (e) { - var error = e; - // include the configuration file being parsed in the error since it may differ from the directly referenced config - throw configFilePath === originalFilePath ? error : new Error(error.message + " in " + configFilePath); + else { + return yaml.safeLoad(fileContent, { + // Note: yaml.LoadOptions expects a schema value of type "any", + // but this trips up the no-unsafe-any rule. + // tslint:disable-next-line:no-unsafe-any + schema: yaml.JSON_SCHEMA, + strict: true, + }); } } - else { - rawConfigFile = require(resolvedConfigFilePath); - delete require.cache[resolvedConfigFilePath]; + catch (e) { + var error = e; + // include the configuration file being parsed in the error since it may differ from the directly referenced config + throw new Error(error.message + " in " + filepath); } - var configFileDir_1 = path.dirname(resolvedConfigFilePath); - var configFile = parseConfigFile(rawConfigFile, configFileDir_1); - // load configurations, in order, using their identifiers or relative paths - // apply the current configuration last by placing it last in this array - var configs = configFile.extends.map(function (name) { - var nextConfigFilePath = resolveConfigurationPath(name, configFileDir_1); - return loadConfigurationFromPath(nextConfigFilePath, originalFilePath); - }).concat([configFile]); - return configs.reduce(extendConfigurationFile, exports.EMPTY_CONFIG); + } + else { + var rawConfigFile = require(filepath); + // tslint:disable-next-line no-dynamic-delete + delete require.cache[filepath]; + return rawConfigFile; } } -exports.loadConfigurationFromPath = loadConfigurationFromPath; +exports.readConfigurationFile = readConfigurationFile; /** * Resolve configuration file path or node_module reference * @param filePath Relative ("./path"), absolute ("/path"), node module ("path"), or built-in ("tslint:path") @@ -244,23 +270,11 @@ function extendConfigurationFile(targetConfig, nextConfigSource) { }; } exports.extendConfigurationFile = extendConfigurationFile; -function getHomeDir() { - var environment = global.process.env; - var paths = [ - environment.USERPROFILE, - environment.HOME, - environment.HOMEPATH, - environment.HOMEDRIVE + environment.HOMEPATH, - ]; - for (var _i = 0, paths_1 = paths; _i < paths_1.length; _i++) { - var homePath = paths_1[_i]; - if (homePath !== undefined && fs.existsSync(homePath)) { - return homePath; - } - } - return undefined; -} -// returns the absolute path (contrary to what the name implies) +/** + * returns the absolute path (contrary to what the name implies) + * + * @deprecated use `path.resolve` instead + */ function getRelativePath(directory, relativeTo) { if (directory != undefined) { var basePath = relativeTo !== undefined ? relativeTo : process.cwd(); @@ -293,15 +307,14 @@ function getRulesDirectories(directories, relativeTo) { // swallow error and fallback to using directory as path } } - var absolutePath = getRelativePath(dir, relativeTo); + var absolutePath = relativeTo === undefined ? path.resolve(dir) : path.resolve(relativeTo, dir); if (absolutePath !== undefined) { if (!fs.existsSync(absolutePath)) { throw new error_1.FatalError("Could not find custom rule directory: " + dir); } } return absolutePath; - }) - .filter(function (dir) { return dir !== undefined; }); + }); } exports.getRulesDirectories = getRulesDirectories; /** @@ -375,36 +388,65 @@ function parseRuleOptions(ruleConfigValue, rawDefaultRuleSeverity) { }; } /** - * Parses a config file and normalizes legacy config settings + * Parses a config file and normalizes legacy config settings. + * If `configFileDir` and `readConfig` are provided, this function will load all base configs and reduce them to the final configuration. * * @param configFile The raw object read from the JSON of a config file * @param configFileDir The directory of the config file + * @param readConfig Will be used to load all base configurations while parsing. The function is called with the resolved path. */ -function parseConfigFile(configFile, configFileDir) { - return { - extends: utils_1.arrayify(configFile.extends), - jsRules: parseRules(configFile.jsRules), - linterOptions: parseLinterOptions(configFile.linterOptions), - rules: parseRules(configFile.rules), - rulesDirectory: getRulesDirectories(configFile.rulesDirectory, configFileDir), - }; +function parseConfigFile(configFile, configFileDir, readConfig) { + var defaultSeverity = configFile.defaultSeverity; + if (readConfig === undefined || configFileDir === undefined) { + return parse(configFile, configFileDir); + } + return loadExtendsRecursive(configFile, configFileDir) + .map(function (_a) { + var dir = _a.dir, config = _a.config; + return parse(config, dir); + }) + .reduce(extendConfigurationFile, exports.EMPTY_CONFIG); + /** Read files in order, depth first, and assign `defaultSeverity` (last config in extends wins). */ + function loadExtendsRecursive(raw, dir) { + var configs = []; + for (var _i = 0, _a = utils_1.arrayify(raw.extends); _i < _a.length; _i++) { + var relativePath = _a[_i]; + var resolvedPath = resolveConfigurationPath(relativePath, dir); + var extendedRaw = readConfig(resolvedPath); + configs.push.apply(configs, loadExtendsRecursive(extendedRaw, path.dirname(resolvedPath))); + } + if (raw.defaultSeverity !== undefined) { + defaultSeverity = raw.defaultSeverity; + } + configs.push({ dir: dir, config: raw }); + return configs; + } + function parse(config, dir) { + return { + extends: utils_1.arrayify(config.extends), + jsRules: parseRules(config.jsRules), + linterOptions: parseLinterOptions(config.linterOptions, dir), + rules: parseRules(config.rules), + rulesDirectory: getRulesDirectories(config.rulesDirectory, dir), + }; + } function parseRules(config) { var map = new Map(); if (config !== undefined) { for (var ruleName in config) { if (utils_1.hasOwnProperty(config, ruleName)) { - map.set(ruleName, parseRuleOptions(config[ruleName], configFile.defaultSeverity)); + map.set(ruleName, parseRuleOptions(config[ruleName], defaultSeverity)); } } } return map; } - function parseLinterOptions(raw) { + function parseLinterOptions(raw, dir) { if (raw === undefined || raw.exclude === undefined) { return {}; } return { - exclude: utils_1.arrayify(raw.exclude).map(function (pattern) { return configFileDir === undefined ? path.resolve(pattern) : path.resolve(configFileDir, pattern); }), + exclude: utils_1.arrayify(raw.exclude).map(function (pattern) { return dir === undefined ? path.resolve(pattern) : path.resolve(dir, pattern); }), }; } } |