Repository: jshint/jshint
Pull request #2219 (2015-02-28 16:08:21)

Allow `this` in class expression methods
Commit d75ef694385ba44ab49b2d2b2cf1f4bed0949ca7 oversimplified the
information passed to the `doFunction` method.

Prior to that commit, `doFunction` was invoked inconsistently (with a
token and with an object literal). This was incorrectly simplified to a
boolean value, which caused the helper function `isMethod` to stop
working:

    function isMethod() {
      return funct["(statement)"] && funct["(statement)"].type === "class" ||
             funct["(context)"] && funct["(context)"]["(verb)"] === "class";
    }

Re-implement the option to be a token and specify consistently at each
invocation of `doFunction`.


Patch:
diff --git a/src/jshint.js b/src/jshint.js
index 050c3626..529d8cf0 100644
--- a/src/jshint.js
+++ b/src/jshint.js
@@ -2993,9 +2993,8 @@ var JSHINT = (function() {
    * @param {Object} [options]
    * @param {token} [options.name] The identifier belonging to the function (if
    *                               any)
-   * @param {boolean} [options.isStatement] Whether the function has been
-   *                                        declared as part of another
-   *                                        statement
+   * @param {boolean} [options.statement] The statement that triggered creation
+   *                                      of the current function.
    * @param {string} [options.type] If specified, either "generator" or "arrow"
    * @param {token} [options.loneArg] The argument to the function in cases
    *                                  where it was defined using the
@@ -3009,14 +3008,14 @@ var JSHINT = (function() {
    *                                           the body of member functions.
    */
   function doFunction(options) {
-    var f, name, isStatement, classExprBinding, isGenerator, isArrow;
+    var f, name, statement, classExprBinding, isGenerator, isArrow;
     var oldOption = state.option;
     var oldIgnored = state.ignored;
     var oldScope  = scope;
 
     if (options) {
       name = options.name;
-      isStatement = options.isStatement;
+      statement = options.statement;
       classExprBinding = options.classExprBinding;
       isGenerator = options.type === "generator";
       isArrow = options.type === "arrow";
@@ -3027,7 +3026,7 @@ var JSHINT = (function() {
     scope = Object.create(scope);
 
     funct = functor(name || state.nameStack.infer(), state.tokens.next, scope, {
-      "(statement)": isStatement,
+      "(statement)": statement,
       "(context)":   funct,
       "(generator)": isGenerator
     });
@@ -3694,7 +3693,7 @@ var JSHINT = (function() {
           advance();
         }
         if (state.tokens.next.value !== "(") {
-          doFunction({ isStatement: true });
+          doFunction({ statement: c });
         }
       }
 
@@ -3723,7 +3722,7 @@ var JSHINT = (function() {
       propertyName(name);
 
       doFunction({
-        isStatement: true,
+        statement: c,
         type: isGenerator ? "generator" : null,
         classExprBinding: c.namedExpr ? c.name : null
       });
@@ -3759,7 +3758,7 @@ var JSHINT = (function() {
 
     doFunction({
       name: i,
-      isStatement: true,
+      statement: this,
       type: generator ? "generator" : null
     });
     if (state.tokens.next.id === "(" && state.tokens.next.line === state.tokens.curr.line) {


Test patch:
diff --git a/tests/unit/parser.js b/tests/unit/parser.js
index d6d524d2..66e95975 100644
--- a/tests/unit/parser.js
+++ b/tests/unit/parser.js
@@ -4623,6 +4623,23 @@ exports.classExpression = function (test) {
   test.done();
 };
 
+exports.classExpressionThis = function (test) {
+  var code = [
+    "void class MyClass {",
+    "  constructor() { return this; }",
+    "  method() { return this; }",
+    "  static method() { return this; }",
+    "  get accessor() { return this; }",
+    "  set accessor() { return this; }",
+    "};"
+  ];
+
+  TestRun(test)
+    .test(code, { esnext: true });
+
+  test.done();
+};
+
 exports["test for GH-1018"] = function (test) {
   var code = [
     "if (a = 42) {}",