You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
2.4 KiB
105 lines
2.4 KiB
'use strict';
|
|
const getDocumentationUrl = require('./utils/get-documentation-url');
|
|
|
|
const errorConstructors = new Set([
|
|
'Error',
|
|
'EvalError',
|
|
'InternalError',
|
|
'RangeError',
|
|
'ReferenceError',
|
|
'SyntaxError',
|
|
'TypeError',
|
|
'URIError'
|
|
]);
|
|
|
|
const isReferenceAssigned = expression => {
|
|
if (expression.type === 'AssignmentExpression') {
|
|
const assignedVariable = expression.left;
|
|
return assignedVariable.type === 'Identifier' && assignedVariable.name;
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
const findIdentifierValues = (identifierNode, context) => {
|
|
const scope = context.getScope(identifierNode);
|
|
const declarations = scope.set.get(identifierNode.name);
|
|
if (declarations === undefined) {
|
|
return [];
|
|
}
|
|
|
|
const expressions = declarations.references.map(reference => reference.identifier.parent);
|
|
const referenceValues = [];
|
|
for (const expression of expressions) {
|
|
if (isReferenceAssigned(expression)) {
|
|
referenceValues.push(expression.right);
|
|
} else if (expression.type === 'VariableDeclarator') {
|
|
referenceValues.push(expression.init);
|
|
}
|
|
}
|
|
|
|
return referenceValues;
|
|
};
|
|
|
|
const isEmptyMessageString = node => {
|
|
return (
|
|
node.arguments.length > 0 &&
|
|
node.arguments[0].type === 'Literal' &&
|
|
!node.arguments[0].value
|
|
);
|
|
};
|
|
|
|
const reportError = (expressionNode, context) => {
|
|
const error = expressionNode.callee;
|
|
if (errorConstructors.has(error.name)) {
|
|
if (expressionNode.arguments.length === 0) {
|
|
context.report({
|
|
node: expressionNode.parent,
|
|
message: 'Pass a message to the error constructor.'
|
|
});
|
|
}
|
|
|
|
if (isEmptyMessageString(expressionNode)) {
|
|
context.report({
|
|
node: expressionNode.parent,
|
|
message: 'Error message should not be an empty string.'
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
const checkErrorMessage = (node, context) => {
|
|
if (node.type === 'Identifier') {
|
|
const identifierValues = findIdentifierValues(node, context);
|
|
for (const node of identifierValues) {
|
|
checkErrorMessage(node, context);
|
|
}
|
|
} else if (node.type === 'NewExpression' || node.type === 'CallExpression') {
|
|
reportError(node, context);
|
|
}
|
|
};
|
|
|
|
const create = context => {
|
|
const throwStatements = [];
|
|
return {
|
|
'ThrowStatement'(throwStatement) {
|
|
throwStatements.push(throwStatement);
|
|
},
|
|
'Program:exit'() {
|
|
for (const throwStatement of throwStatements) {
|
|
checkErrorMessage(throwStatement.argument, context);
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
module.exports = {
|
|
create,
|
|
meta: {
|
|
type: 'problem',
|
|
docs: {
|
|
url: getDocumentationUrl(__filename)
|
|
}
|
|
}
|
|
};
|