Repository: ember-cli/eslint-plugin-ember
Pull request #503 (2019-09-07 23:05:37)

Refactor utils to move type checking utils to a separate file and alphabetize
The previous list of utils was too disorganized, making it difficult to find functions, and difficult to know where to put new ones.


Patch:
diff --git a/lib/rules/avoid-leaking-state-in-ember-objects.js b/lib/rules/avoid-leaking-state-in-ember-objects.js
index 57187505..02a4942d 100644
--- a/lib/rules/avoid-leaking-state-in-ember-objects.js
+++ b/lib/rules/avoid-leaking-state-in-ember-objects.js
@@ -1,7 +1,7 @@
 'use strict';
 
 const ember = require('../utils/ember');
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 
 const DEFAULT_IGNORED_PROPERTIES = [
   'classNames',
@@ -19,14 +19,14 @@ const isAllowed = function(property) {
   const value = property.value;
   return (
     ember.isFunctionExpression(value) ||
-    utils.isLiteral(value) ||
-    utils.isIdentifier(value) ||
-    utils.isCallExpression(value) ||
-    utils.isBinaryExpression(value) ||
-    utils.isTemplateLiteral(value) ||
-    utils.isTaggedTemplateExpression(value) ||
-    utils.isMemberExpression(value) ||
-    utils.isUnaryExpression(value)
+    types.isLiteral(value) ||
+    types.isIdentifier(value) ||
+    types.isCallExpression(value) ||
+    types.isBinaryExpression(value) ||
+    types.isTemplateLiteral(value) ||
+    types.isTaggedTemplateExpression(value) ||
+    types.isMemberExpression(value) ||
+    types.isUnaryExpression(value)
   );
 };
 
diff --git a/lib/rules/closure-actions.js b/lib/rules/closure-actions.js
index 4db9a7b2..33c7a585 100644
--- a/lib/rules/closure-actions.js
+++ b/lib/rules/closure-actions.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 
 //------------------------------------------------------------------------------
 // Components - Closure actions
@@ -30,8 +30,8 @@ module.exports = {
     return {
       MemberExpression(node) {
         const isSendAction =
-          utils.isThisExpression(node.object) &&
-          utils.isIdentifier(node.property) &&
+          types.isThisExpression(node.object) &&
+          types.isIdentifier(node.property) &&
           node.property.name === 'sendAction';
 
         if (isSendAction) {
diff --git a/lib/rules/computed-property-getters.js b/lib/rules/computed-property-getters.js
index e7b1bdc2..ebd04ec3 100644
--- a/lib/rules/computed-property-getters.js
+++ b/lib/rules/computed-property-getters.js
@@ -1,7 +1,7 @@
 'use strict';
 
 const ember = require('../utils/ember');
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 
 //------------------------------------------------------------------------------
 // General rule - Prevent using a getter inside computed properties.
@@ -36,7 +36,7 @@ module.exports = {
     };
 
     const requireGetterOnlyWithASetterInComputedProperty = function(node) {
-      const objectExpressions = node.arguments.filter(arg => utils.isObjectExpression(arg));
+      const objectExpressions = node.arguments.filter(arg => types.isObjectExpression(arg));
       if (objectExpressions.length) {
         const { properties } = objectExpressions[0];
         const getters = properties.filter(
@@ -55,7 +55,7 @@ module.exports = {
     };
 
     const preventGetterInComputedProperty = function(node) {
-      const objectExpressions = node.arguments.filter(arg => utils.isObjectExpression(arg));
+      const objectExpressions = node.arguments.filter(arg => types.isObjectExpression(arg));
       if (objectExpressions.length) {
         const { properties } = objectExpressions[0];
         const getters = properties.filter(
@@ -71,7 +71,7 @@ module.exports = {
     };
 
     const requireGetterInComputedProperty = function(node) {
-      const objectExpressions = node.arguments.filter(arg => utils.isObjectExpression(arg));
+      const objectExpressions = node.arguments.filter(arg => types.isObjectExpression(arg));
       if (objectExpressions.length) {
         const { properties } = objectExpressions[0];
         const getters = properties.filter(
diff --git a/lib/rules/jquery-ember-run.js b/lib/rules/jquery-ember-run.js
index 41181f2f..5e2068be 100644
--- a/lib/rules/jquery-ember-run.js
+++ b/lib/rules/jquery-ember-run.js
@@ -1,6 +1,7 @@
 'use strict';
 
 const utils = require('../utils/utils');
+const types = require('../utils/types');
 const ember = require('../utils/ember');
 
 //------------------------------------------------------------------------------
@@ -28,8 +29,8 @@ module.exports = {
 
     const isJqueryUsed = function(node) {
       return (
-        utils.isMemberExpression(node) &&
-        utils.isCallExpression(node.object) &&
+        types.isMemberExpression(node) &&
+        types.isCallExpression(node.object) &&
         ember.isModule(node.object, '$')
       );
     };
@@ -52,8 +53,8 @@ module.exports = {
               const expression = fnExpression.expression;
 
               if (
-                utils.isCallExpression(expression) &&
-                utils.isMemberExpression(expression.callee) &&
+                types.isCallExpression(expression) &&
+                types.isMemberExpression(expression.callee) &&
                 !isRunUsed(expression)
               ) {
                 report(expression.callee);
diff --git a/lib/rules/named-functions-in-promises.js b/lib/rules/named-functions-in-promises.js
index fb17aa86..f2ca2b14 100644
--- a/lib/rules/named-functions-in-promises.js
+++ b/lib/rules/named-functions-in-promises.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 
 //------------------------------------------------------------------------------
 // General rule - Use named functions defined on objects to handle promises
@@ -35,11 +35,11 @@ module.exports = {
         if (hasPromiseExpression(node)) {
           if (
             allowSimpleArrowFunction &&
-            utils.isConciseArrowFunctionWithCallExpression(firstArg)
+            types.isConciseArrowFunctionWithCallExpression(firstArg)
           ) {
             return;
           }
-          if (utils.isFunctionExpression(firstArg) || utils.isArrowFunctionExpression(firstArg)) {
+          if (types.isFunctionExpression(firstArg) || types.isArrowFunctionExpression(firstArg)) {
             report(node);
           }
         }
@@ -51,8 +51,8 @@ module.exports = {
       const promisesMethods = ['then', 'catch', 'finally'];
 
       return (
-        utils.isCallExpression(callee.object) &&
-        utils.isIdentifier(callee.property) &&
+        types.isCallExpression(callee.object) &&
+        types.isIdentifier(callee.property) &&
         promisesMethods.indexOf(callee.property.name) > -1
       );
     }
diff --git a/lib/rules/no-arrow-function-computed-properties.js b/lib/rules/no-arrow-function-computed-properties.js
index c90713e5..aaf40283 100644
--- a/lib/rules/no-arrow-function-computed-properties.js
+++ b/lib/rules/no-arrow-function-computed-properties.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 const emberUtils = require('../utils/ember');
 
 const ERROR_MESSAGE = 'Do not use arrow functions in computed properties';
@@ -22,7 +22,7 @@ module.exports = {
         if (
           emberUtils.isComputedProp(node) &&
           node.arguments.length > 0 &&
-          utils.isArrowFunctionExpression(node.arguments[node.arguments.length - 1])
+          types.isArrowFunctionExpression(node.arguments[node.arguments.length - 1])
         ) {
           context.report(node.arguments[node.arguments.length - 1], ERROR_MESSAGE);
         }
diff --git a/lib/rules/no-attrs-in-components.js b/lib/rules/no-attrs-in-components.js
index 23125b26..56878a79 100644
--- a/lib/rules/no-attrs-in-components.js
+++ b/lib/rules/no-attrs-in-components.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 
 const MESSAGE = 'Do not use this.attrs';
 
@@ -22,7 +22,7 @@ module.exports = {
 
   create(context) {
     function isThisAttrsExpression(node) {
-      return utils.isThisExpression(node.object) && node.property.name === 'attrs';
+      return types.isThisExpression(node.object) && node.property.name === 'attrs';
     }
 
     return {
diff --git a/lib/rules/no-capital-letters-in-routes.js b/lib/rules/no-capital-letters-in-routes.js
index 7cbeff7d..fe46a4cd 100644
--- a/lib/rules/no-capital-letters-in-routes.js
+++ b/lib/rules/no-capital-letters-in-routes.js
@@ -1,7 +1,7 @@
 'use strict';
 
 const ember = require('../utils/ember');
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 
 //------------------------------------------------------------------------------
 // Routing - No capital letters in routes
@@ -26,7 +26,7 @@ module.exports = {
 
     return {
       CallExpression(node) {
-        if (ember.isRoute(node) && node.arguments[0] && utils.isLiteral(node.arguments[0])) {
+        if (ember.isRoute(node) && node.arguments[0] && types.isLiteral(node.arguments[0])) {
           const routeName = node.arguments[0].value;
           const hasAnyUppercaseLetter = Boolean(routeName.match('[A-Z]'));
 
diff --git a/lib/rules/no-function-prototype-extensions.js b/lib/rules/no-function-prototype-extensions.js
index 5ca0c065..425d5250 100644
--- a/lib/rules/no-function-prototype-extensions.js
+++ b/lib/rules/no-function-prototype-extensions.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 
 //----------------------------------------------------------------------------------------------
 // General rule - Don't use Ember's function prototype extensions like .property() or .observe()
@@ -25,7 +25,7 @@ module.exports = {
 
     const isFunctionPrototypeExtension = function(property) {
       return (
-        utils.isIdentifier(property) &&
+        types.isIdentifier(property) &&
         functionPrototypeExtensionNames.indexOf(property.name) !== -1
       );
     };
@@ -39,9 +39,9 @@ module.exports = {
         const callee = node.callee;
 
         if (
-          utils.isCallExpression(node) &&
-          utils.isMemberExpression(callee) &&
-          utils.isFunctionExpression(callee.object) &&
+          types.isCallExpression(node) &&
+          types.isMemberExpression(callee) &&
+          types.isFunctionExpression(callee.object) &&
           isFunctionPrototypeExtension(callee.property)
         ) {
           report(node);
diff --git a/lib/rules/no-get.js b/lib/rules/no-get.js
index e3c29891..f407f5ed 100644
--- a/lib/rules/no-get.js
+++ b/lib/rules/no-get.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 
 function makeErrorMessageForGet(property, isImportedGet) {
   return isImportedGet
@@ -29,12 +29,12 @@ module.exports = {
         // **************************
 
         if (
-          utils.isMemberExpression(node.callee) &&
-          utils.isThisExpression(node.callee.object) &&
-          utils.isIdentifier(node.callee.property) &&
+          types.isMemberExpression(node.callee) &&
+          types.isThisExpression(node.callee.object) &&
+          types.isIdentifier(node.callee.property) &&
           node.callee.property.name === 'get' &&
           node.arguments.length === 1 &&
-          utils.isStringLiteral(node.arguments[0]) &&
+          types.isStringLiteral(node.arguments[0]) &&
           !node.arguments[0].value.includes('.')
         ) {
           // Example: this.get('foo');
@@ -42,11 +42,11 @@ module.exports = {
         }
 
         if (
-          utils.isIdentifier(node.callee) &&
+          types.isIdentifier(node.callee) &&
           node.callee.name === 'get' &&
           node.arguments.length === 2 &&
-          utils.isThisExpression(node.arguments[0]) &&
-          utils.isStringLiteral(node.arguments[1]) &&
+          types.isThisExpression(node.arguments[0]) &&
+          types.isStringLiteral(node.arguments[1]) &&
           !node.arguments[1].value.includes('.')
         ) {
           // Example: get(this, 'foo');
@@ -58,9 +58,9 @@ module.exports = {
         // **************************
 
         if (
-          utils.isMemberExpression(node.callee) &&
-          utils.isThisExpression(node.callee.object) &&
-          utils.isIdentifier(node.callee.property) &&
+          types.isMemberExpression(node.callee) &&
+          types.isThisExpression(node.callee.object) &&
+          types.isIdentifier(node.callee.property) &&
           node.callee.property.name === 'getProperties' &&
           validateGetPropertiesArguments(node.arguments)
         ) {
@@ -69,9 +69,9 @@ module.exports = {
         }
 
         if (
-          utils.isIdentifier(node.callee) &&
+          types.isIdentifier(node.callee) &&
           node.callee.name === 'getProperties' &&
-          utils.isThisExpression(node.arguments[0]) &&
+          types.isThisExpression(node.arguments[0]) &&
           validateGetPropertiesArguments(node.arguments.slice(1))
         ) {
           // Example: getProperties(this, 'foo', 'bar');
@@ -83,9 +83,9 @@ module.exports = {
 };
 
 function validateGetPropertiesArguments(args) {
-  if (args.length === 1 && utils.isArrayExpression(args[0])) {
+  if (args.length === 1 && types.isArrayExpression(args[0])) {
     return validateGetPropertiesArguments(args[0].elements);
   }
   // We can only handle string arguments without nested property paths.
-  return args.every(argument => utils.isStringLiteral(argument) && !argument.value.includes('.'));
+  return args.every(argument => types.isStringLiteral(argument) && !argument.value.includes('.'));
 }
diff --git a/lib/rules/no-global-jquery.js b/lib/rules/no-global-jquery.js
index a7556fd4..08f4291c 100644
--- a/lib/rules/no-global-jquery.js
+++ b/lib/rules/no-global-jquery.js
@@ -2,6 +2,7 @@
 
 const ember = require('../utils/ember');
 const utils = require('../utils/utils');
+const types = require('../utils/types');
 
 const ALIASES = ['$', 'jQuery'];
 const ERROR_MESSAGE = 'Do not use global `$` or `jQuery`';
@@ -62,7 +63,7 @@ module.exports = {
           // only to test against.
           if (
             node.init &&
-            utils.isMemberExpression(node.init) &&
+            types.isMemberExpression(node.init) &&
             isEmberMemberExpression(node.init)
           ) {
             const isJQueryVariable = node.init.property.name === '$';
diff --git a/lib/rules/no-incorrect-calls-with-inline-anonymous-functions.js b/lib/rules/no-incorrect-calls-with-inline-anonymous-functions.js
index c64f264e..59699829 100644
--- a/lib/rules/no-incorrect-calls-with-inline-anonymous-functions.js
+++ b/lib/rules/no-incorrect-calls-with-inline-anonymous-functions.js
@@ -1,11 +1,11 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 const ERROR_MESSAGE =
   'Do not use anonymous functions as arguments to `debounce`, `once`, and `scheduleOnce`.';
 
 function isMemberExpressionOnRun(node) {
-  return utils.isMemberExpression(node.callee) && node.callee.object.name === 'run';
+  return types.isMemberExpression(node.callee) && node.callee.object.name === 'run';
 }
 
 const functionRules = [
@@ -31,7 +31,7 @@ module.exports = {
   create(context) {
     function checkArgumentsForInlineFunction(node) {
       node.arguments.forEach((argument, index) => {
-        if (utils.isAnyFunctionExpression(argument)) {
+        if (types.isAnyFunctionExpression(argument)) {
           context.report(node.arguments[index], ERROR_MESSAGE);
         }
       });
diff --git a/lib/rules/no-invalid-debug-function-arguments.js b/lib/rules/no-invalid-debug-function-arguments.js
index c5bd1b34..d703aa1c 100644
--- a/lib/rules/no-invalid-debug-function-arguments.js
+++ b/lib/rules/no-invalid-debug-function-arguments.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 const emberUtils = require('../utils/ember');
 
 //------------------------------------------------------------------------------
@@ -45,8 +45,8 @@ function isDebugFunctionWithReversedArgs(node) {
   return (
     isDebugFunction(node) &&
     node.arguments.length >= 2 &&
-    !utils.isString(node.arguments[0]) &&
-    utils.isString(node.arguments[1])
+    !types.isString(node.arguments[0]) &&
+    types.isString(node.arguments[1])
   );
 }
 
diff --git a/lib/rules/no-jquery.js b/lib/rules/no-jquery.js
index b84fdfbd..d54fb9da 100644
--- a/lib/rules/no-jquery.js
+++ b/lib/rules/no-jquery.js
@@ -2,6 +2,7 @@
 
 const ember = require('../utils/ember');
 const utils = require('../utils/utils');
+const types = require('../utils/types');
 
 //------------------------------------------------------------------------------
 // General rule -  Disallow usage of jQuery
@@ -42,7 +43,7 @@ module.exports = {
 
       VariableDeclarator(node) {
         if (emberImportAliasName) {
-          if (node.init && utils.isMemberExpression(node.init)) {
+          if (node.init && types.isMemberExpression(node.init)) {
             // assignment of type const $ = Ember.$;
             destructuredAssignment = node.id.name;
           } else {
diff --git a/lib/rules/no-on-calls-in-components.js b/lib/rules/no-on-calls-in-components.js
index 7659daed..3dbaacd4 100644
--- a/lib/rules/no-on-calls-in-components.js
+++ b/lib/rules/no-on-calls-in-components.js
@@ -2,6 +2,7 @@
 
 const ember = require('../utils/ember');
 const utils = require('../utils/utils');
+const types = require('../utils/types');
 
 //----------------------------------------------
 // Don’t use .on() for component lifecycle events.
@@ -44,13 +45,13 @@ module.exports = {
       const args = utils.parseArgs(value);
 
       return (
-        utils.isCallExpression(value) &&
+        types.isCallExpression(value) &&
         lifecycleHooks.indexOf(args[0]) > -1 &&
-        ((utils.isIdentifier(callee) && callee.name === 'on') ||
-          (utils.isMemberExpression(callee) &&
-            utils.isIdentifier(callee.object) &&
+        ((types.isIdentifier(callee) && callee.name === 'on') ||
+          (types.isMemberExpression(callee) &&
+            types.isIdentifier(callee.object) &&
             callee.object.name === 'Ember' &&
-            utils.isIdentifier(callee.property) &&
+            types.isIdentifier(callee.property) &&
             callee.property.name === 'on'))
       );
     };
diff --git a/lib/rules/no-side-effects.js b/lib/rules/no-side-effects.js
index 6e259d42..8f1a60ce 100644
--- a/lib/rules/no-side-effects.js
+++ b/lib/rules/no-side-effects.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 const ember = require('../utils/ember');
 
 //------------------------------------------------------------------------------
@@ -42,12 +42,12 @@ module.exports = {
       CallExpression(node) {
         const callee = node.callee;
         const isEmberSet =
-          (utils.isIdentifier(callee) && isUnallowedMethod(callee.name)) ||
-          (utils.isMemberExpression(callee) &&
-            (utils.isThisExpression(callee.object) ||
+          (types.isIdentifier(callee) && isUnallowedMethod(callee.name)) ||
+          (types.isMemberExpression(callee) &&
+            (types.isThisExpression(callee.object) ||
               callee.object.name === 'Ember' ||
               callee.object.name === emberImportAliasName) &&
-            utils.isIdentifier(callee.property) &&
+            types.isIdentifier(callee.property) &&
             isUnallowedMethod(callee.property.name));
 
         if (isEmberSet) {
@@ -57,7 +57,7 @@ module.exports = {
             ancestor =>
               ancestor.type === 'Property' &&
               ancestor.key.name === 'set' &&
-              utils.isFunctionExpression(ancestor.value)
+              types.isFunctionExpression(ancestor.value)
           );
 
           if (
diff --git a/lib/rules/no-unnecessary-route-path-option.js b/lib/rules/no-unnecessary-route-path-option.js
index f15ceaff..143cc282 100644
--- a/lib/rules/no-unnecessary-route-path-option.js
+++ b/lib/rules/no-unnecessary-route-path-option.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 const ember = require('../utils/ember');
 
 //------------------------------------------------------------------------------
@@ -29,7 +29,7 @@ module.exports = {
         }
 
         const hasExplicitPathOption =
-          utils.isObjectExpression(node.arguments[1]) &&
+          types.isObjectExpression(node.arguments[1]) &&
           hasPropertyWithKeyName(node.arguments[1], 'path');
         if (!hasExplicitPathOption) {
           return;
diff --git a/lib/rules/no-unnecessary-service-injection-argument.js b/lib/rules/no-unnecessary-service-injection-argument.js
index 59aded1c..920dce33 100644
--- a/lib/rules/no-unnecessary-service-injection-argument.js
+++ b/lib/rules/no-unnecessary-service-injection-argument.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 const emberUtils = require('../utils/ember');
 
 //------------------------------------------------------------------------------
@@ -28,7 +28,7 @@ module.exports = {
         if (
           !emberUtils.isInjectedServiceProp(node.value) ||
           node.value.arguments.length !== 1 ||
-          !utils.isLiteral(node.value.arguments[0])
+          !types.isLiteral(node.value.arguments[0])
         ) {
           return;
         }
diff --git a/lib/rules/no-volatile-computed-properties.js b/lib/rules/no-volatile-computed-properties.js
index e7a87b56..5ddf5873 100644
--- a/lib/rules/no-volatile-computed-properties.js
+++ b/lib/rules/no-volatile-computed-properties.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 const emberUtils = require('../utils/ember');
 
 const ERROR_MESSAGE = 'Do not use volatile computed properties';
@@ -20,10 +20,10 @@ module.exports = {
     return {
       CallExpression(node) {
         if (
-          utils.isMemberExpression(node.callee) &&
-          utils.isCallExpression(node.callee.object) &&
+          types.isMemberExpression(node.callee) &&
+          types.isCallExpression(node.callee.object) &&
           emberUtils.isComputedProp(node.callee.object) &&
-          utils.isIdentifier(node.callee.property) &&
+          types.isIdentifier(node.callee.property) &&
           node.callee.property.name === 'volatile'
         ) {
           context.report(node.callee.property, ERROR_MESSAGE);
diff --git a/lib/rules/require-computed-macros.js b/lib/rules/require-computed-macros.js
index bb85d91c..968de676 100644
--- a/lib/rules/require-computed-macros.js
+++ b/lib/rules/require-computed-macros.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 const emberUtils = require('../utils/ember');
 const propertyGetterUtils = require('../utils/property-getter');
 
@@ -30,13 +30,13 @@ const ERROR_MESSAGE_EQUAL = makeErrorMessage('equal');
  * @returns {boolean} Whether the node looks like `this.x && this.y && this.z`.
  */
 function isSimpleThisExpressionsInsideLogicalExpression(node, operator) {
-  if (!utils.isLogicalExpression(node)) {
+  if (!types.isLogicalExpression(node)) {
     return false;
   }
 
   let current = node;
   while (current !== null) {
-    if (utils.isLogicalExpression(current)) {
+    if (types.isLogicalExpression(current)) {
       if (!propertyGetterUtils.isSimpleThisExpression(current.right)) {
         return false;
       }
@@ -66,7 +66,7 @@ function getThisExpressions(nodeLogicalExpression) {
   const arrayOfThisExpressions = [];
   let current = nodeLogicalExpression;
   while (current !== null) {
-    if (utils.isLogicalExpression(current)) {
+    if (types.isLogicalExpression(current)) {
       arrayOfThisExpressions.push(current.right);
       current = current.left;
     } else {
@@ -152,7 +152,7 @@ module.exports = {
         }
 
         const lastArg = node.arguments[node.arguments.length - 1];
-        if (!utils.isFunctionExpression(lastArg)) {
+        if (!types.isFunctionExpression(lastArg)) {
           return;
         }
 
@@ -160,27 +160,27 @@ module.exports = {
           return;
         }
 
-        if (!utils.isReturnStatement(lastArg.body.body[0])) {
+        if (!types.isReturnStatement(lastArg.body.body[0])) {
           return;
         }
 
         const statement = lastArg.body.body[0].argument;
 
         if (
-          utils.isUnaryExpression(statement) &&
+          types.isUnaryExpression(statement) &&
           statement.operator === '!' &&
           propertyGetterUtils.isSimpleThisExpression(statement.argument)
         ) {
           reportSingleArg(node, statement.argument, 'not');
-        } else if (utils.isLogicalExpression(statement)) {
+        } else if (types.isLogicalExpression(statement)) {
           if (isSimpleThisExpressionsInsideLogicalExpression(statement, '&&')) {
             reportLogicalExpression(node, statement, 'and');
           } else if (isSimpleThisExpressionsInsideLogicalExpression(statement, '||')) {
             reportLogicalExpression(node, statement, 'or');
           }
         } else if (
-          utils.isBinaryExpression(statement) &&
-          utils.isLiteral(statement.right) &&
+          types.isBinaryExpression(statement) &&
+          types.isLiteral(statement.right) &&
           propertyGetterUtils.isSimpleThisExpression(statement.left)
         ) {
           if (statement.operator === '===') {
diff --git a/lib/rules/require-computed-property-dependencies.js b/lib/rules/require-computed-property-dependencies.js
index a42ef595..5fe3c0d8 100644
--- a/lib/rules/require-computed-property-dependencies.js
+++ b/lib/rules/require-computed-property-dependencies.js
@@ -11,7 +11,7 @@ function getTraverser() {
 }
 
 const Traverser = getTraverser();
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 const propertyGetterUtils = require('../utils/property-getter');
 
 /**
@@ -22,7 +22,7 @@ const propertyGetterUtils = require('../utils/property-getter');
  * @returns {boolean}
  */
 function isIdentifier(node, name) {
-  if (!utils.isIdentifier(node)) {
+  if (!types.isIdentifier(node)) {
     return false;
   }
 
@@ -44,15 +44,15 @@ function isIdentifier(node, name) {
  */
 function isMemberExpression(node, objectName, propertyName) {
   if (!objectName && !propertyName) {
-    return node && utils.isMemberExpression(node);
+    return node && types.isMemberExpression(node);
   }
 
   return (
     node &&
-    utils.isMemberExpression(node) &&
+    types.isMemberExpression(node) &&
     !node.computed &&
     (objectName === 'this'
-      ? utils.isThisExpression(node.object)
+      ? types.isThisExpression(node.object)
       : isIdentifier(node.object, objectName)) &&
     isIdentifier(node.property, propertyName)
   );
@@ -91,7 +91,7 @@ function parseComputedDependencies(args) {
   for (let i = 0; i < args.length - 1; i++) {
     const arg = args[i];
 
-    if (utils.isStringLiteral(arg)) {
+    if (types.isStringLiteral(arg)) {
       keys.push(arg);
     } else {
       dynamicKeys.push(arg);
@@ -160,7 +160,7 @@ function findEmberGetCalls(node) {
 
   new Traverser().traverse(node, {
     enter(child) {
-      if (utils.isCallExpression(child)) {
+      if (types.isCallExpression(child)) {
         const dependency = extractEmberGetDependencies(child);
 
         if (dependency.length > 0) {
@@ -185,8 +185,8 @@ function findThisGetCalls(node) {
   new Traverser().traverse(node, {
     enter(child, parent) {
       if (
-        utils.isMemberExpression(child) &&
-        !(utils.isCallExpression(parent) && parent.callee === child) &&
+        types.isMemberExpression(child) &&
+        !(types.isCallExpression(parent) && parent.callee === child) &&
         propertyGetterUtils.isSimpleThisExpression(child)
       ) {
         results.push(child);
@@ -205,7 +205,7 @@ function findThisGetCalls(node) {
  * @returns {Array<ASTNode>}
  */
 function getArrayOrRest(args) {
-  if (args.length === 1 && utils.isArrayExpression(args[0])) {
+  if (args.length === 1 && types.isArrayExpression(args[0])) {
     return args[0].elements;
   }
   return args;
@@ -224,7 +224,7 @@ function extractEmberGetDependencies(call) {
   ) {
     const firstArg = call.arguments[0];
 
-    if (utils.isStringLiteral(firstArg)) {
+    if (types.isStringLiteral(firstArg)) {
       return [firstArg.value];
     }
   } else if (
@@ -234,20 +234,20 @@ function extractEmberGetDependencies(call) {
     const firstArg = call.arguments[0];
     const secondArgument = call.arguments[1];
 
-    if (utils.isThisExpression(firstArg) && utils.isStringLiteral(secondArgument)) {
+    if (types.isThisExpression(firstArg) && types.isStringLiteral(secondArgument)) {
       return [secondArgument.value];
     }
   } else if (isMemberExpression(call.callee, 'this', 'getProperties')) {
     return getArrayOrRest(call.arguments)
-      .filter(utils.isStringLiteral)
+      .filter(types.isStringLiteral)
       .map(arg => arg.value);
   } else if (isMemberExpression(call.callee, 'Ember', 'getProperties')) {
     const firstArg = call.arguments[0];
     const rest = call.arguments.slice(1);
 
-    if (utils.isThisExpression(firstArg)) {
+    if (types.isThisExpression(firstArg)) {
       return getArrayOrRest(rest)
-        .filter(utils.isStringLiteral)
+        .filter(types.isStringLiteral)
         .map(arg => arg.value);
     }
   }
diff --git a/lib/rules/require-super-in-init.js b/lib/rules/require-super-in-init.js
index 3f89ddd0..4e4c84ce 100644
--- a/lib/rules/require-super-in-init.js
+++ b/lib/rules/require-super-in-init.js
@@ -2,6 +2,7 @@
 
 const ember = require('../utils/ember');
 const utils = require('../utils/utils');
+const types = require('../utils/types');
 
 /**
  * Locates nodes with either an ExpressionStatement or ReturnStatement
@@ -38,16 +39,16 @@ function checkForSuper(nodes) {
   if (nodes.length === 0) return false;
 
   return nodes.some(n => {
-    if (utils.isCallExpression(n.expression)) {
+    if (types.isCallExpression(n.expression)) {
       const fnCallee = n.expression.callee;
       return (
-        utils.isMemberExpression(fnCallee) &&
-        utils.isThisExpression(fnCallee.object) &&
-        utils.isIdentifier(fnCallee.property) &&
+        types.isMemberExpression(fnCallee) &&
+        types.isThisExpression(fnCallee.object) &&
+        types.isIdentifier(fnCallee.property) &&
         fnCallee.property.name === '_super'
       );
-    } else if (utils.isReturnStatement(n)) {
-      if (!n.argument || !utils.isCallExpression(n.argument)) return false;
+    } else if (types.isReturnStatement(n)) {
+      if (!n.argument || !types.isCallExpression(n.argument)) return false;
 
       const fnCallee = n.argument.callee;
       return fnCallee.property.name === '_super';
diff --git a/lib/rules/route-path-style.js b/lib/rules/route-path-style.js
index 02ee6b67..90cdc995 100644
--- a/lib/rules/route-path-style.js
+++ b/lib/rules/route-path-style.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 const ember = require('../utils/ember');
 
 //------------------------------------------------------------------------------
@@ -34,7 +34,7 @@ module.exports = {
         // 2. this.route('route', { path: 'path' });
 
         const hasExplicitPathOption =
-          utils.isObjectExpression(node.arguments[1]) &&
+          types.isObjectExpression(node.arguments[1]) &&
           hasPropertyWithKeyName(node.arguments[1], 'path');
         const pathValueNode = hasExplicitPathOption
           ? getPropertyByKeyName(node.arguments[1], 'path').value
diff --git a/lib/rules/routes-segments-snake-case.js b/lib/rules/routes-segments-snake-case.js
index 9f0eb08b..05592d3f 100644
--- a/lib/rules/routes-segments-snake-case.js
+++ b/lib/rules/routes-segments-snake-case.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 const ember = require('../utils/ember');
 const snakeCase = require('snake-case');
 
@@ -46,7 +46,7 @@ module.exports = {
       CallExpression(node) {
         if (!ember.isRoute(node)) return;
 
-        const routeOptions = utils.isObjectExpression(node.arguments[1])
+        const routeOptions = types.isObjectExpression(node.arguments[1])
           ? node.arguments[1]
           : false;
 
diff --git a/lib/rules/use-brace-expansion.js b/lib/rules/use-brace-expansion.js
index 622239c8..f704cad2 100644
--- a/lib/rules/use-brace-expansion.js
+++ b/lib/rules/use-brace-expansion.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 const ember = require('../utils/ember');
 
 //------------------------------------------------------------------------------
@@ -28,7 +28,7 @@ module.exports = {
 
     return {
       CallExpression(node) {
-        if (!ember.isComputedProp(node) || utils.isMemberExpression(node.callee)) {
+        if (!ember.isComputedProp(node) || types.isMemberExpression(node.callee)) {
           return;
         }
 
@@ -41,7 +41,7 @@ module.exports = {
         const problem = node.arguments
           .filter(
             arg =>
-              utils.isLiteral(arg) && typeof arg.value === 'string' && arg.value.indexOf('.') >= 0
+              types.isLiteral(arg) && typeof arg.value === 'string' && arg.value.indexOf('.') >= 0
           )
           .map(e => e.value.split('.'))
           .find(
diff --git a/lib/rules/use-ember-get-and-set.js b/lib/rules/use-ember-get-and-set.js
index 7a30e2d7..54624f47 100644
--- a/lib/rules/use-ember-get-and-set.js
+++ b/lib/rules/use-ember-get-and-set.js
@@ -3,10 +3,11 @@
 const path = require('path');
 const ember = require('../utils/ember');
 const utils = require('../utils/utils');
+const types = require('../utils/types');
 
 const collectObjectPatternBindings = utils.collectObjectPatternBindings;
-const isIdentifier = utils.isIdentifier;
-const isThisExpression = utils.isThisExpression;
+const isIdentifier = types.isIdentifier;
+const isThisExpression = types.isThisExpression;
 
 //------------------------------------------------------------------------------
 // General - use get and set
diff --git a/lib/utils/ember.js b/lib/utils/ember.js
index 1974ad17..3491dd1d 100644
--- a/lib/utils/ember.js
+++ b/lib/utils/ember.js
@@ -1,6 +1,7 @@
 'use strict';
 
 const utils = require('./utils');
+const types = require('./types');
 
 module.exports = {
   isDSModel,
@@ -54,17 +55,17 @@ module.exports = {
 
 function isLocalModule(callee, element) {
   return (
-    (utils.isIdentifier(callee) && callee.name === element) ||
-    (utils.isIdentifier(callee.object) && callee.object.name === element)
+    (types.isIdentifier(callee) && callee.name === element) ||
+    (types.isIdentifier(callee.object) && callee.object.name === element)
   );
 }
 
 function isEmberModule(callee, element, module) {
-  const memberExp = utils.isMemberExpression(callee.object) ? callee.object : callee;
+  const memberExp = types.isMemberExpression(callee.object) ? callee.object : callee;
 
   return (
     isLocalModule(memberExp, module) &&
-    utils.isIdentifier(memberExp.property) &&
+    types.isIdentifier(memberExp.property) &&
     memberExp.property.name === element
   );
 }
@@ -73,10 +74,10 @@ function isPropOfType(node, type) {
   const calleeNode = node.callee;
 
   return (
-    utils.isCallExpression(node) &&
-    ((utils.isIdentifier(calleeNode) && calleeNode.name === type) ||
-      (utils.isMemberExpression(calleeNode) &&
-        utils.isIdentifier(calleeNode.property) &&
+    types.isCallExpression(node) &&
+    ((types.isIdentifier(calleeNode) && calleeNode.name === type) ||
+      (types.isMemberExpression(calleeNode) &&
+        types.isIdentifier(calleeNode.property) &&
         calleeNode.property.name === type))
   );
 }
@@ -87,7 +88,7 @@ function isModule(node, element, module) {
   const moduleName = module || 'Ember';
 
   return (
-    utils.isCallExpression(node) &&
+    types.isCallExpression(node) &&
     (isLocalModule(node.callee, element) || isEmberModule(node.callee, element, moduleName))
   );
 }
@@ -174,10 +175,10 @@ function isObserverProp(node) {
 
 function isComputedProp(node) {
   const allowedMemberExpNames = ['volatile', 'readOnly', 'property', 'meta'];
-  if (utils.isMemberExpression(node.callee) && utils.isCallExpression(node.callee.object)) {
+  if (types.isMemberExpression(node.callee) && types.isCallExpression(node.callee.object)) {
     return (
       isModule(node.callee.object, 'computed') &&
-      utils.isIdentifier(node.callee.property) &&
+      types.isIdentifier(node.callee.property) &&
       allowedMemberExpNames.indexOf(node.callee.property.name) > -1
     );
   }
@@ -185,35 +186,35 @@ function isComputedProp(node) {
 }
 
 function isArrayProp(node) {
-  if (utils.isNewExpression(node.value)) {
+  if (types.isNewExpression(node.value)) {
     const parsedCallee = utils.parseCallee(node.value);
     return parsedCallee.pop() === 'A';
   }
 
-  return utils.isArrayExpression(node.value);
+  return types.isArrayExpression(node.value);
 }
 
 function isObjectProp(node) {
-  if (utils.isNewExpression(node.value)) {
+  if (types.isNewExpression(node.value)) {
     const parsedCallee = utils.parseCallee(node.value);
     return parsedCallee.pop() === 'Object';
   }
 
-  return utils.isObjectExpression(node.value);
+  return types.isObjectExpression(node.value);
 }
 
 function isCustomProp(property) {
   const value = property.value;
-  const isCustomObjectProp = utils.isObjectExpression(value) && property.key.name !== 'actions';
+  const isCustomObjectProp = types.isObjectExpression(value) && property.key.name !== 'actions';
 
   return (
-    utils.isLiteral(value) ||
-    utils.isIdentifier(value) ||
-    utils.isArrayExpression(value) ||
-    utils.isUnaryExpression(value) ||
+    types.isLiteral(value) ||
+    types.isIdentifier(value) ||
+    types.isArrayExpression(value) ||
+    types.isUnaryExpression(value) ||
     isCustomObjectProp ||
-    utils.isConditionalExpression(value) ||
-    utils.isTaggedTemplateExpression(value)
+    types.isConditionalExpression(value) ||
+    types.isTaggedTemplateExpression(value)
   );
 }
 
@@ -222,7 +223,7 @@ function isRouteLifecycleHook(property) {
 }
 
 function isActionsProp(property) {
-  return property.key.name === 'actions' && utils.isObjectExpression(property.value);
+  return property.key.name === 'actions' && types.isObjectExpression(property.value);
 }
 
 function isComponentLifecycleHookName(name) {
@@ -249,9 +250,9 @@ function isComponentLifecycleHook(property) {
 
 function isRoute(node) {
   return (
-    utils.isMemberExpression(node.callee) &&
-    utils.isThisExpression(node.callee.object) &&
-    utils.isIdentifier(node.callee.property) &&
+    types.isMemberExpression(node.callee) &&
+    types.isThisExpression(node.callee.object) &&
+    types.isIdentifier(node.callee.property) &&
     node.callee.property.name === 'route'
   );
 }
@@ -332,27 +333,27 @@ function getEmberImportAliasName(importDeclaration) {
 
 function isSingleLineFn(property) {
   return (
-    utils.isCallExpression(property.value) &&
+    types.isCallExpression(property.value) &&
     utils.getSize(property.value) === 1 &&
     !isObserverProp(property.value) &&
-    (isComputedProp(property.value) || !utils.isCallWithFunctionExpression(property.value))
+    (isComputedProp(property.value) || !types.isCallWithFunctionExpression(property.value))
   );
 }
 
 function isMultiLineFn(property) {
   return (
-    utils.isCallExpression(property.value) &&
+    types.isCallExpression(property.value) &&
     utils.getSize(property.value) > 1 &&
     !isObserverProp(property.value) &&
-    (isComputedProp(property.value) || !utils.isCallWithFunctionExpression(property.value))
+    (isComputedProp(property.value) || !types.isCallWithFunctionExpression(property.value))
   );
 }
 
 function isFunctionExpression(property) {
   return (
-    utils.isFunctionExpression(property) ||
-    utils.isArrowFunctionExpression(property) ||
-    utils.isCallWithFunctionExpression(property)
+    types.isFunctionExpression(property) ||
+    types.isArrowFunctionExpression(property) ||
+    types.isCallWithFunctionExpression(property)
   );
 }
 
@@ -396,12 +397,12 @@ function parseDependentKeys(callExp) {
   // Check whether we have a MemberExpression, eg. computed(...).volatile()
   const isMemberExpCallExp =
     !callExp.arguments.length &&
-    utils.isMemberExpression(callExp.callee) &&
-    utils.isCallExpression(callExp.callee.object);
+    types.isMemberExpression(callExp.callee) &&
+    types.isCallExpression(callExp.callee.object);
 
   const args = isMemberExpCallExp ? callExp.callee.object.arguments : callExp.arguments;
 
-  const dependentKeys = args.filter(arg => utils.isLiteral(arg)).map(literal => literal.value);
+  const dependentKeys = args.filter(arg => types.isLiteral(arg)).map(literal => literal.value);
 
   return unwrapBraceExpressions(dependentKeys);
 }
diff --git a/lib/utils/property-getter.js b/lib/utils/property-getter.js
index ea9fd15f..ec61e94f 100644
--- a/lib/utils/property-getter.js
+++ b/lib/utils/property-getter.js
@@ -1,4 +1,4 @@
-const utils = require('./utils');
+const types = require('./types');
 
 /**
  * Checks if a MemberExpression node looks like `this.x` or `this.x.y`.
@@ -7,18 +7,18 @@ const utils = require('./utils');
  * @returns {boolean} Whether the node looks like `this.x` or `this.x.y`.
  */
 function isSimpleThisExpression(node) {
-  if (!utils.isMemberExpression(node)) {
+  if (!types.isMemberExpression(node)) {
     return false;
   }
 
   let current = node;
   while (current !== null) {
-    if (utils.isMemberExpression(current) && !current.computed) {
-      if (!utils.isIdentifier(current.property)) {
+    if (types.isMemberExpression(current) && !current.computed) {
+      if (!types.isIdentifier(current.property)) {
         return false;
       }
       current = current.object;
-    } else if (utils.isThisExpression(current)) {
+    } else if (types.isThisExpression(current)) {
       return true;
     } else {
       return false;
diff --git a/lib/utils/types.js b/lib/utils/types.js
new file mode 100644
index 00000000..77785980
--- /dev/null
+++ b/lib/utils/types.js
@@ -0,0 +1,275 @@
+'use strict';
+
+module.exports = {
+  isAnyFunctionExpression,
+  isArrayExpression,
+  isArrowFunctionExpression,
+  isBinaryExpression,
+  isCallExpression,
+  isCallWithFunctionExpression,
+  isConciseArrowFunctionWithCallExpression,
+  isConditionalExpression,
+  isExpressionStatement,
+  isFunctionExpression,
+  isIdentifier,
+  isLiteral,
+  isLogicalExpression,
+  isMemberExpression,
+  isNewExpression,
+  isObjectExpression,
+  isObjectPattern,
+  isReturnStatement,
+  isString,
+  isStringLiteral,
+  isTaggedTemplateExpression,
+  isTemplateLiteral,
+  isThisExpression,
+  isUnaryExpression,
+  isVariableDeclarator,
+};
+
+/**
+ * Check whether or not a node is an ArrowFunctionExpression or FunctionExpression.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an ArrowFunctionExpression or FunctionExpression.
+ */
+function isAnyFunctionExpression(node) {
+  return isArrowFunctionExpression(node) || isFunctionExpression(node);
+}
+
+/**
+ * Check whether or not a node is an ArrayExpression.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an ArrayExpression.
+ */
+function isArrayExpression(node) {
+  return node !== undefined && node.type === 'ArrayExpression';
+}
+
+/**
+ * Check whether or not a node is an ArrowFunctionExpression.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an ArrowFunctionExpression.
+ */
+function isArrowFunctionExpression(node) {
+  return node !== undefined && node.type === 'ArrowFunctionExpression';
+}
+
+/**
+ * Check whether or not a node is an BinaryExpression.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an BinaryExpression.
+ */
+function isBinaryExpression(node) {
+  return node !== undefined && node.type === 'BinaryExpression';
+}
+
+/**
+ * Check whether or not a node is an CallExpression.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an CallExpression.
+ */
+function isCallExpression(node) {
+  return node !== undefined && node.type === 'CallExpression';
+}
+
+/**
+ * Check whether or not a node is a CallExpression that has a FunctionExpression
+ * as first argument, eg.:
+ * tSomeAction: mysteriousFnc(function(){})
+ *
+ * @param  {[type]}  node [description]
+ * @return {Boolean}      [description]
+ */
+function isCallWithFunctionExpression(node) {
+  const callObj = isMemberExpression(node.callee) ? node.callee.object : node;
+  const firstArg = callObj.arguments ? callObj.arguments[0] : null;
+  return (
+    callObj !== undefined && isCallExpression(callObj) && firstArg && isFunctionExpression(firstArg)
+  );
+}
+
+/**
+ * Check whether or not a node is an ArrowFunctionExpression with concise body
+ * that contains a call expression.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an ArrowFunctionExpression
+ * with concise body.
+ */
+function isConciseArrowFunctionWithCallExpression(node) {
+  return isArrowFunctionExpression(node) && node.expression && isCallExpression(node.body);
+}
+
+/**
+ * Check whether or not a node is a ConditionalExpression.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is a ConditionalExpression.
+ */
+function isConditionalExpression(node) {
+  return node !== undefined && node.type === 'ConditionalExpression';
+}
+
+/**
+ * Check whether or not a node is an ExpressionStatement.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an ExpressionStatement.
+ */
+function isExpressionStatement(node) {
+  return node !== undefined && node.type === 'ExpressionStatement';
+}
+
+/**
+ * Check whether or not a node is an FunctionExpression.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an FunctionExpression.
+ */
+function isFunctionExpression(node) {
+  return node !== undefined && node.type === 'FunctionExpression';
+}
+
+/**
+ * Check whether or not a node is an Identifier.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an Identifier.
+ */
+function isIdentifier(node) {
+  return node !== undefined && node.type === 'Identifier';
+}
+
+/**
+ * Check whether or not a node is an Literal.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an Literal.
+ */
+function isLiteral(node) {
+  return node !== undefined && node.type === 'Literal';
+}
+
+/**
+ * Check whether or not a node is an LogicalExpression.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an LogicalExpression.
+ */
+function isLogicalExpression(node) {
+  return node !== undefined && node.type === 'LogicalExpression';
+}
+
+/**
+ * Check whether or not a node is an MemberExpression.
+ *
+ * @param {Object} node The node to check.
+ * @return {boolean} Whether or not the node is an MemberExpression.
+ */
+function isMemberExpression(node) {
+  return node !== undefined && node.type === 'MemberExpression';
+}
+
+/**
+ * Check whether or not a node is an NewExpression.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an NewExpression.
+ */
+function isNewExpression(node) {
+  return node !== undefined && node.type === 'NewExpression';
+}
+
+/**
+ * Check whether or not a node is an ObjectExpression.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an ObjectExpression.
+ */
+function isObjectExpression(node) {
+  return node !== undefined && node.type === 'ObjectExpression';
+}
+
+/**
+ * Check whether or not a node is an ObjectPattern.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an ObjectPattern.
+ */
+function isObjectPattern(node) {
+  return node !== undefined && node.type === 'ObjectPattern';
+}
+
+/**
+ * Check whether or not a node is a ReturnStatement
+ *
+ * @param {Object} node The node to check.
+ * @return {Boolean} Whether or not the node is a ReturnStatement.
+ */
+function isReturnStatement(node) {
+  return node !== undefined && node.type && node.type === 'ReturnStatement';
+}
+
+function isString(node) {
+  return isTemplateLiteral(node) || (isLiteral(node) && typeof node.value === 'string');
+}
+
+function isStringLiteral(node) {
+  return isLiteral(node) && typeof node.value === 'string';
+}
+
+/**
+ * Check whether or not a node is a TaggedTemplateExpression.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is a TaggedTemplateExpression.
+ */
+function isTaggedTemplateExpression(node) {
+  return node !== undefined && node.type === 'TaggedTemplateExpression';
+}
+
+/**
+ * Check whether or not a node is a TemplateLiteral.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is a TemplateLiteral.
+ */
+function isTemplateLiteral(node) {
+  return node !== undefined && node.type === 'TemplateLiteral';
+}
+
+/**
+ * Check whether or not a node is an ThisExpression.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an ThisExpression.
+ */
+function isThisExpression(node) {
+  return node !== undefined && node.type === 'ThisExpression';
+}
+
+/**
+ * Check whether or not a node is an UnaryExpression.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is an Literal.
+ */
+function isUnaryExpression(node) {
+  return node !== undefined && node.type === 'UnaryExpression';
+}
+
+/**
+ * Check whether or not a node is a VariableDeclarator.
+ *
+ * @param {Object} node The node to check.
+ * @returns {boolean} Whether or not the node is a VariableDeclarator.
+ */
+function isVariableDeclarator(node) {
+  return node !== undefined && node.type === 'VariableDeclarator';
+}
diff --git a/lib/utils/utils.js b/lib/utils/utils.js
index 39d94cc6..22d7a232 100644
--- a/lib/utils/utils.js
+++ b/lib/utils/utils.js
@@ -1,40 +1,25 @@
 'use strict';
 
-module.exports = {
-  findNodes,
+const {
+  isCallExpression,
   isIdentifier,
   isLiteral,
-  isUnaryExpression,
   isMemberExpression,
-  isCallExpression,
-  isObjectExpression,
-  isObjectPattern,
-  isArrayExpression,
-  isFunctionExpression,
-  isExpressionStatement,
-  isAnyFunctionExpression,
-  isArrowFunctionExpression,
-  isConciseArrowFunctionWithCallExpression,
   isNewExpression,
-  isCallWithFunctionExpression,
-  isThisExpression,
-  isConditionalExpression,
-  isTemplateLiteral,
-  isTaggedTemplateExpression,
-  isGlobalCallExpression,
-  isString,
-  isStringLiteral,
-  getSize,
-  parseCallee,
-  parseArgs,
+  isObjectPattern,
+} = require('../utils/types');
+
+module.exports = {
+  collectObjectPatternBindings,
+  findNodes,
   findUnorderedProperty,
+  getParent,
   getPropertyValue,
-  collectObjectPatternBindings,
+  getSize,
   isEmptyMethod,
-  isBinaryExpression,
-  isLogicalExpression,
-  isReturnStatement,
-  getParent,
+  isGlobalCallExpression,
+  parseArgs,
+  parseCallee,
 };
 
 /**
@@ -54,234 +39,6 @@ function findNodes(body, nodeName) {
   return nodesArray;
 }
 
-/**
- * Check whether or not a node is an Identifier.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an Identifier.
- */
-function isIdentifier(node) {
-  return node !== undefined && node.type === 'Identifier';
-}
-
-/**
- * Check whether or not a node is an Literal.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an Literal.
- */
-function isLiteral(node) {
-  return node !== undefined && node.type === 'Literal';
-}
-
-/**
- * Check whether or not a node is an UnaryExpression.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an Literal.
- */
-function isUnaryExpression(node) {
-  return node !== undefined && node.type === 'UnaryExpression';
-}
-
-/**
- * Check whether or not a node is an MemberExpression.
- *
- * @param {Object} node The node to check.
- * @return {boolean} Whether or not the node is an MemberExpression.
- */
-function isMemberExpression(node) {
-  return node !== undefined && node.type === 'MemberExpression';
-}
-
-/**
- * Check whether or not a node is an CallExpression.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an CallExpression.
- */
-function isCallExpression(node) {
-  return node !== undefined && node.type === 'CallExpression';
-}
-
-/**
- * Check whether or not a node is an BinaryExpression.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an BinaryExpression.
- */
-function isBinaryExpression(node) {
-  return node !== undefined && node.type === 'BinaryExpression';
-}
-
-/**
- * Check whether or not a node is an LogicalExpression.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an LogicalExpression.
- */
-function isLogicalExpression(node) {
-  return node !== undefined && node.type === 'LogicalExpression';
-}
-
-/**
- * Check whether or not a node is an ObjectExpression.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an ObjectExpression.
- */
-function isObjectExpression(node) {
-  return node !== undefined && node.type === 'ObjectExpression';
-}
-
-/**
- * Check whether or not a node is an ObjectPattern.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an ObjectPattern.
- */
-function isObjectPattern(node) {
-  return node !== undefined && node.type === 'ObjectPattern';
-}
-
-/**
- * Check whether or not a node is an ArrayExpression.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an ArrayExpression.
- */
-function isArrayExpression(node) {
-  return node !== undefined && node.type === 'ArrayExpression';
-}
-
-/**
- * Check whether or not a node is an FunctionExpression.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an FunctionExpression.
- */
-function isFunctionExpression(node) {
-  return node !== undefined && node.type === 'FunctionExpression';
-}
-
-/**
- * Check whether or not a node is an isExpressionStatement.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an isExpressionStatement.
- */
-function isExpressionStatement(node) {
-  return node !== undefined && node.type === 'ExpressionStatement';
-}
-
-/**
- * Check whether or not a node is an ArrowFunctionExpression or FunctionExpression.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an ArrowFunctionExpression or FunctionExpression.
- */
-function isAnyFunctionExpression(node) {
-  return isArrowFunctionExpression(node) || isFunctionExpression(node);
-}
-
-/**
- * Check whether or not a node is an ArrowFunctionExpression.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an ArrowFunctionExpression.
- */
-function isArrowFunctionExpression(node) {
-  return node !== undefined && node.type === 'ArrowFunctionExpression';
-}
-
-/**
- * Check whether or not a node is an ArrowFunctionExpression with concise body
- * that contains a call expression.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an ArrowFunctionExpression
- * with concise body.
- */
-function isConciseArrowFunctionWithCallExpression(node) {
-  return isArrowFunctionExpression(node) && node.expression && isCallExpression(node.body);
-}
-
-/**
- * Check whether or not a node is an NewExpression.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an NewExpression.
- */
-function isNewExpression(node) {
-  return node !== undefined && node.type === 'NewExpression';
-}
-
-/**
- * Check whether or not a node is a CallExpression that has a FunctionExpression
- * as first argument, eg.:
- * tSomeAction: mysteriousFnc(function(){})
- *
- * @param  {[type]}  node [description]
- * @return {Boolean}      [description]
- */
-function isCallWithFunctionExpression(node) {
-  const callObj = isMemberExpression(node.callee) ? node.callee.object : node;
-  const firstArg = callObj.arguments ? callObj.arguments[0] : null;
-  return (
-    callObj !== undefined && isCallExpression(callObj) && firstArg && isFunctionExpression(firstArg)
-  );
-}
-
-/**
- * Check whether or not a node is a ReturnStatement
- *
- * @param {Object} node The node to check.
- * @return {Boolean} Whether or not the node is a ReturnStatement.
- */
-function isReturnStatement(node) {
-  return node !== undefined && node.type && node.type === 'ReturnStatement';
-}
-
-/**
- * Check whether or not a node is an ThisExpression.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is an ThisExpression.
- */
-function isThisExpression(node) {
-  return node !== undefined && node.type === 'ThisExpression';
-}
-
-/**
- * Check whether or not a node is a ConditionalExpression.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is a ConditionalExpression.
- */
-function isConditionalExpression(node) {
-  return node !== undefined && node.type === 'ConditionalExpression';
-}
-
-/**
- * Check whether or not a node is a TaggedTemplateExpression.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is a TaggedTemplateExpression.
- */
-function isTaggedTemplateExpression(node) {
-  return node !== undefined && node.type === 'TaggedTemplateExpression';
-}
-
-/**
- * Check whether or not a node is a TemplateLiteral.
- *
- * @param {Object} node The node to check.
- * @returns {boolean} Whether or not the node is a TemplateLiteral.
- */
-function isTemplateLiteral(node) {
-  return node !== undefined && node.type === 'TemplateLiteral';
-}
-
 /**
  * Check if given call is a global call
  *
@@ -301,14 +58,6 @@ function isGlobalCallExpression(node, destructuredName, aliases) {
   return !isDestructured && isGlobalCall;
 }
 
-function isString(node) {
-  return isTemplateLiteral(node) || (isLiteral(node) && typeof node.value === 'string');
-}
-
-function isStringLiteral(node) {
-  return isLiteral(node) && typeof node.value === 'string';
-}
-
 /**
  * Get size of expression in lines
  *


Test patch:
diff --git a/lib/rules/no-restricted-resolver-tests.js b/lib/rules/no-restricted-resolver-tests.js
index 1c51fd62..81465789 100644
--- a/lib/rules/no-restricted-resolver-tests.js
+++ b/lib/rules/no-restricted-resolver-tests.js
@@ -1,6 +1,7 @@
 'use strict';
 
 const utils = require('../utils/utils');
+const types = require('../utils/types');
 
 //------------------------------------------------------------------------------------------------
 // General Rule - Don't use constructs or configuration that use the restricted resolver in tests.
@@ -26,7 +27,7 @@ function hasOnlyStringArgument(node) {
   const parentMethodCall = getParentCallExpression(node);
   const args = parentMethodCall.arguments;
 
-  return args.length === 1 && utils.isLiteral(args[0]);
+  return args.length === 1 && types.isLiteral(args[0]);
 }
 
 function hasUnitTrue(node) {
@@ -109,7 +110,7 @@ module.exports = {
         }
 
         const lastArgument = getLastArgument(node);
-        const lastArgumentIsObject = utils.isObjectExpression(lastArgument);
+        const lastArgumentIsObject = types.isObjectExpression(lastArgument);
 
         if (lastArgumentIsObject && hasUnitTrue(lastArgument)) {
           context.report(lastArgument, getNoUnitTrueMessage(fn));
diff --git a/lib/rules/no-test-and-then.js b/lib/rules/no-test-and-then.js
index c06251ed..ad4a3cd3 100644
--- a/lib/rules/no-test-and-then.js
+++ b/lib/rules/no-test-and-then.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const utils = require('../utils/utils');
+const types = require('../utils/types');
 const emberUtils = require('../utils/ember');
 
 const ERROR_MESSAGE = 'Use `await` instead of `andThen` test wait helper.';
@@ -29,7 +29,7 @@ module.exports = {
     return {
       CallExpression(node) {
         const callee = node.callee;
-        if (utils.isIdentifier(callee) && callee.name === 'andThen') {
+        if (types.isIdentifier(callee) && callee.name === 'andThen') {
           context.report({
             node,
             message: ERROR_MESSAGE,
diff --git a/tests/lib/utils/types-test.js b/tests/lib/utils/types-test.js
new file mode 100644
index 00000000..3c8072fc
--- /dev/null
+++ b/tests/lib/utils/types-test.js
@@ -0,0 +1,194 @@
+const babelEslint = require('babel-eslint');
+const types = require('../../../lib/utils/types');
+
+function parse(code) {
+  return babelEslint.parse(code).body[0].expression;
+}
+
+describe('function sort order', function() {
+  it('has exported functions in sorted order', function() {
+    expect(Object.getOwnPropertyNames(types)).toEqual(Object.getOwnPropertyNames(types).sort());
+  });
+});
+
+describe('isArrayExpression', () => {
+  const node = parse('test = []').right;
+
+  it('should check if node is array expression', () => {
+    expect(types.isArrayExpression(node)).toBeTruthy();
+  });
+});
+
+describe('isArrowFunctionExpression', () => {
+  const node = parse('test = () => {}').right;
+
+  it('should check if node is arrow function expression', () => {
+    expect(types.isArrowFunctionExpression(node)).toBeTruthy();
+  });
+});
+
+describe('isCallExpression', () => {
+  const node = parse('test()');
+
+  it('should check if node is call expression', () => {
+    expect(types.isCallExpression(node)).toBeTruthy();
+  });
+});
+
+describe('isCallWithFunctionExpression', () => {
+  const node = parse('mysteriousFnc(function(){})');
+
+  it('should check if node is call with function expression', () => {
+    expect(types.isCallWithFunctionExpression(node)).toBeTruthy();
+  });
+});
+
+describe('isConciseArrowFunctionExpressionWithCall', () => {
+  const node = parse('test = () => foo()').right;
+  const blockNode = parse('test = () => { foo() }').right;
+
+  it('should check if node is concise arrow function expression with call expression body', () => {
+    expect(types.isConciseArrowFunctionWithCallExpression(node)).toBeTruthy();
+  });
+
+  it('should check if node does not have block body', () => {
+    expect(!types.isConciseArrowFunctionWithCallExpression(blockNode)).toBeTruthy();
+  });
+});
+
+describe('isConditionalExpression', () => {
+  const node = parse("test = true ? 'asd' : 'qwe'").right;
+
+  it('should check if node is a conditional expression', () => {
+    expect(types.isConditionalExpression(node)).toBeTruthy();
+  });
+});
+
+describe('isFunctionExpression', () => {
+  const node = parse('test = function () {}').right;
+
+  it('should check if node is function expression', () => {
+    expect(types.isFunctionExpression(node)).toBeTruthy();
+  });
+});
+
+describe('isIdentifier', () => {
+  const node = parse('test');
+
+  it('should check if node is identifier', () => {
+    expect(types.isIdentifier(node)).toBeTruthy();
+  });
+});
+
+describe('isLiteral', () => {
+  const node = parse('"test"');
+
+  it('should check if node is identifier', () => {
+    expect(types.isLiteral(node)).toBeTruthy();
+  });
+});
+
+describe('isMemberExpression', () => {
+  const node = parse('test.value');
+
+  it('should check if node is member expression', () => {
+    expect(types.isMemberExpression(node)).toBeTruthy();
+  });
+});
+
+describe('isNewExpression', () => {
+  const node = parse('new Date()');
+
+  it('should check if node is new expression', () => {
+    expect(types.isNewExpression(node)).toBeTruthy();
+  });
+});
+
+describe('isObjectExpression', () => {
+  const node = parse('test = {}').right;
+
+  it('should check if node is identifier', () => {
+    expect(types.isObjectExpression(node)).toBeTruthy();
+  });
+});
+
+describe('isReturnStatement', () => {
+  const node = babelEslint.parse('return').body[0];
+
+  it('should check if node is a return statement', () => {
+    expect(types.isReturnStatement(node)).toBeTruthy();
+  });
+});
+
+describe('isString', () => {
+  it('recognizes template literals', () => {
+    const node = parse('`template literal`');
+    expect(types.isString(node)).toBeTruthy();
+  });
+
+  it('recognizes template literals with interpolation', () => {
+    const node = parse('`template ${123} literal`'); // eslint-disable-line no-template-curly-in-string
+    expect(types.isString(node)).toBeTruthy();
+  });
+
+  it('recognizes string literals', () => {
+    const node = parse("'string literal'");
+    expect(types.isString(node)).toBeTruthy();
+  });
+
+  it('ignores identifiers', () => {
+    const node = parse('MY_VARIABLE');
+    expect(types.isString(node)).not.toBeTruthy();
+  });
+
+  it('ignores number literals', () => {
+    const node = parse('123');
+    expect(types.isString(node)).not.toBeTruthy();
+  });
+});
+
+describe('isStringLiteral', () => {
+  it('recognizes string literals', () => {
+    const node = parse("'string literal'");
+    expect(types.isStringLiteral(node)).toBeTruthy();
+  });
+
+  it('ignores template literals', () => {
+    const node = parse('`template literal`');
+    expect(types.isStringLiteral(node)).not.toBeTruthy();
+  });
+
+  it('ignores identifiers', () => {
+    const node = parse('MY_VARIABLE');
+    expect(types.isStringLiteral(node)).not.toBeTruthy();
+  });
+
+  it('ignores number literals', () => {
+    const node = parse('123');
+    expect(types.isStringLiteral(node)).not.toBeTruthy();
+  });
+});
+
+describe('isTaggedTemplateExpression', () => {
+  const node = parse('test = hbs`lorem ipsum`;').right;
+
+  it('should check if node is a tagged template expression', () => {
+    expect(types.isTaggedTemplateExpression(node)).toBeTruthy();
+  });
+});
+
+describe('isThisExpression', () => {
+  const node = parse('this');
+
+  it('should check if node is "this" expression', () => {
+    expect(types.isThisExpression(node)).toBeTruthy();
+  });
+});
+
+describe('isUnaryExpression', () => {
+  const node = parse('-1');
+
+  it('should check if node is identifier', () => {
+    expect(types.isUnaryExpression(node)).toBeTruthy();
+  });
+});
diff --git a/tests/lib/utils/utils-test.js b/tests/lib/utils/utils-test.js
index 94801242..d4091477 100644
--- a/tests/lib/utils/utils-test.js
+++ b/tests/lib/utils/utils-test.js
@@ -11,6 +11,53 @@ function parseVariableDeclarator(code) {
   return babelEslint.parse(code).body[0].declarations[0];
 }
 
+describe('collectObjectPatternBindings', () => {
+  it('collects bindings correctly', () => {
+    const node = parseVariableDeclarator('const { $ } = Ember');
+    const collectedBindings = utils.collectObjectPatternBindings(node, {
+      Ember: ['$'],
+    });
+
+    expect(collectedBindings).toEqual(['$']);
+  });
+
+  it('collects aliased bindings correctly', () => {
+    const node = parseVariableDeclarator('const { $:foo } = Ember');
+    const collectedBindings = utils.collectObjectPatternBindings(node, {
+      Ember: ['$'],
+    });
+
+    expect(collectedBindings).toEqual(['foo']);
+  });
+
+  it('collects only relevant bindings correctly for multiple destructurings', () => {
+    const node = parseVariableDeclarator('const { $, computed } = Ember');
+    const collectedBindings = utils.collectObjectPatternBindings(node, {
+      Ember: ['$'],
+    });
+
+    expect(collectedBindings).toEqual(['$']);
+  });
+
+  it('collects only relevant bindings correctly for multiple destructurings and aliases', () => {
+    const node = parseVariableDeclarator('const { $: foo, computed } = Ember');
+    const collectedBindings = utils.collectObjectPatternBindings(node, {
+      Ember: ['$'],
+    });
+
+    expect(collectedBindings).toEqual(['foo']);
+  });
+
+  it('collects multiple relevant bindings', () => {
+    const node = parseVariableDeclarator('const { $: foo, computed } = Ember');
+    const collectedBindings = utils.collectObjectPatternBindings(node, {
+      Ember: ['$', 'computed'],
+    });
+
+    expect(collectedBindings).toEqual(['foo', 'computed']);
+  });
+});
+
 describe('findNodes', () => {
   const node = parse(`test = [
     {test: "a"}, b, "c", [d, e], "f", "g", h, {test: "i"}, function() {}, [], new Date()
@@ -33,171 +80,9 @@ describe('findNodes', () => {
   });
 });
 
-describe('isIdentifier', () => {
-  const node = parse('test');
-
-  it('should check if node is identifier', () => {
-    expect(utils.isIdentifier(node)).toBeTruthy();
-  });
-});
-
-describe('isLiteral', () => {
-  const node = parse('"test"');
-
-  it('should check if node is identifier', () => {
-    expect(utils.isLiteral(node)).toBeTruthy();
-  });
-});
-
-describe('isUnaryExpression', () => {
-  const node = parse('-1');
-
-  it('should check if node is identifier', () => {
-    expect(utils.isUnaryExpression(node)).toBeTruthy();
-  });
-});
-
-describe('isMemberExpression', () => {
-  const node = parse('test.value');
-
-  it('should check if node is member expression', () => {
-    expect(utils.isMemberExpression(node)).toBeTruthy();
-  });
-});
-
-describe('isCallExpression', () => {
-  const node = parse('test()');
-
-  it('should check if node is call expression', () => {
-    expect(utils.isCallExpression(node)).toBeTruthy();
-  });
-});
-
-describe('isObjectExpression', () => {
-  const node = parse('test = {}').right;
-
-  it('should check if node is identifier', () => {
-    expect(utils.isObjectExpression(node)).toBeTruthy();
-  });
-});
-
-describe('isArrayExpression', () => {
-  const node = parse('test = []').right;
-
-  it('should check if node is array expression', () => {
-    expect(utils.isArrayExpression(node)).toBeTruthy();
-  });
-});
-
-describe('isFunctionExpression', () => {
-  const node = parse('test = function () {}').right;
-
-  it('should check if node is function expression', () => {
-    expect(utils.isFunctionExpression(node)).toBeTruthy();
-  });
-});
-
-describe('isArrowFunctionExpression', () => {
-  const node = parse('test = () => {}').right;
-
-  it('should check if node is arrow function expression', () => {
-    expect(utils.isArrowFunctionExpression(node)).toBeTruthy();
-  });
-});
-
-describe('isConciseArrowFunctionExpressionWithCall', () => {
-  const node = parse('test = () => foo()').right;
-  const blockNode = parse('test = () => { foo() }').right;
-
-  it('should check if node is concise arrow function expression with call expression body', () => {
-    expect(utils.isConciseArrowFunctionWithCallExpression(node)).toBeTruthy();
-  });
-
-  it('should check if node does not have block body', () => {
-    expect(!utils.isConciseArrowFunctionWithCallExpression(blockNode)).toBeTruthy();
-  });
-});
-
-describe('isNewExpression', () => {
-  const node = parse('new Date()');
-
-  it('should check if node is new expression', () => {
-    expect(utils.isNewExpression(node)).toBeTruthy();
-  });
-});
-
-describe('isCallWithFunctionExpression', () => {
-  const node = parse('mysteriousFnc(function(){})');
-
-  it('should check if node is call with function expression', () => {
-    expect(utils.isCallWithFunctionExpression(node)).toBeTruthy();
-  });
-});
-
-describe('isReturnStatement', () => {
-  const node = babelEslint.parse('return').body[0];
-
-  it('should check if node is a return statement', () => {
-    expect(utils.isReturnStatement(node)).toBeTruthy();
-  });
-});
-
-describe('isThisExpression', () => {
-  const node = parse('this');
-
-  it('should check if node is "this" expression', () => {
-    expect(utils.isThisExpression(node)).toBeTruthy();
-  });
-});
-
-describe('isConditionalExpression', () => {
-  const node = parse("test = true ? 'asd' : 'qwe'").right;
-
-  it('should check if node is a conditional expression', () => {
-    expect(utils.isConditionalExpression(node)).toBeTruthy();
-  });
-});
-
-describe('isTaggedTemplateExpression', () => {
-  const node = parse('test = hbs`lorem ipsum`;').right;
-
-  it('should check if node is a tagged template expression', () => {
-    expect(utils.isTaggedTemplateExpression(node)).toBeTruthy();
-  });
-});
-
-describe('getSize', () => {
-  const node = parse(
-    'some = {\nfew: "line",\nheight: "statement",\nthat: "should",\nhave: "6 lines",\n};'
-  );
-
-  it('should check size of given expression', () => {
-    expect(utils.getSize(node)).toEqual(6);
-  });
-});
-
-describe('parseCallee', () => {
-  it('should parse calleeExpression', () => {
-    const node = parse('Ember.computed.or("asd", "qwe")');
-    const parsedCallee = utils.parseCallee(node);
-    expect(parsedCallee).toHaveLength(3, 'it has 3 elements in array');
-    expect(parsedCallee).toEqual(['Ember', 'computed', 'or']);
-  });
-
-  it('should parse newExpression', () => {
-    const node = parse('new Ember.A()');
-    const parsedCallee = utils.parseCallee(node);
-    expect(parsedCallee).toHaveLength(2, 'it has 2 elements in array');
-    expect(parsedCallee).toEqual(['Ember', 'A']);
-  });
-});
-
-describe('parseArgs', () => {
-  it('should parse arguments', () => {
-    const node = parse('Ember.computed("asd", "qwe", "zxc", function() {})');
-    const parsedArgs = utils.parseArgs(node);
-    expect(parsedArgs).toHaveLength(3);
-    expect(parsedArgs).toEqual(['asd', 'qwe', 'zxc']);
+describe('function sort order', function() {
+  it('has exported functions in sorted order', function() {
+    expect(Object.getOwnPropertyNames(utils)).toEqual(Object.getOwnPropertyNames(utils).sort());
   });
 });
 
@@ -261,50 +146,13 @@ describe('getPropertyValue', () => {
   });
 });
 
-describe('collectObjectPatternBindings', () => {
-  it('collects bindings correctly', () => {
-    const node = parseVariableDeclarator('const { $ } = Ember');
-    const collectedBindings = utils.collectObjectPatternBindings(node, {
-      Ember: ['$'],
-    });
-
-    expect(collectedBindings).toEqual(['$']);
-  });
-
-  it('collects aliased bindings correctly', () => {
-    const node = parseVariableDeclarator('const { $:foo } = Ember');
-    const collectedBindings = utils.collectObjectPatternBindings(node, {
-      Ember: ['$'],
-    });
-
-    expect(collectedBindings).toEqual(['foo']);
-  });
-
-  it('collects only relevant bindings correctly for multiple destructurings', () => {
-    const node = parseVariableDeclarator('const { $, computed } = Ember');
-    const collectedBindings = utils.collectObjectPatternBindings(node, {
-      Ember: ['$'],
-    });
-
-    expect(collectedBindings).toEqual(['$']);
-  });
-
-  it('collects only relevant bindings correctly for multiple destructurings and aliases', () => {
-    const node = parseVariableDeclarator('const { $: foo, computed } = Ember');
-    const collectedBindings = utils.collectObjectPatternBindings(node, {
-      Ember: ['$'],
-    });
-
-    expect(collectedBindings).toEqual(['foo']);
-  });
-
-  it('collects multiple relevant bindings', () => {
-    const node = parseVariableDeclarator('const { $: foo, computed } = Ember');
-    const collectedBindings = utils.collectObjectPatternBindings(node, {
-      Ember: ['$', 'computed'],
-    });
+describe('getSize', () => {
+  const node = parse(
+    'some = {\nfew: "line",\nheight: "statement",\nthat: "should",\nhave: "6 lines",\n};'
+  );
 
-    expect(collectedBindings).toEqual(['foo', 'computed']);
+  it('should check size of given expression', () => {
+    expect(utils.getSize(node)).toEqual(6);
   });
 });
 
@@ -320,51 +168,27 @@ describe('isGlobalCallExpression', () => {
   });
 });
 
-describe('isString', () => {
-  it('recognizes template literals', () => {
-    const node = parse('`template literal`');
-    expect(utils.isString(node)).toBeTruthy();
-  });
-
-  it('recognizes template literals with interpolation', () => {
-    const node = parse('`template ${123} literal`'); // eslint-disable-line no-template-curly-in-string
-    expect(utils.isString(node)).toBeTruthy();
-  });
-
-  it('recognizes string literals', () => {
-    const node = parse("'string literal'");
-    expect(utils.isString(node)).toBeTruthy();
-  });
-
-  it('ignores identifiers', () => {
-    const node = parse('MY_VARIABLE');
-    expect(utils.isString(node)).not.toBeTruthy();
-  });
-
-  it('ignores number literals', () => {
-    const node = parse('123');
-    expect(utils.isString(node)).not.toBeTruthy();
+describe('parseArgs', () => {
+  it('should parse arguments', () => {
+    const node = parse('Ember.computed("asd", "qwe", "zxc", function() {})');
+    const parsedArgs = utils.parseArgs(node);
+    expect(parsedArgs).toHaveLength(3);
+    expect(parsedArgs).toEqual(['asd', 'qwe', 'zxc']);
   });
 });
 
-describe('isStringLiteral', () => {
-  it('recognizes string literals', () => {
-    const node = parse("'string literal'");
-    expect(utils.isStringLiteral(node)).toBeTruthy();
-  });
-
-  it('ignores template literals', () => {
-    const node = parse('`template literal`');
-    expect(utils.isStringLiteral(node)).not.toBeTruthy();
-  });
-
-  it('ignores identifiers', () => {
-    const node = parse('MY_VARIABLE');
-    expect(utils.isStringLiteral(node)).not.toBeTruthy();
+describe('parseCallee', () => {
+  it('should parse calleeExpression', () => {
+    const node = parse('Ember.computed.or("asd", "qwe")');
+    const parsedCallee = utils.parseCallee(node);
+    expect(parsedCallee).toHaveLength(3, 'it has 3 elements in array');
+    expect(parsedCallee).toEqual(['Ember', 'computed', 'or']);
   });
 
-  it('ignores number literals', () => {
-    const node = parse('123');
-    expect(utils.isStringLiteral(node)).not.toBeTruthy();
+  it('should parse newExpression', () => {
+    const node = parse('new Ember.A()');
+    const parsedCallee = utils.parseCallee(node);
+    expect(parsedCallee).toHaveLength(2, 'it has 2 elements in array');
+    expect(parsedCallee).toEqual(['Ember', 'A']);
   });
 });