Repository: eslint/eslint
Pull request #9500 (2017-10-22 14:18:20)

Chore: add isValidThisArg in ast-utils.
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

**What is the purpose of this pull request? (put an "X" next to item)**

[x] Other, please explain:

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

**What changes did you make? (Give an overview)**
`isValidThisArg` is used both in `no-useless-call.js` and `prefer-spread.js`. placed it in ast-utils in case some other rules will use it.

**Is there anything you'd like reviewers to focus on?**




eslintbot: LGTM
eslintbot: LGTM
not-an-aardvark: IMO, it might be better to export `equalTokens` from `ast-utils` rather than `isValidThisArg`, because `equalTokens` seems like it's more useful in general. But I'm fine with either.
Aladdin-ADD: > IMO, it might be better to export equalTokens from ast-utils rather than isValidThisArg, because equalTokens seems like it's more useful in general.

maybe we can export both?
not-an-aardvark: I'm fine with that too, although I think `isValidThisArg` is fairly small and situational compared to `equalTokens`.
kaicataldo: I'm fine with both too as long as we have test coverage :)
Aladdin-ADD: @not-an-aardvark @kaicataldo  updated the PR to export `equalTokens`, and added tests.

Patch:
diff --git a/lib/ast-utils.js b/lib/ast-utils.js
index 23d2a7dcb..a186bdee5 100644
--- a/lib/ast-utils.js
+++ b/lib/ast-utils.js
@@ -406,6 +406,31 @@ function createGlobalLinebreakMatcher() {
     return new RegExp(LINEBREAK_MATCHER.source, "g");
 }
 
+/**
+ * Checks whether or not the tokens of two given nodes are same.
+ * @param {ASTNode} left - A node 1 to compare.
+ * @param {ASTNode} right - A node 2 to compare.
+ * @param {SourceCode} sourceCode - The ESLint source code object.
+ * @returns {boolean} the source code for the given node.
+ */
+function equalTokens(left, right, sourceCode) {
+    const tokensL = sourceCode.getTokens(left);
+    const tokensR = sourceCode.getTokens(right);
+
+    if (tokensL.length !== tokensR.length) {
+        return false;
+    }
+    for (let i = 0; i < tokensL.length; ++i) {
+        if (tokensL[i].type !== tokensR[i].type ||
+            tokensL[i].value !== tokensR[i].value
+        ) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 //------------------------------------------------------------------------------
 // Public Interface
 //------------------------------------------------------------------------------
@@ -438,6 +463,7 @@ module.exports = {
     isArrayFromMethod,
     isParenthesised,
     createGlobalLinebreakMatcher,
+    equalTokens,
 
     isArrowToken,
     isClosingBraceToken,
diff --git a/lib/rules/no-useless-call.js b/lib/rules/no-useless-call.js
index eb67bcb3b..e4820ac24 100644
--- a/lib/rules/no-useless-call.js
+++ b/lib/rules/no-useless-call.js
@@ -28,30 +28,6 @@ function isCallOrNonVariadicApply(node) {
     );
 }
 
-/**
- * Checks whether or not the tokens of two given nodes are same.
- * @param {ASTNode} left - A node 1 to compare.
- * @param {ASTNode} right - A node 2 to compare.
- * @param {SourceCode} sourceCode - The ESLint source code object.
- * @returns {boolean} the source code for the given node.
- */
-function equalTokens(left, right, sourceCode) {
-    const tokensL = sourceCode.getTokens(left);
-    const tokensR = sourceCode.getTokens(right);
-
-    if (tokensL.length !== tokensR.length) {
-        return false;
-    }
-    for (let i = 0; i < tokensL.length; ++i) {
-        if (tokensL[i].type !== tokensR[i].type ||
-            tokensL[i].value !== tokensR[i].value
-        ) {
-            return false;
-        }
-    }
-
-    return true;
-}
 
 /**
  * Checks whether or not `thisArg` is not changed by `.call()`/`.apply()`.
@@ -64,7 +40,7 @@ function isValidThisArg(expectedThis, thisArg, sourceCode) {
     if (!expectedThis) {
         return astUtils.isNullOrUndefined(thisArg);
     }
-    return equalTokens(expectedThis, thisArg, sourceCode);
+    return astUtils.equalTokens(expectedThis, thisArg, sourceCode);
 }
 
 //------------------------------------------------------------------------------
diff --git a/lib/rules/prefer-spread.js b/lib/rules/prefer-spread.js
index 1f5785828..c111d5f98 100644
--- a/lib/rules/prefer-spread.js
+++ b/lib/rules/prefer-spread.js
@@ -28,30 +28,6 @@ function isVariadicApplyCalling(node) {
     );
 }
 
-/**
- * Checks whether or not the tokens of two given nodes are same.
- * @param {ASTNode} left - A node 1 to compare.
- * @param {ASTNode} right - A node 2 to compare.
- * @param {SourceCode} sourceCode - The ESLint source code object.
- * @returns {boolean} the source code for the given node.
- */
-function equalTokens(left, right, sourceCode) {
-    const tokensL = sourceCode.getTokens(left);
-    const tokensR = sourceCode.getTokens(right);
-
-    if (tokensL.length !== tokensR.length) {
-        return false;
-    }
-    for (let i = 0; i < tokensL.length; ++i) {
-        if (tokensL[i].type !== tokensR[i].type ||
-            tokensL[i].value !== tokensR[i].value
-        ) {
-            return false;
-        }
-    }
-
-    return true;
-}
 
 /**
  * Checks whether or not `thisArg` is not changed by `.apply()`.
@@ -64,7 +40,7 @@ function isValidThisArg(expectedThis, thisArg, context) {
     if (!expectedThis) {
         return astUtils.isNullOrUndefined(thisArg);
     }
-    return equalTokens(expectedThis, thisArg, context);
+    return astUtils.equalTokens(expectedThis, thisArg, context);
 }
 
 //------------------------------------------------------------------------------


Test patch:
diff --git a/tests/lib/ast-utils.js b/tests/lib/ast-utils.js
index 65600f353..538b941cd 100644
--- a/tests/lib/ast-utils.js
+++ b/tests/lib/ast-utils.js
@@ -1198,4 +1198,22 @@ describe("ast-utils", () => {
             });
         });
     });
+
+    describe("equalTokens", () => {
+        it("should return true if tokens are equal", () => {
+            const code = "a=0;a=0;";
+            const ast = espree.parse(code, ESPREE_CONFIG);
+            const sourceCode = new SourceCode(code, ast);
+
+            assert.strictEqual(astUtils.equalTokens(ast.body[0], ast.body[1], sourceCode), true);
+        });
+
+        it("should return false if tokens are not equal", () => {
+            const code = "a=0;a=1;";
+            const ast = espree.parse(code, ESPREE_CONFIG);
+            const sourceCode = new SourceCode(code, ast);
+
+            assert.strictEqual(astUtils.equalTokens(ast.body[0], ast.body[1], sourceCode), false);
+        });
+    });
 });