Repository: jsx-eslint/eslint-plugin-react (JavaScript)

Issue:
jsx-fragments: self closing <React.Fragment /> breaking eslint "Cannot read property 'range' of null"
Hi there, stumbled into linter-crashing bug.
Error caused when processing a self closing fragment: `<React.Fragment />` crashes eslint.

Without going into whether `<React.Fragment />` is really needed, it shouldn't break eslint and especially with no indication from the error that this was the cause, I had to search file by file to find it.

```
TypeError: Cannot read property 'range' of null
    at replaceNode (/node_modules/eslint-plugin-react/lib/rules/jsx-fragments.js:18:34)
    at Object.fix (/node_modules/eslint-plugin-react/lib/rules/jsx-fragments.js:74:18)
    at normalizeFixes (/node_modules/eslint/lib/report-translator.js:176:28)
    at args (/node_modules/eslint/lib/report-translator.js:278:18)
    at Object.report (/node_modules/eslint/lib/linter.js:830:41)
    at Program:exit.jsxElements.forEach.node (/node_modules/eslint-plugin-react/lib/rules/jsx-fragments.js:169:23)
    at Array.forEach (<anonymous>)
    at Program:exit (/node_modules/eslint-plugin-react/lib/rules/jsx-fragments.js:158:21)
    at listeners.(anonymous function).forEach.listener (/node_modules/eslint/lib/util/safe-emitter.js:45:58)
    at Array.forEach (<anonymous>)
error Command failed with exit code 2.
```


Discussion:
Change `<React.Fragment />` to `<></>` that will let you run the eslint task
Sorry about that, I’ll take a look.



Patch:
diff --git a/lib/rules/jsx-fragments.js b/lib/rules/jsx-fragments.js
index 6a68697f27..10060036e4 100644
--- a/lib/rules/jsx-fragments.js
+++ b/lib/rules/jsx-fragments.js
@@ -71,10 +71,18 @@ module.exports = {
     function getFixerToShort(jsxElement) {
       return function(fixer) {
         let source = sourceCode.getText();
-        source = replaceNode(source, jsxElement.closingElement, closeFragShort);
-        source = replaceNode(source, jsxElement.openingElement, openFragShort);
-        const lengthDiff = sourceCode.getText(jsxElement.openingElement).length - openFragShort.length
-          + sourceCode.getText(jsxElement.closingElement).length - closeFragShort.length;
+        let lengthDiff;
+        if (jsxElement.closingElement) {
+          source = replaceNode(source, jsxElement.closingElement, closeFragShort);
+          source = replaceNode(source, jsxElement.openingElement, openFragShort);
+          lengthDiff = sourceCode.getText(jsxElement.openingElement).length - openFragShort.length
+            + sourceCode.getText(jsxElement.closingElement).length - closeFragShort.length;
+        } else {
+          source = replaceNode(source, jsxElement.openingElement, `${openFragShort}${closeFragShort}`);
+          lengthDiff = sourceCode.getText(jsxElement.openingElement).length - openFragShort.length
+            - closeFragShort.length;
+        }
+
         const range = jsxElement.range;
         return fixer.replaceTextRange(range, source.slice(range[0], range[1] - lengthDiff));
       };


Test patch:
diff --git a/tests/lib/rules/jsx-fragments.js b/tests/lib/rules/jsx-fragments.js
index 640f029c7a..b0d06dd924 100644
--- a/tests/lib/rules/jsx-fragments.js
+++ b/tests/lib/rules/jsx-fragments.js
@@ -49,6 +49,10 @@ ruleTester.run('jsx-fragments', rule, {
     code: '<Act.Frag><Foo /></Act.Frag>',
     options: ['element'],
     settings
+  }, {
+    code: '<Act.Frag />',
+    options: ['element'],
+    settings
   }, {
     code: `
       import Act, { Frag as F } from 'react';
@@ -81,6 +85,10 @@ ruleTester.run('jsx-fragments', rule, {
     code: '<Act.Frag key="key"><Foo /></Act.Frag>',
     options: ['syntax'],
     settings
+  }, {
+    code: '<Act.Frag key="key" />',
+    options: ['syntax'],
+    settings
   }],
 
   invalid: [{
@@ -98,6 +106,13 @@ ruleTester.run('jsx-fragments', rule, {
       message: 'Fragments are only supported starting from React v16.2. '
         + 'Please disable the `react/jsx-fragments` rule in ESLint settings or upgrade your version of React.'
     }]
+  }, {
+    code: '<Act.Frag />',
+    settings: settingsOld,
+    errors: [{
+      message: 'Fragments are only supported starting from React v16.2. '
+        + 'Please disable the `react/jsx-fragments` rule in ESLint settings or upgrade your version of React.'
+    }]
   }, {
     code: '<><Foo /></>',
     parser: 'babel-eslint',
@@ -115,6 +130,28 @@ ruleTester.run('jsx-fragments', rule, {
       message: 'Prefer fragment shorthand over Act.Frag'
     }],
     output: '<><Foo /></>'
+  }, {
+    code: '<Act.Frag />',
+    options: ['syntax'],
+    settings,
+    errors: [{
+      message: 'Prefer fragment shorthand over Act.Frag'
+    }],
+    output: '<></>'
+  }, {
+    code: `
+      import Act, { Frag as F } from 'react';
+      <F />;
+    `,
+    options: ['syntax'],
+    settings,
+    errors: [{
+      message: 'Prefer fragment shorthand over Act.Frag'
+    }],
+    output: `
+      import Act, { Frag as F } from 'react';
+      <></>;
+    `
   }, {
     code: `
       import Act, { Frag as F } from 'react';