Skip to content

Commit

Permalink
Breaking: runtime-deprecation on '~/.eslintrc' (refs eslint/rfcs#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
mysticatea committed Dec 17, 2019
1 parent 257f3d6 commit e7581dd
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 39 deletions.
49 changes: 37 additions & 12 deletions lib/cli-engine/cascading-config-array-factory.js
Expand Up @@ -26,6 +26,7 @@
const os = require("os");
const path = require("path");
const { validateConfigArray } = require("../shared/config-validator");
const { emitDeprecationWarning } = require("../shared/deprecation-warnings");
const { ConfigArrayFactory } = require("./config-array-factory");
const { ConfigArray, ConfigDependency, IgnorePattern } = require("./config-array");
const loadRules = require("./load-rules");
Expand Down Expand Up @@ -290,10 +291,11 @@ class CascadingConfigArrayFactory {
/**
* Load and normalize config files from the ancestor directories.
* @param {string} directoryPath The path to a leaf directory.
* @param {boolean} configsExistInSubdirs `true` if configurations exist in subdirectories.
* @returns {ConfigArray} The loaded config.
* @private
*/
_loadConfigInAncestors(directoryPath) {
_loadConfigInAncestors(directoryPath, configsExistInSubdirs = false) {
const {
baseConfigArray,
configArrayFactory,
Expand All @@ -315,14 +317,6 @@ class CascadingConfigArrayFactory {
}
debug(`No cache found: ${directoryPath}.`);

const homePath = os.homedir();

// Consider this is root.
if (directoryPath === homePath && cwd !== homePath) {
debug("Stop traversing because of considered root.");
return this._cacheConfig(directoryPath, baseConfigArray);
}

// Load the config on this directory.
try {
configArray = configArrayFactory.loadInDirectory(directoryPath);
Expand All @@ -335,6 +329,22 @@ class CascadingConfigArrayFactory {
throw error;
}

const homePath = os.homedir();

// Consider this is root.
if (directoryPath === homePath && cwd !== homePath) {
debug("Stop traversing because of considered root.");
if (configsExistInSubdirs && configArray.length > 0) {
const lastElement = configArray[configArray.length - 1];

emitDeprecationWarning(
lastElement.filePath,
"ESLINT_PERSONAL_CONFOG_SUPPRESS"
);
}
return this._cacheConfig(directoryPath, baseConfigArray);
}

if (configArray.length > 0 && configArray.isRoot()) {
debug("Stop traversing because of 'root:true'.");
configArray.unshift(...baseConfigArray);
Expand All @@ -344,7 +354,10 @@ class CascadingConfigArrayFactory {
// Load from the ancestors and merge it.
const parentPath = path.dirname(directoryPath);
const parentConfigArray = parentPath && parentPath !== directoryPath
? this._loadConfigInAncestors(parentPath)
? this._loadConfigInAncestors(
parentPath,
configsExistInSubdirs || configArray.length > 0
)
: baseConfigArray;

if (configArray.length > 0) {
Expand Down Expand Up @@ -402,10 +415,22 @@ class CascadingConfigArrayFactory {
) {
debug("Loading the config file of the home directory.");

finalConfigArray = configArrayFactory.loadInDirectory(
const personalConfigArray = configArrayFactory.loadInDirectory(
os.homedir(),
{ name: "PersonalConfig", parent: finalConfigArray }
{ name: "PersonalConfig" }
);

if (personalConfigArray.length > 0) {
const lastElement =
personalConfigArray[personalConfigArray.length - 1];

emitDeprecationWarning(
lastElement.filePath,
"ESLINT_PERSONAL_CONFOG_LOAD"
);
finalConfigArray =
finalConfigArray.concat(personalConfigArray);
}
}

// Apply CLI options.
Expand Down
29 changes: 2 additions & 27 deletions lib/shared/config-validator.js
Expand Up @@ -10,13 +10,12 @@
//------------------------------------------------------------------------------

const
path = require("path"),
util = require("util"),
lodash = require("lodash"),
configSchema = require("../../conf/config-schema"),
BuiltInEnvironments = require("../../conf/environments"),
BuiltInRules = require("../rules"),
ConfigOps = require("./config-ops");
ConfigOps = require("./config-ops"),
{ emitDeprecationWarning } = require("./deprecation-warnings");

const ajv = require("./ajv")();
const ruleValidators = new WeakMap();
Expand All @@ -26,11 +25,6 @@ const noop = Function.prototype;
// Private
//------------------------------------------------------------------------------
let validateSchema;

// Defitions for deprecation warnings.
const deprecationWarningMessages = {
ESLINT_LEGACY_ECMAFEATURES: "The 'ecmaFeatures' config file property is deprecated, and has no effect."
};
const severityMap = {
error: 2,
warn: 1,
Expand Down Expand Up @@ -254,25 +248,6 @@ function formatErrors(errors) {
}).map(message => `\t- ${message}.\n`).join("");
}

/**
* Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted
* for each unique file path, but repeated invocations with the same file path have no effect.
* No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.
* @param {string} source The name of the configuration source to report the warning for.
* @param {string} errorCode The warning message to show.
* @returns {void}
*/
const emitDeprecationWarning = lodash.memoize((source, errorCode) => {
const rel = path.relative(process.cwd(), source);
const message = deprecationWarningMessages[errorCode];

process.emitWarning(
`${message} (found in "${rel}")`,
"DeprecationWarning",
errorCode
);
});

/**
* Validates the top level properties of the config object.
* @param {Object} config The config object to validate.
Expand Down
56 changes: 56 additions & 0 deletions lib/shared/deprecation-warnings.js
@@ -0,0 +1,56 @@
/**
* @fileoverview Provide the function that emits deprecation warnings.
* @author Toru Nagashima <http://github.com/mysticatea>
*/
"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const path = require("path");
const lodash = require("lodash");

//------------------------------------------------------------------------------
// Private
//------------------------------------------------------------------------------

// Defitions for deprecation warnings.
const deprecationWarningMessages = {
ESLINT_LEGACY_ECMAFEATURES:
"The 'ecmaFeatures' config file property is deprecated, and has no effect.",
ESLINT_PERSONAL_CONFOG_LOAD:
"The '~/.eslintrc.*' config file has been deprecated. " +
"Please use config files for each project or '--config' option.",
ESLINT_PERSONAL_CONFOG_SUPPRESS:
"The '~/.eslintrc.*' config file has been deprecated. " +
"Please remove it or add 'root:true' into the config file of your " +
"projects in order to avoid loading '~/.eslintrc.*' accidentally."
};

/**
* Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted
* for each unique file path, but repeated invocations with the same file path have no effect.
* No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.
* @param {string} source The name of the configuration source to report the warning for.
* @param {string} errorCode The warning message to show.
* @returns {void}
*/
const emitDeprecationWarning = lodash.memoize((source, errorCode) => {
const rel = path.relative(process.cwd(), source);
const message = deprecationWarningMessages[errorCode];

process.emitWarning(
`${message} (found in "${rel}")`,
"DeprecationWarning",
errorCode
);
}, (...args) => JSON.stringify(args));

//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------

module.exports = {
emitDeprecationWarning
};

0 comments on commit e7581dd

Please sign in to comment.