Repository: yannickcr/eslint-plugin-react (js)

Issue:
JSX pragma matching too strict
The current JSX pragma detector will only detect pragmas included at the beginning of a docstring comment. However, pragmas can appear in regular block comments and at any position in them.

Additionally, the current requirement to use docstring comments causes issues with other eslint plugins that lint docstrings, as `@jsx` is not a valid JSDoc identifier.

The solution is to simply relax the regular expression that checks for this a bit.

Pull request description:
Relax JSX pragma regexp
Fixes #2642.

This PR relaxes the JSX pragma detection slightly.

Previously, only pragmas at the beginning of docstring comments were recognised. But pragmas can occur anywhere in any block comment (not just docstring comments). This PR fixes the regexp that recognises pragmas.

Patch:
diff --git a/lib/util/pragma.js b/lib/util/pragma.js
index d8affe9d..86d390df 100644
--- a/lib/util/pragma.js
+++ b/lib/util/pragma.js
@@ -5,7 +5,7 @@
 
 'use strict';
 
-const JSX_ANNOTATION_REGEX = /^\*\s*@jsx\s+([^\s]+)/;
+const JSX_ANNOTATION_REGEX = /@jsx\s+([^\s]+)/;
 // Does not check for reserved keywords or unicode characters
 const JS_IDENTIFIER_REGEX = /^[_$a-zA-Z][_$a-zA-Z0-9]*$/;
 
@@ -42,7 +42,7 @@ function getFromContext(context) {
   if (pragmaNode) {
     const matches = JSX_ANNOTATION_REGEX.exec(pragmaNode.value);
     pragma = matches[1].split('.')[0];
-  // .eslintrc shared settings (http://eslint.org/docs/user-guide/configuring#adding-shared-settings)
+    // .eslintrc shared settings (http://eslint.org/docs/user-guide/configuring#adding-shared-settings)
   } else if (context.settings.react && context.settings.react.pragma) {
     pragma = context.settings.react.pragma;
   }
diff --git a/package.json b/package.json
index c7ab0d72..1a6a0af7 100644
--- a/package.json
+++ b/package.json
@@ -51,6 +51,7 @@
     "eslint-config-airbnb-base": "^14.2.0",
     "eslint-plugin-eslint-plugin": "^2.2.2",
     "eslint-plugin-import": "^2.21.2",
+    "espree": "^3.5.4",
     "istanbul": "^0.4.5",
     "markdown-magic": "^1.0.0",
     "mocha": "^5.2.0",


Test patch:
diff --git a/tests/util/pragma.js b/tests/util/pragma.js
new file mode 100644
index 00000000..1898f68c
--- /dev/null
+++ b/tests/util/pragma.js
@@ -0,0 +1,64 @@
+'use strict';
+
+const assert = require('assert');
+const SourceCode = require('eslint').SourceCode;
+const espree = require('espree');
+
+const getFromContext = require('../../lib/util/pragma').getFromContext;
+
+const DEFAULT_CONFIG = {
+  ecmaVersion: 6,
+  comment: true,
+  tokens: true,
+  range: true,
+  loc: true
+};
+
+const DEFAULT_SETTINGS = {
+  react: {
+    pragma: 'React'
+  }
+};
+
+const fakeContext = (code) => {
+  const ast = espree.parse(code, DEFAULT_CONFIG);
+  return {
+    getSourceCode: () => new SourceCode(code, ast),
+    settings: DEFAULT_SETTINGS
+  };
+};
+
+describe('pragma', () => {
+  describe('getFromContext', () => {
+    it('finds the pragma in a block comment', () => {
+      const code = '/* @jsx jsx */';
+      assert.strictEqual(getFromContext(fakeContext(code)), 'jsx');
+    });
+
+    it('finds the pragma in a docstring comment', () => {
+      const code = '/** @jsx jsx */';
+      assert.strictEqual(getFromContext(fakeContext(code)), 'jsx');
+    });
+
+    it('finds the pragma in a line comment', () => {
+      const code = '// @jsx jsx';
+      assert.strictEqual(
+        getFromContext(fakeContext(code)),
+        'jsx'
+      );
+    });
+
+    it('defaults to the value of settings.react.pragma', () => {
+      const code = '';
+      assert.strictEqual(
+        getFromContext(fakeContext(code)),
+        DEFAULT_SETTINGS.react.pragma
+      );
+    });
+
+    it('throws an error if the pragma is invalid', () => {
+      const code = '/* @jsx invalid-jsx-pragma */';
+      assert.throws(() => getFromContext(fakeContext(code)));
+    });
+  });
+});