aboutsummaryrefslogtreecommitdiff
path: root/node_modules/tslint/lib/configuration.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/tslint/lib/configuration.js')
-rw-r--r--node_modules/tslint/lib/configuration.js439
1 files changed, 439 insertions, 0 deletions
diff --git a/node_modules/tslint/lib/configuration.js b/node_modules/tslint/lib/configuration.js
new file mode 100644
index 000000000..39e6569ab
--- /dev/null
+++ b/node_modules/tslint/lib/configuration.js
@@ -0,0 +1,439 @@
+"use strict";
+/**
+ * @license
+ * Copyright 2013 Palantir Technologies, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+Object.defineProperty(exports, "__esModule", { value: true });
+var fs = require("fs");
+var path = require("path");
+var resolve = require("resolve");
+var error_1 = require("./error");
+var utils_1 = require("./utils");
+exports.CONFIG_FILENAME = "tslint.json";
+exports.DEFAULT_CONFIG = {
+ defaultSeverity: "error",
+ extends: ["tslint:recommended"],
+ jsRules: new Map(),
+ rules: new Map(),
+ rulesDirectory: [],
+};
+exports.EMPTY_CONFIG = {
+ defaultSeverity: "error",
+ extends: [],
+ jsRules: new Map(),
+ rules: new Map(),
+ rulesDirectory: [],
+};
+var BUILT_IN_CONFIG = /^tslint:(.*)$/;
+/**
+ * Searches for a TSLint configuration and returns the data from the config.
+ * @param configFile A path to a config file, this can be null if the location of a config is not known
+ * @param inputFilePath A path containing the current file being linted. This is the starting location
+ * of the search for a configuration.
+ * @returns Load status for a TSLint configuration object
+ */
+function findConfiguration(configFile, inputFilePath) {
+ var configPath = findConfigurationPath(configFile, inputFilePath);
+ var loadResult = { path: configPath };
+ try {
+ loadResult.results = loadConfigurationFromPath(configPath);
+ return loadResult;
+ }
+ catch (error) {
+ throw new error_1.FatalError("Failed to load " + configPath + ": " + error.message, error);
+ }
+}
+exports.findConfiguration = findConfiguration;
+/**
+ * Searches for a TSLint configuration and returns the path to it.
+ * Could return undefined if not configuration is found.
+ * @param suppliedConfigFilePath A path to an known config file supplied by a user. Pass null here if
+ * the location of the config file is not known and you want to search for one.
+ * @param inputFilePath A path to the current file being linted. This is the starting location
+ * of the search for a configuration.
+ * @returns An absolute path to a tslint.json file
+ * or undefined if neither can be found.
+ */
+function findConfigurationPath(suppliedConfigFilePath, inputFilePath) {
+ if (suppliedConfigFilePath != null) {
+ if (!fs.existsSync(suppliedConfigFilePath)) {
+ throw new Error("Could not find config file at: " + path.resolve(suppliedConfigFilePath));
+ }
+ else {
+ return path.resolve(suppliedConfigFilePath);
+ }
+ }
+ else {
+ // convert to dir if it's a file or doesn't exist
+ var useDirName = false;
+ try {
+ var stats = fs.statSync(inputFilePath);
+ if (stats.isFile()) {
+ useDirName = true;
+ }
+ }
+ catch (e) {
+ // throws if file doesn't exist
+ useDirName = true;
+ }
+ if (useDirName) {
+ inputFilePath = path.dirname(inputFilePath);
+ }
+ // search for tslint.json from input file location
+ var configFilePath = findup(exports.CONFIG_FILENAME, inputFilePath);
+ if (configFilePath !== undefined) {
+ return path.resolve(configFilePath);
+ }
+ // search for tslint.json in home directory
+ var homeDir = getHomeDir();
+ if (homeDir != null) {
+ configFilePath = path.join(homeDir, exports.CONFIG_FILENAME);
+ if (fs.existsSync(configFilePath)) {
+ return path.resolve(configFilePath);
+ }
+ }
+ // no path could be found
+ return undefined;
+ }
+}
+exports.findConfigurationPath = findConfigurationPath;
+/**
+ * Find a file by name in a directory or any ancestory directory.
+ * This is case-insensitive, so it can find 'TsLiNt.JsOn' when searching for 'tslint.json'.
+ */
+function findup(filename, directory) {
+ while (true) {
+ var res = findFile(directory);
+ if (res !== undefined) {
+ return path.join(directory, res);
+ }
+ var parent = path.dirname(directory);
+ if (parent === directory) {
+ return undefined;
+ }
+ 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));
+ }
+ return result;
+ }
+}
+/**
+ * Used Node semantics to load a configuration file given configFilePath.
+ * For example:
+ * '/path/to/config' will be treated as an absolute path
+ * './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
+ * @returns a configuration object for TSLint loaded from the file at configFilePath
+ */
+function loadConfigurationFromPath(configFilePath, originalFilePath) {
+ if (originalFilePath === void 0) { originalFilePath = configFilePath; }
+ if (configFilePath == null) {
+ 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);
+ }
+ 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 {
+ rawConfigFile = require(resolvedConfigFilePath);
+ delete require.cache[resolvedConfigFilePath];
+ }
+ 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);
+ }
+}
+exports.loadConfigurationFromPath = loadConfigurationFromPath;
+/**
+ * Resolve configuration file path or node_module reference
+ * @param filePath Relative ("./path"), absolute ("/path"), node module ("path"), or built-in ("tslint:path")
+ */
+function resolveConfigurationPath(filePath, relativeTo) {
+ var matches = filePath.match(BUILT_IN_CONFIG);
+ var isBuiltInConfig = matches != null && matches.length > 0;
+ if (isBuiltInConfig) {
+ var configName = matches[1];
+ try {
+ return require.resolve("./configs/" + configName);
+ }
+ catch (err) {
+ throw new Error(filePath + " is not a built-in config, try \"tslint:recommended\" instead.");
+ }
+ }
+ var basedir = relativeTo !== undefined ? relativeTo : process.cwd();
+ try {
+ return resolve.sync(filePath, { basedir: basedir });
+ }
+ catch (err) {
+ try {
+ return require.resolve(filePath);
+ }
+ catch (err) {
+ // tslint:disable-next-line prefer-template (fixed in 5.3)
+ throw new Error("Invalid \"extends\" configuration value - could not require \"" + filePath + "\". " +
+ "Review the Node lookup algorithm (https://nodejs.org/api/modules.html#modules_all_together) " +
+ "for the approximate method TSLint uses to find the referenced configuration file.");
+ }
+ }
+}
+function extendConfigurationFile(targetConfig, nextConfigSource) {
+ function combineProperties(targetProperty, nextProperty) {
+ var combinedProperty = {};
+ add(targetProperty);
+ // next config source overwrites the target config object
+ add(nextProperty);
+ return combinedProperty;
+ function add(property) {
+ if (property !== undefined) {
+ for (var name in property) {
+ if (utils_1.hasOwnProperty(property, name)) {
+ combinedProperty[name] = property[name];
+ }
+ }
+ }
+ }
+ }
+ function combineMaps(target, next) {
+ var combined = new Map();
+ target.forEach(function (options, ruleName) {
+ combined.set(ruleName, options);
+ });
+ next.forEach(function (options, ruleName) {
+ var combinedRule = combined.get(ruleName);
+ if (combinedRule != null) {
+ combined.set(ruleName, combineProperties(combinedRule, options));
+ }
+ else {
+ combined.set(ruleName, options);
+ }
+ });
+ return combined;
+ }
+ var combinedRulesDirs = targetConfig.rulesDirectory.concat(nextConfigSource.rulesDirectory);
+ var dedupedRulesDirs = Array.from(new Set(combinedRulesDirs));
+ return {
+ extends: [],
+ jsRules: combineMaps(targetConfig.jsRules, nextConfigSource.jsRules),
+ linterOptions: combineProperties(targetConfig.linterOptions, nextConfigSource.linterOptions),
+ rules: combineMaps(targetConfig.rules, nextConfigSource.rules),
+ rulesDirectory: dedupedRulesDirs,
+ };
+}
+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 != null && fs.existsSync(homePath)) {
+ return homePath;
+ }
+ }
+ return undefined;
+}
+// returns the absolute path (contrary to what the name implies)
+function getRelativePath(directory, relativeTo) {
+ if (directory != null) {
+ var basePath = relativeTo !== undefined ? relativeTo : process.cwd();
+ return path.resolve(basePath, directory);
+ }
+ return undefined;
+}
+exports.getRelativePath = getRelativePath;
+// check if directory should be used as path or if it should be resolved like a module
+// matches if directory starts with '/', './', '../', 'node_modules/' or equals '.' or '..'
+function useAsPath(directory) {
+ return /^(?:\.?\.?(?:\/|$)|node_modules\/)/.test(directory);
+}
+exports.useAsPath = useAsPath;
+/**
+ * @param directories A path(s) to a directory of custom rules
+ * @param relativeTo A path that directories provided are relative to.
+ * For example, if the directories come from a tslint.json file, this path
+ * should be the path to the tslint.json file.
+ * @return An array of absolute paths to directories potentially containing rules
+ */
+function getRulesDirectories(directories, relativeTo) {
+ return utils_1.arrayify(directories)
+ .map(function (dir) {
+ if (!useAsPath(dir)) {
+ try {
+ return path.dirname(resolve.sync(dir, { basedir: relativeTo }));
+ }
+ catch (err) {
+ // swallow error and fallback to using directory as path
+ }
+ }
+ var absolutePath = getRelativePath(dir, relativeTo);
+ if (absolutePath != null) {
+ if (!fs.existsSync(absolutePath)) {
+ throw new Error("Could not find custom rule directory: " + dir);
+ }
+ }
+ return absolutePath;
+ })
+ .filter(function (dir) { return dir !== undefined; });
+}
+exports.getRulesDirectories = getRulesDirectories;
+/**
+ * Parses the options of a single rule and upgrades legacy settings such as `true`, `[true, "option"]`
+ *
+ * @param ruleConfigValue The raw option setting of a rule
+ */
+function parseRuleOptions(ruleConfigValue, rawDefaultRuleSeverity) {
+ var ruleArguments;
+ var defaultRuleSeverity = "error";
+ if (rawDefaultRuleSeverity !== undefined) {
+ switch (rawDefaultRuleSeverity.toLowerCase()) {
+ case "warn":
+ case "warning":
+ defaultRuleSeverity = "warning";
+ break;
+ case "off":
+ case "none":
+ defaultRuleSeverity = "off";
+ break;
+ default:
+ defaultRuleSeverity = "error";
+ }
+ }
+ var ruleSeverity = defaultRuleSeverity;
+ if (ruleConfigValue == null) {
+ ruleArguments = [];
+ ruleSeverity = "off";
+ }
+ else if (Array.isArray(ruleConfigValue)) {
+ if (ruleConfigValue.length > 0) {
+ // old style: array
+ ruleArguments = ruleConfigValue.slice(1);
+ ruleSeverity = ruleConfigValue[0] === true ? defaultRuleSeverity : "off";
+ }
+ }
+ else if (typeof ruleConfigValue === "boolean") {
+ // old style: boolean
+ ruleArguments = [];
+ ruleSeverity = ruleConfigValue ? defaultRuleSeverity : "off";
+ }
+ else if (typeof ruleConfigValue === "object") {
+ if (ruleConfigValue.severity !== undefined) {
+ switch (ruleConfigValue.severity.toLowerCase()) {
+ case "default":
+ ruleSeverity = defaultRuleSeverity;
+ break;
+ case "error":
+ ruleSeverity = "error";
+ break;
+ case "warn":
+ case "warning":
+ ruleSeverity = "warning";
+ break;
+ case "off":
+ case "none":
+ ruleSeverity = "off";
+ break;
+ default:
+ console.warn("Invalid severity level: " + ruleConfigValue.severity);
+ ruleSeverity = defaultRuleSeverity;
+ }
+ }
+ if (ruleConfigValue.options != null) {
+ ruleArguments = utils_1.arrayify(ruleConfigValue.options);
+ }
+ }
+ return {
+ ruleArguments: ruleArguments,
+ ruleSeverity: ruleSeverity,
+ };
+}
+/**
+ * Parses a config file and normalizes legacy config settings
+ *
+ * @param configFile The raw object read from the JSON of a config file
+ * @param configFileDir The directory of the config file
+ */
+function parseConfigFile(configFile, configFileDir) {
+ return {
+ extends: utils_1.arrayify(configFile.extends),
+ jsRules: parseRules(configFile.jsRules),
+ linterOptions: configFile.linterOptions !== undefined ? configFile.linterOptions : {},
+ rules: parseRules(configFile.rules),
+ rulesDirectory: getRulesDirectories(configFile.rulesDirectory, configFileDir),
+ };
+ 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));
+ }
+ }
+ }
+ return map;
+ }
+}
+exports.parseConfigFile = parseConfigFile;
+/**
+ * Fills in default values for `IOption` properties and outputs an array of `IOption`
+ */
+function convertRuleOptions(ruleConfiguration) {
+ var output = [];
+ ruleConfiguration.forEach(function (_a, ruleName) {
+ var ruleArguments = _a.ruleArguments, ruleSeverity = _a.ruleSeverity;
+ var options = {
+ disabledIntervals: [],
+ ruleArguments: ruleArguments != null ? ruleArguments : [],
+ ruleName: ruleName,
+ ruleSeverity: ruleSeverity != null ? ruleSeverity : "error",
+ };
+ output.push(options);
+ });
+ return output;
+}
+exports.convertRuleOptions = convertRuleOptions;