Skip to content

Commit

Permalink
Issue #470 Solve automatically definedundefined rule
Browse files Browse the repository at this point in the history
  • Loading branch information
EmmanuelDemey committed Apr 11, 2017
1 parent 125290a commit ac674af
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 30 deletions.
35 changes: 23 additions & 12 deletions rules/definedundefined.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,30 @@
*/
'use strict';

var utils = require('./utils/utils');

const utils = require('./utils/utils');
const SHOULD_USE_ISDEFINED_OR_ISUNDEFINED = 'You should not use directly the "undefined" keyword. Prefer ' +
'angular.isUndefined or angular.isDefined';
const SHOULD_NOT_USE_BANG_WITH_ISDEFINED = 'Instead of !angular.isDefined, you can use the out-of-box angular.isUndefined method';
const SHOULD_NOT_USE_BANG_WITH_ISUNDEFINED = 'Instead of !angular.isUndefined, you can use the out-of-box angular.isDefined method';

module.exports = {
meta: {
schema: []
schema: [],
fixable: 'code'
},
create: function(context) {
function isCompareOperator(operator) {
return operator === '===' || operator === '!==' || operator === '==' || operator === '!=';
}
function reportError(node) {
context.report(node, 'You should not use directly the "undefined" keyword. Prefer ' +
'angular.isUndefined or angular.isDefined', {});
function reportError(node, message, fix) {
context.report({
node,
message,
fix
});
}
var sourceCode = context.getSourceCode();

/**
* Rule that check if we use angular.is(Un)defined() instead of the undefined keyword
*/
Expand All @@ -35,22 +44,24 @@ module.exports = {
node.parent.parent !== undefined &&
node.parent.parent.operator === '!') {
if (node.property.name === 'isDefined') {
context.report(node, 'Instead of !angular.isDefined, you can use the out-of-box angular.isUndefined method', {});
reportError(node, SHOULD_NOT_USE_BANG_WITH_ISDEFINED, fixer => fixer.replaceText(node.parent.parent, `angular.isUndefined(${node.parent.arguments[0].name})`));
} else if (node.property.name === 'isUndefined') {
context.report(node, 'Instead of !angular.isUndefined, you can use the out-of-box angular.isDefined method', {});
reportError(node, SHOULD_NOT_USE_BANG_WITH_ISUNDEFINED, fixer => fixer.replaceText(node.parent.parent, `angular.isDefined(${node.parent.arguments[0].name})`));
}
}
},
BinaryExpression: function(node) {
if (isCompareOperator(node.operator)) {
let method = (node.operator === '!=' || node.operator === '!==') ? 'isDefined' : 'isUndefined';

if (utils.isTypeOfStatement(node.left) && node.right.value === 'undefined') {
reportError(node);
reportError(node, SHOULD_USE_ISDEFINED_OR_ISUNDEFINED, fixer => fixer.replaceText(node, `angular.${method}(${sourceCode.getText(node.left)})`));
} else if (utils.isTypeOfStatement(node.right) && node.left.value === 'undefined') {
reportError(node);
reportError(node, SHOULD_USE_ISDEFINED_OR_ISUNDEFINED, fixer => fixer.replaceText(node, `angular.${method}(${sourceCode.getText(node.right)})`));
} else if (node.left.type === 'Identifier' && node.left.name === 'undefined') {
reportError(node);
reportError(node, SHOULD_USE_ISDEFINED_OR_ISUNDEFINED, fixer => fixer.replaceText(node, `angular.${method}(${node.right.name})`));
} else if (node.right.type === 'Identifier' && node.right.name === 'undefined') {
reportError(node);
reportError(node, SHOULD_USE_ISDEFINED_OR_ISUNDEFINED, fixer => fixer.replaceText(node, `angular.${method}(${node.left.name})`));
}
}
}
Expand Down
36 changes: 18 additions & 18 deletions test/definedundefined.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
// Requirements
// ------------------------------------------------------------------------------

var rule = require('../rules/definedundefined');
var RuleTester = require('eslint').RuleTester;
var commonFalsePositives = require('./utils/commonFalsePositives');
const rule = require('../rules/definedundefined');
const RuleTester = require('eslint').RuleTester;
const commonFalsePositives = require('./utils/commonFalsePositives');

// ------------------------------------------------------------------------------
// Tests
// ------------------------------------------------------------------------------

var eslintTester = new RuleTester();
const eslintTester = new RuleTester();
eslintTester.run('definedundefined', rule, {
valid: [
'angular.isUndefined(toto)',
Expand All @@ -24,19 +24,19 @@ eslintTester.run('definedundefined', rule, {
'angular.isString(null)'
].concat(commonFalsePositives),
invalid: [
{code: 'variable === undefined', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'undefined === variable', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'undefined !== variable', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'variable !== undefined', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'variable == undefined', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'undefined == variable', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'undefined != variable', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'variable != undefined', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'typeof variable === "undefined"', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'typeof variable !== "undefined"', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: '"undefined" == typeof variable', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: '"undefined" != typeof variable', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: '!angular.isUndefined(variable)', errors: [{message: 'Instead of !angular.isUndefined, you can use the out-of-box angular.isDefined method'}]},
{code: '!angular.isDefined(variable)', errors: [{message: 'Instead of !angular.isDefined, you can use the out-of-box angular.isUndefined method'}]}
{code: 'variable === undefined', output: 'angular.isUndefined(variable)', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'undefined === variable', output: 'angular.isUndefined(variable)', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'undefined !== variable', output: 'angular.isDefined(variable)', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'variable !== undefined', output: 'angular.isDefined(variable)', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'variable == undefined', output: 'angular.isUndefined(variable)', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'undefined == variable', output: 'angular.isUndefined(variable)', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'undefined != variable', output: 'angular.isDefined(variable)', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'variable != undefined', output: 'angular.isDefined(variable)', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'typeof variable === "undefined"', output: 'angular.isUndefined(typeof variable)', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: 'typeof variable !== "undefined"', output: 'angular.isDefined(typeof variable)', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: '"undefined" == typeof variable', output: 'angular.isUndefined(typeof variable)', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: '"undefined" != typeof variable', output: 'angular.isDefined(typeof variable)', errors: [{message: 'You should not use directly the "undefined" keyword. Prefer angular.isUndefined or angular.isDefined'}]},
{code: '!angular.isUndefined(variable)', output: 'angular.isDefined(variable)', errors: [{message: 'Instead of !angular.isUndefined, you can use the out-of-box angular.isDefined method'}]},
{code: '!angular.isDefined(variable)', output: 'angular.isUndefined(variable)', errors: [{message: 'Instead of !angular.isDefined, you can use the out-of-box angular.isUndefined method'}]}
]
});

0 comments on commit ac674af

Please sign in to comment.