Skip to content

tools: update eslint to v2.2.0 #5457

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
28 changes: 27 additions & 1 deletion tools/eslint/lib/code-path-analysis/code-path-segment.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ function CodePathSegment(id, allPrevSegments, reachable) {

// Internal data.
Object.defineProperty(this, "internal", {value: {
used: false
used: false,
loopedPrevSegments: []
}});

/* istanbul ignore if */
Expand All @@ -130,6 +131,20 @@ function CodePathSegment(id, allPrevSegments, reachable) {
}
}

CodePathSegment.prototype = {
constructor: CodePathSegment,

/**
* Checks a given previous segment is coming from the end of a loop.
*
* @param {CodePathSegment} segment - A previous segment to check.
* @returns {boolean} `true` if the segment is coming from the end of a loop.
*/
isLoopedPrevSegment: function(segment) {
return this.internal.loopedPrevSegments.indexOf(segment) !== -1;
}
};

/**
* Creates the root segment.
*
Expand Down Expand Up @@ -205,4 +220,15 @@ CodePathSegment.markUsed = function(segment) {
}
};

/**
* Marks a previous segment as looped.
*
* @param {CodePathSegment} segment - A segment.
* @param {CodePathSegment} prevSegment - A previous segment to mark.
* @returns {void}
*/
CodePathSegment.markPrevSegmentAsLooped = function(segment, prevSegment) {
segment.internal.loopedPrevSegments.push(prevSegment);
};

module.exports = CodePathSegment;
4 changes: 4 additions & 0 deletions tools/eslint/lib/code-path-analysis/code-path-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,10 @@ function makeLooped(state, fromSegments, toSegments) {
fromSegment.allNextSegments.push(toSegment);
toSegment.allPrevSegments.push(fromSegment);

if (toSegment.allPrevSegments.length >= 2) {
CodePathSegment.markPrevSegmentAsLooped(toSegment, fromSegment);
}

state.notifyLooped(fromSegment, toSegment);
}
}
Expand Down
114 changes: 114 additions & 0 deletions tools/eslint/lib/code-path-analysis/code-path.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,120 @@ CodePath.prototype = {
*/
get currentSegments() {
return this.internal.currentSegments;
},

/**
* Traverses all segments in this code path.
*
* codePath.traverseSegments(function(segment, controller) {
* // do something.
* });
*
* This method enumerates segments in order from the head.
*
* The `controller` object has two methods.
*
* - `controller.skip()` - Skip the following segments in this branch.
* - `controller.break()` - Skip all following segments.
*
* @param {object} [options] - Omittable.
* @param {CodePathSegment} [options.first] - The first segment to traverse.
* @param {CodePathSegment} [options.last] - The last segment to traverse.
* @param {function} callback - A callback function.
* @returns {void}
*/
traverseSegments: function(options, callback) {
if (typeof options === "function") {
callback = options;
options = null;
}

options = options || {};
var startSegment = options.first || this.internal.initialSegment;
var lastSegment = options.last;

var item = null;
var index = 0;
var end = 0;
var segment = null;
var visited = Object.create(null);
var stack = [[startSegment, 0]];
var skippedSegment = null;
var broken = false;
var controller = {
skip: function() {
if (stack.length <= 1) {
broken = true;
} else {
skippedSegment = stack[stack.length - 2][0];
}
},
break: function() {
broken = true;
}
};

/**
* Checks a given previous segment has been visited.
* @param {CodePathSegment} prevSegment - A previous segment to check.
* @returns {boolean} `true` if the segment has been visited.
*/
function isVisited(prevSegment) {
return (
visited[prevSegment.id] ||
segment.isLoopedPrevSegment(prevSegment)
);
}

while (stack.length > 0) {
item = stack[stack.length - 1];
segment = item[0];
index = item[1];

if (index === 0) {
// Skip this has been visited already.
if (visited[segment.id]) {
stack.pop();
continue;
}
// Skip if all previous segments have not been visited.
if (segment !== startSegment &&
segment.prevSegments.length > 0 &&
!segment.prevSegments.every(isVisited)
) {
stack.pop();
continue;
}
// Reset the flag of skipping if all branches have been skipped.
if (skippedSegment && segment.prevSegments.indexOf(skippedSegment) !== -1) {
skippedSegment = null;
}
visited[segment.id] = true;

// Call the callback when the first time.
if (!skippedSegment) {
callback.call(this, segment, controller); // eslint-disable-line callback-return
if (segment === lastSegment) {
controller.skip();
}
if (broken) {
break;
}
}
}

// Update the stack.
end = segment.nextSegments.length - 1;
if (index < end) {
item[1] += 1;
stack.push([segment.nextSegments[index], 0]);
} else if (index === end) {
item[0] = segment.nextSegments[index];
item[1] = 0;
} else {
stack.pop();
}
}
}
};

Expand Down
11 changes: 9 additions & 2 deletions tools/eslint/lib/config/config-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ var debug = require("debug"),
pathIsInside = require("path-is-inside"),
stripComments = require("strip-json-comments"),
stringify = require("json-stable-stringify"),
isAbsolutePath = require("path-is-absolute");
isAbsolutePath = require("path-is-absolute"),
defaultOptions = require("../../conf/eslint.json"),
requireUncached = require("require-uncached");


//------------------------------------------------------------------------------
Expand Down Expand Up @@ -152,7 +154,7 @@ function loadLegacyConfigFile(filePath) {
function loadJSConfigFile(filePath) {
debug("Loading JS config file: " + filePath);
try {
return require(filePath);
return requireUncached(filePath);
} catch (e) {
debug("Error reading JavaScript file: " + filePath);
e.message = "Cannot read config file: " + filePath + "\nError: " + e.message;
Expand Down Expand Up @@ -441,6 +443,11 @@ function load(filePath, applyEnvironments) {
Plugins.loadAll(config.plugins);
}

// remove parser from config if it is the default parser
if (config.parser === defaultOptions.parser) {
config.parser = null;
}

// include full path of parser if present
if (config.parser) {
config.parser = resolveModule.sync(config.parser, {
Expand Down
5 changes: 4 additions & 1 deletion tools/eslint/lib/eslint.js
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ function modifyConfigsFromComments(filename, ast, config, reportingConfig, messa
ast.comments.forEach(function(comment) {

var value = comment.value.trim();
var match = /^(eslint-\w+|eslint-\w+-\w+|eslint|exported|globals?)(\s|$)/.exec(value);
var match = /^(eslint(-\w+){0,3}|exported|globals?)(\s|$)/.exec(value);

if (match) {
value = value.substring(match.index + match[1].length);
Expand Down Expand Up @@ -324,6 +324,9 @@ function modifyConfigsFromComments(filename, ast, config, reportingConfig, messa
if (match[1] === "eslint-disable-line") {
disableReporting(reportingConfig, { "line": comment.loc.start.line, "column": 0 }, Object.keys(parseListConfig(value)));
enableReporting(reportingConfig, comment.loc.end, Object.keys(parseListConfig(value)));
} else if (match[1] === "eslint-disable-next-line") {
disableReporting(reportingConfig, comment.loc.start, Object.keys(parseListConfig(value)));
enableReporting(reportingConfig, { "line": comment.loc.start.line + 2 }, Object.keys(parseListConfig(value)));
}
}
}
Expand Down
1 change: 1 addition & 0 deletions tools/eslint/lib/ignored-paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,3 +232,4 @@ IgnoredPaths.prototype.contains = function(filepath, category) {
};

module.exports = IgnoredPaths;

96 changes: 71 additions & 25 deletions tools/eslint/lib/rules/constructor-super.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ module.exports = function(context) {
// Information for each code path segment.
// - calledInSomePaths: A flag of be called `super()` in some code paths.
// - calledInEveryPaths: A flag of be called `super()` in all code paths.
// - validNodes:
var segInfoMap = Object.create(null);

/**
Expand Down Expand Up @@ -77,21 +78,26 @@ module.exports = function(context) {
* @returns {void}
*/
"onCodePathStart": function(codePath, node) {
if (!isConstructorFunction(node)) {
return;
if (isConstructorFunction(node)) {
// Class > ClassBody > MethodDefinition > FunctionExpression
var classNode = node.parent.parent.parent;
funcInfo = {
upper: funcInfo,
isConstructor: true,
hasExtends: Boolean(
classNode.superClass &&
!astUtils.isNullOrUndefined(classNode.superClass)
),
codePath: codePath
};
} else {
funcInfo = {
upper: funcInfo,
isConstructor: false,
hasExtends: false,
codePath: codePath
};
}

// Class > ClassBody > MethodDefinition > FunctionExpression
var classNode = node.parent.parent.parent;
funcInfo = {
upper: funcInfo,
hasExtends: Boolean(
classNode.superClass &&
!astUtils.isNullOrUndefined(classNode.superClass)
),
scope: context.getScope(),
codePath: codePath
};
},

/**
Expand All @@ -102,10 +108,6 @@ module.exports = function(context) {
* @returns {void}
*/
"onCodePathEnd": function(codePath, node) {
if (!isConstructorFunction(node)) {
return;
}

// Skip if own class which has a valid `extends` part.
var hasExtends = funcInfo.hasExtends;
funcInfo = funcInfo.upper;
Expand Down Expand Up @@ -135,18 +137,15 @@ module.exports = function(context) {
"onCodePathSegmentStart": function(segment) {
// Skip if this is not in a constructor of a class which has a valid
// `extends` part.
if (!(
funcInfo &&
funcInfo.hasExtends &&
funcInfo.scope === context.getScope().variableScope
)) {
if (!(funcInfo && funcInfo.isConstructor && funcInfo.hasExtends)) {
return;
}

// Initialize info.
var info = segInfoMap[segment.id] = {
calledInSomePaths: false,
calledInEveryPaths: false
calledInEveryPaths: false,
validNodes: []
};

// When there are previous segments, aggregates these.
Expand All @@ -157,6 +156,51 @@ module.exports = function(context) {
}
},

/**
* Update information of the code path segment when a code path was
* looped.
* @param {CodePathSegment} fromSegment - The code path segment of the
* end of a loop.
* @param {CodePathSegment} toSegment - A code path segment of the head
* of a loop.
* @returns {void}
*/
"onCodePathSegmentLoop": function(fromSegment, toSegment) {
// Skip if this is not in a constructor of a class which has a valid
// `extends` part.
if (!(funcInfo && funcInfo.isConstructor && funcInfo.hasExtends)) {
return;
}

// Update information inside of the loop.
var isRealLoop = toSegment.prevSegments.length >= 2;
funcInfo.codePath.traverseSegments(
{first: toSegment, last: fromSegment},
function(segment) {
var info = segInfoMap[segment.id];

// Updates flags.
var prevSegments = segment.prevSegments;
info.calledInSomePaths = prevSegments.some(isCalledInSomePath);
info.calledInEveryPaths = prevSegments.every(isCalledInEveryPath);

// If flags become true anew, reports the valid nodes.
if (info.calledInSomePaths || isRealLoop) {
var nodes = info.validNodes;
info.validNodes = [];

for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i];
context.report({
message: "Unexpected duplicate 'super()'.",
node: node
});
}
}
}
);
},

/**
* Checks for a call of `super()`.
* @param {ASTNode} node - A CallExpression node to check.
Expand All @@ -169,7 +213,7 @@ module.exports = function(context) {
}

// Skip if this is not in a constructor.
if (!(funcInfo && funcInfo.scope === context.getScope().variableScope)) {
if (!(funcInfo && funcInfo.isConstructor)) {
return;
}

Expand All @@ -191,6 +235,8 @@ module.exports = function(context) {
message: "Unexpected duplicate 'super()'.",
node: node
});
} else {
info.validNodes.push(node);
}
} else {
// This class does not have a valid `extends` part.
Expand Down
Loading