eslint-plugin-ember
Advanced tools
Comparing version 7.1.0 to 7.2.0
@@ -0,1 +1,21 @@ | ||
## v7.2.0 (2019-10-20) | ||
#### :rocket: Enhancement | ||
* [#545](https://github.com/ember-cli/eslint-plugin-ember/pull/545) Add `ignoreNonThisExpressions` option to `use-ember-get-and-set` rule ([@nlfurniss](https://github.com/nlfurniss)) | ||
* [#534](https://github.com/ember-cli/eslint-plugin-ember/pull/534) Add `onlyThisContexts` option to `no-arrow-function-computed-properties` rule ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) | ||
* [#537](https://github.com/ember-cli/eslint-plugin-ember/pull/537) Add `ignoreGetProperties` option for `no-get` rule ([@EvgenyOrekhov](https://github.com/EvgenyOrekhov)) | ||
#### :house: Internal | ||
* [#462](https://github.com/ember-cli/eslint-plugin-ember/pull/462) Refactor null checks for `new-module-imports` and `use-ember-data-rfc-395-imports` rules ([@dcyriller](https://github.com/dcyriller)) | ||
* [#528](https://github.com/ember-cli/eslint-plugin-ember/pull/528) Add eslint-plugin-node and enable recommended rules internally ([@bmish](https://github.com/bmish)) | ||
* [#524](https://github.com/ember-cli/eslint-plugin-ember/pull/524) Add eslint-plugin-filenames to enforce kebab-case filenames ([@bmish](https://github.com/bmish)) | ||
* [#523](https://github.com/ember-cli/eslint-plugin-ember/pull/523) Add eslint-plugin-eslint-comments and fix violations ([@bmish](https://github.com/bmish)) | ||
#### Committers: 5 | ||
- Bryan Mishkin ([@bmish](https://github.com/bmish)) | ||
- Cyrille David ([@dcyriller](https://github.com/dcyriller)) | ||
- Evgeny Orekhov ([@EvgenyOrekhov](https://github.com/EvgenyOrekhov)) | ||
- L. Preston Sego III ([@NullVoxPopuli](https://github.com/NullVoxPopuli)) | ||
- Nathaniel Furniss ([@nlfurniss](https://github.com/nlfurniss)) | ||
## v7.1.0 (2019-09-18) | ||
@@ -2,0 +22,0 @@ |
'use strict'; | ||
/* eslint-disable global-require */ | ||
module.exports = { | ||
@@ -5,0 +4,0 @@ rules: { |
@@ -33,3 +33,5 @@ 'use strict'; | ||
CallExpression(node) { | ||
if (!ember.isEmberController(node, filePath)) return; | ||
if (!ember.isEmberController(node, filePath)) { | ||
return; | ||
} | ||
@@ -36,0 +38,0 @@ const properties = ember.getModuleProperties(node); |
@@ -69,3 +69,5 @@ 'use strict'; | ||
CallExpression(node) { | ||
if (!(ember.isEmberObject(node) || ember.isReopenObject(node))) return; | ||
if (!(ember.isEmberObject(node) || ember.isReopenObject(node))) { | ||
return; | ||
} | ||
@@ -72,0 +74,0 @@ const properties = ember.getModuleProperties(node); |
@@ -31,3 +31,5 @@ 'use strict'; | ||
if (!ember.isEmberController(node, filePath) && !isReopenNode) return; | ||
if (!ember.isEmberController(node, filePath) && !isReopenNode) { | ||
return; | ||
} | ||
@@ -34,0 +36,0 @@ const properties = ember.getModuleProperties(node); |
@@ -45,3 +45,5 @@ const ERROR_MESSAGE_INIT_IN_NON_CLASSIC = | ||
MethodDefinition(node) { | ||
if (!inClassicClass && !inNonClassicClass) return; | ||
if (!inClassicClass && !inNonClassicClass) { | ||
return; | ||
} | ||
@@ -48,0 +50,0 @@ if (inClassicClass && node.key.name === 'constructor') { |
@@ -55,4 +55,8 @@ const disallowedMethods = [ | ||
MemberExpression(node) { | ||
if (!inClassExtends) return; | ||
if (node.object.type !== 'ThisExpression') return; | ||
if (!inClassExtends) { | ||
return; | ||
} | ||
if (node.object.type !== 'ThisExpression') { | ||
return; | ||
} | ||
@@ -59,0 +63,0 @@ if (disallowedMethods.includes(node.property.name)) { |
'use strict'; | ||
const MAPPING = require('ember-rfc176-data'); | ||
const { buildMessage, getFullNames, isInitImportedFrom } = require('../utils/new-module'); | ||
const { | ||
buildMessage, | ||
getFullNames, | ||
isDestructuring, | ||
isIdentifierImportedFrom, | ||
} = require('../utils/new-module'); | ||
@@ -56,6 +61,3 @@ const GLOBALS = MAPPING.reduce((memo, exportDefinition) => { | ||
VariableDeclarator(node) { | ||
if (!node.init) return; | ||
// Filter out non-Ember variable declarations | ||
if (node.init.name !== 'Ember' && !isInitImportedFrom(node, 'ember')) { | ||
if (!isDestructuring(node) || !isIdentifierImportedFrom(node, 'ember')) { | ||
return; | ||
@@ -93,3 +95,5 @@ } | ||
// filter out "foo.Ember" | ||
if (node.parent.object !== node) return; | ||
if (node.parent.object !== node) { | ||
return; | ||
} | ||
@@ -96,0 +100,0 @@ // build an array of full expression names |
@@ -20,9 +20,29 @@ 'use strict'; | ||
create(context) { | ||
const options = context.options[0] || {}; | ||
const onlyThisContexts = options.onlyThisContexts || false; | ||
let isThisPresent = false; | ||
return { | ||
CallExpression(node) { | ||
if ( | ||
ThisExpression() { | ||
isThisPresent = true; | ||
}, | ||
CallExpression() { | ||
isThisPresent = false; | ||
}, | ||
'CallExpression:exit'(node) { | ||
const isComputedArrow = | ||
emberUtils.isComputedProp(node) && | ||
node.arguments.length > 0 && | ||
types.isArrowFunctionExpression(node.arguments[node.arguments.length - 1]) | ||
) { | ||
types.isArrowFunctionExpression(node.arguments[node.arguments.length - 1]); | ||
if (!isComputedArrow) { | ||
return; | ||
} | ||
if (onlyThisContexts) { | ||
if (isThisPresent) { | ||
context.report(node.arguments[node.arguments.length - 1], ERROR_MESSAGE); | ||
} | ||
} else { | ||
context.report(node.arguments[node.arguments.length - 1], ERROR_MESSAGE); | ||
@@ -29,0 +49,0 @@ } |
@@ -31,3 +31,5 @@ 'use strict'; | ||
CallExpression(node) { | ||
if (!ember.isDSModel(node, filePath)) return; | ||
if (!ember.isDSModel(node, filePath)) { | ||
return; | ||
} | ||
@@ -34,0 +36,0 @@ const allProperties = ember.getModuleProperties(node); |
@@ -23,5 +23,21 @@ 'use strict'; | ||
}, | ||
schema: [ | ||
{ | ||
type: 'object', | ||
properties: { | ||
ignoreGetProperties: { | ||
type: 'boolean', | ||
default: false, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
], | ||
}, | ||
create(context) { | ||
// Options: | ||
const ignoreGetProperties = context.options[0] && context.options[0].ignoreGetProperties; | ||
return { | ||
// eslint-disable-next-line complexity | ||
CallExpression(node) { | ||
@@ -61,2 +77,6 @@ // ************************** | ||
if (ignoreGetProperties) { | ||
return; | ||
} | ||
if ( | ||
@@ -63,0 +83,0 @@ types.isMemberExpression(node.callee) && |
@@ -78,5 +78,9 @@ 'use strict'; | ||
// to perform the below checks/run the below code. | ||
if (node.init && !isEmberIdentifier(node.init)) return; | ||
if (node.init && !isEmberIdentifier(node.init)) { | ||
return; | ||
} | ||
if (!node.id.properties || !isNestedJQueryAssignment(node.id.properties)) return; | ||
if (!node.id.properties || !isNestedJQueryAssignment(node.id.properties)) { | ||
return; | ||
} | ||
// Assignment of type const { $: foo } = Ember; | ||
@@ -96,3 +100,5 @@ // It will grab/return "foo". | ||
// using the new modules import syntax do not report to ESLint | ||
if (hasJqueryImport) return; | ||
if (hasJqueryImport) { | ||
return; | ||
} | ||
@@ -99,0 +105,0 @@ if (utils.isGlobalCallExpression(node, destructuredAssignment, ALIASES)) { |
'use strict'; | ||
const types = require('../utils/types'); | ||
const ERROR_MESSAGE = | ||
@@ -46,4 +47,4 @@ 'Do not use anonymous functions as arguments to `debounce`, `once`, and `scheduleOnce`.'; | ||
let importedRun = false; | ||
let inactiveFunctionRules = new Set(functionRules); | ||
let activeFunctionRules = new Set(); | ||
const inactiveFunctionRules = new Set(functionRules); | ||
const activeFunctionRules = new Set(); | ||
@@ -50,0 +51,0 @@ return { |
@@ -42,3 +42,5 @@ 'use strict'; | ||
const isOnCall = function(node) { | ||
if (!node.value) return false; | ||
if (!node.value) { | ||
return false; | ||
} | ||
const value = node.value; | ||
@@ -66,3 +68,5 @@ const callee = value.callee; | ||
CallExpression(node) { | ||
if (!ember.isEmberComponent(node, filePath)) return; | ||
if (!ember.isEmberComponent(node, filePath)) { | ||
return; | ||
} | ||
@@ -69,0 +73,0 @@ const propertiesWithOnCalls = ember.getModuleProperties(node).filter(isOnCall); |
@@ -77,3 +77,5 @@ 'use strict'; | ||
CallExpression(node) { | ||
if (!ember.isEmberComponent(node, filePath)) return; | ||
if (!ember.isEmberComponent(node, filePath)) { | ||
return; | ||
} | ||
@@ -80,0 +82,0 @@ reportUnorderedProperties(node, context, 'component', order); |
@@ -48,3 +48,5 @@ 'use strict'; | ||
CallExpression(node) { | ||
if (!ember.isEmberController(node, filePath)) return; | ||
if (!ember.isEmberController(node, filePath)) { | ||
return; | ||
} | ||
@@ -51,0 +53,0 @@ reportUnorderedProperties(node, context, 'controller', order); |
@@ -37,3 +37,5 @@ 'use strict'; | ||
CallExpression(node) { | ||
if (!ember.isDSModel(node, filePath)) return; | ||
if (!ember.isDSModel(node, filePath)) { | ||
return; | ||
} | ||
@@ -40,0 +42,0 @@ reportUnorderedProperties(node, context, 'model', order); |
@@ -72,3 +72,5 @@ 'use strict'; | ||
CallExpression(node) { | ||
if (!ember.isEmberRoute(node, filePath)) return; | ||
if (!ember.isEmberRoute(node, filePath)) { | ||
return; | ||
} | ||
@@ -75,0 +77,0 @@ reportUnorderedProperties(node, context, 'route', order); |
@@ -145,2 +145,3 @@ 'use strict'; | ||
return { | ||
// eslint-disable-next-line complexity | ||
CallExpression(node) { | ||
@@ -147,0 +148,0 @@ if (!emberUtils.isComputedProp(node)) { |
@@ -6,4 +6,6 @@ 'use strict'; | ||
try { | ||
// eslint-disable-next-line node/no-unpublished-require | ||
traverser = require('eslint/lib/shared/traverser'); // eslint >= 6 | ||
} catch (e) { | ||
// eslint-disable-next-line node/no-unpublished-require, node/no-missing-require | ||
traverser = require('eslint/lib/util/traverser'); // eslint < 6 | ||
@@ -10,0 +12,0 @@ } |
@@ -39,3 +39,5 @@ 'use strict'; | ||
function checkForSuper(nodes) { | ||
if (nodes.length === 0) return false; | ||
if (nodes.length === 0) { | ||
return false; | ||
} | ||
@@ -52,3 +54,5 @@ return nodes.some(n => { | ||
} else if (types.isReturnStatement(n)) { | ||
if (!n.argument || !types.isCallExpression(n.argument)) return false; | ||
if (!n.argument || !types.isCallExpression(n.argument)) { | ||
return false; | ||
} | ||
@@ -96,4 +100,5 @@ const fnCallee = n.argument.callee; | ||
!ember.isEmberService(node, filePath) | ||
) | ||
) { | ||
return; | ||
} | ||
@@ -100,0 +105,0 @@ const initProperty = ember |
@@ -36,3 +36,5 @@ 'use strict'; | ||
const getSegmentNames = function(property) { | ||
if (!isSegment(property)) return []; | ||
if (!isSegment(property)) { | ||
return []; | ||
} | ||
@@ -48,3 +50,5 @@ return property.value.value.match(routeSegmentRegex).map(segment => segment.slice(1)); | ||
CallExpression(node) { | ||
if (!ember.isRoute(node)) return; | ||
if (!ember.isRoute(node)) { | ||
return; | ||
} | ||
@@ -51,0 +55,0 @@ const routeOptions = types.isObjectExpression(node.arguments[1]) |
'use strict'; | ||
const MAPPINGS = require('@ember-data/rfc395-data'); | ||
const { buildFix, buildMessage, getFullNames, isInitImportedFrom } = require('../utils/new-module'); | ||
const { | ||
buildFix, | ||
buildMessage, | ||
getFullNames, | ||
isDestructuring, | ||
isIdentifierImportedFrom, | ||
} = require('../utils/new-module'); | ||
@@ -15,3 +21,3 @@ /** | ||
function oldDataImportsReducer(acc, mapping) { | ||
let obj = Object.create(null); | ||
const obj = Object.create(null); | ||
obj[mapping.export] = [mapping.replacement.module, mapping.replacement.export]; | ||
@@ -42,3 +48,3 @@ acc[mapping.module] = obj; // eslint-disable-line no-param-reassign | ||
let obj = { | ||
const obj = { | ||
global, | ||
@@ -50,3 +56,3 @@ export: mapping.replacement.export, | ||
acc[global] = obj; | ||
acc[global] = obj; // eslint-disable-line no-param-reassign | ||
@@ -115,6 +121,4 @@ return acc; | ||
VariableDeclarator(node) { | ||
if (!node.init) return; | ||
// Filter out non-DS variable declarations | ||
if (node.init.name !== 'DS' && !isInitImportedFrom(node, 'ember-data')) { | ||
// Filter out non-ember-data variable declarations | ||
if (!isDestructuring(node) || !isIdentifierImportedFrom(node, 'ember-data')) { | ||
return; | ||
@@ -148,3 +152,5 @@ } | ||
// filter out "foo.DS" | ||
if (node.parent.object !== node) return; | ||
if (node.parent.object !== node) { | ||
return; | ||
} | ||
@@ -151,0 +157,0 @@ // build an array of full expression names |
@@ -118,2 +118,9 @@ 'use strict'; | ||
} | ||
// Only lint calls made on this | ||
if (options.ignoreNonThisExpressions && isThisExpression(callee.object)) { | ||
report(node); | ||
return; | ||
} else if (options.ignoreNonThisExpressions) { | ||
return; | ||
} | ||
// Skip calls made on Ember methods | ||
@@ -120,0 +127,0 @@ if (isIdentifier(callee.object) && callee.object.name === emberImportAliasName) { |
@@ -329,4 +329,8 @@ 'use strict'; | ||
function getEmberImportAliasName(importDeclaration) { | ||
if (!importDeclaration.source) return null; | ||
if (importDeclaration.source.value !== 'ember') return null; | ||
if (!importDeclaration.source) { | ||
return null; | ||
} | ||
if (importDeclaration.source.value !== 'ember') { | ||
return null; | ||
} | ||
return importDeclaration.specifiers[0].local.name; | ||
@@ -381,3 +385,5 @@ } | ||
function hasDuplicateDependentKeys(callExp) { | ||
if (!isComputedProp(callExp)) return false; | ||
if (!isComputedProp(callExp)) { | ||
return false; | ||
} | ||
@@ -422,3 +428,5 @@ const dependentKeys = parseDependentKeys(callExp); | ||
const unwrappedExpressions = dependentKeys.map(key => { | ||
if (typeof key !== 'string' || !braceExpressionRegexp.test(key)) return key; | ||
if (typeof key !== 'string' || !braceExpressionRegexp.test(key)) { | ||
return key; | ||
} | ||
@@ -425,0 +433,0 @@ const braceExpansionPart = key.match(braceExpressionRegexp)[0]; |
'use strict'; | ||
const { isIdentifier, isObjectPattern, isVariableDeclarator } = require('./types'); | ||
const EMBER_NAMESPACES = ['inject.controller', 'inject.service']; | ||
@@ -156,7 +158,19 @@ | ||
function isInitImportedFrom(node, module) { | ||
function isDestructuring(node) { | ||
return ( | ||
isVariableDeclarator(node) && | ||
node.init && | ||
isIdentifier(node.init) && | ||
node.id && | ||
isObjectPattern(node.id) | ||
); | ||
} | ||
function isIdentifierImportedFrom(node, module) { | ||
const { name } = node.init; | ||
const pp = node.parent.parent; | ||
if (!pp || !pp.body || !pp.body.some) { | ||
// `import` may only appear at the top level, ie. in a `Program` node | ||
// also, a `Program` node will always have a `body` attribute | ||
if (!pp || pp.type !== 'Program') { | ||
return false; | ||
@@ -184,3 +198,4 @@ } | ||
getFullNames, | ||
isInitImportedFrom, | ||
isDestructuring, | ||
isIdentifierImportedFrom, | ||
}; |
@@ -51,2 +51,3 @@ 'use strict'; | ||
// eslint-disable-next-line complexity | ||
function determinePropertyType(node, parentType) { | ||
@@ -53,0 +54,0 @@ if (ember.isInjectedServiceProp(node.value)) { |
@@ -173,3 +173,5 @@ 'use strict'; | ||
function collectObjectPatternBindings(node, initialObjToBinding) { | ||
if (!isObjectPattern(node.id)) return []; | ||
if (!isObjectPattern(node.id)) { | ||
return []; | ||
} | ||
@@ -179,3 +181,5 @@ const identifiers = Object.keys(initialObjToBinding); | ||
const bindingIndex = identifiers.indexOf(objBindingName); | ||
if (bindingIndex === -1) return []; | ||
if (bindingIndex === -1) { | ||
return []; | ||
} | ||
@@ -182,0 +186,0 @@ const binding = identifiers[bindingIndex]; |
{ | ||
"name": "eslint-plugin-ember", | ||
"version": "7.1.0", | ||
"version": "7.2.0", | ||
"description": "Eslint plugin for Ember.js apps", | ||
@@ -55,6 +55,9 @@ "main": "lib/index.js", | ||
"babel-eslint": "^10.0.3", | ||
"eslint": "^6.4.0", | ||
"eslint-config-prettier": "^6.3.0", | ||
"eslint": "^6.5.1", | ||
"eslint-config-prettier": "^6.4.0", | ||
"eslint-plugin-eslint-comments": "^3.1.2", | ||
"eslint-plugin-eslint-plugin": "^2.1.0", | ||
"eslint-plugin-filenames": "^1.3.2", | ||
"eslint-plugin-import": "^2.18.2", | ||
"eslint-plugin-node": "^10.0.0", | ||
"eslint-plugin-prettier": "^3.1.1", | ||
@@ -88,3 +91,3 @@ "jest": "^24.9.0", | ||
"functions": 99, | ||
"lines": 98, | ||
"lines": 97, | ||
"statements": 97 | ||
@@ -91,0 +94,0 @@ } |
248099
5245
12