diff --git a/README.md b/README.md
index 4d30bd8033..3a06ef705d 100644
--- a/README.md
+++ b/README.md
@@ -194,6 +194,7 @@ Enable the rules that you would like to use.
## Other useful plugins
+- Rules of Hooks: [eslint-plugin-react-hooks](https://github.com/facebook/react/tree/master/packages/eslint-plugin-react-hooks)
- JSX accessibility: [eslint-plugin-jsx-a11y](https://github.com/evcohen/eslint-plugin-jsx-a11y)
- React Native: [eslint-plugin-react-native](https://github.com/Intellicode/eslint-plugin-react-native)
diff --git a/lib/rules/jsx-curly-spacing.js b/lib/rules/jsx-curly-spacing.js
index a53f24a740..b587d2fe52 100644
--- a/lib/rules/jsx-curly-spacing.js
+++ b/lib/rules/jsx-curly-spacing.js
@@ -244,7 +244,7 @@ module.exports = {
// Take comments into consideration to narrow the fix range to what is actually affected. (See #1414)
if (nextComment.length > 0) {
- return fixByTrimmingWhitespace(fixer, token.range[1], Math.min(nextToken.range[0], nextComment[0].start), 'start');
+ return fixByTrimmingWhitespace(fixer, token.range[1], Math.min(nextToken.range[0], nextComment[0].range[0]), 'start');
}
return fixByTrimmingWhitespace(fixer, token.range[1], nextToken.range[0], 'start');
@@ -279,7 +279,7 @@ module.exports = {
// Take comments into consideration to narrow the fix range to what is actually affected. (See #1414)
if (previousComment.length > 0) {
- return fixByTrimmingWhitespace(fixer, Math.max(previousToken.range[1], previousComment[0].end), token.range[0], 'end');
+ return fixByTrimmingWhitespace(fixer, Math.max(previousToken.range[1], previousComment[0].range[1]), token.range[0], 'end');
}
return fixByTrimmingWhitespace(fixer, previousToken.range[1], token.range[0], 'end');
diff --git a/lib/rules/jsx-no-bind.js b/lib/rules/jsx-no-bind.js
index 612f492cea..35f1c8a2d3 100644
--- a/lib/rules/jsx-no-bind.js
+++ b/lib/rules/jsx-no-bind.js
@@ -132,13 +132,13 @@ module.exports = {
function findVariableViolation(node, name) {
getBlockStatementAncestors(node).find(
- block => reportVariableViolation(node, name, block.start)
+ block => reportVariableViolation(node, name, block.range[0])
);
}
return {
BlockStatement(node) {
- setBlockVariableNameSet(node.start);
+ setBlockVariableNameSet(node.range[0]);
},
VariableDeclarator(node) {
@@ -154,7 +154,7 @@ module.exports = {
node.parent.kind === 'const' // only support const right now
) {
addVariableNameToSet(
- variableViolationType, node.id.name, blockAncestors[0].start
+ variableViolationType, node.id.name, blockAncestors[0].range[0]
);
}
},
diff --git a/lib/rules/jsx-pascal-case.js b/lib/rules/jsx-pascal-case.js
index 13f65eaa10..c8be42538e 100644
--- a/lib/rules/jsx-pascal-case.js
+++ b/lib/rules/jsx-pascal-case.js
@@ -93,22 +93,24 @@ module.exports = {
return {
JSXOpeningElement(node) {
+ const isCompatTag = jsxUtil.isDOMComponent(node);
+ if (isCompatTag) return undefined;
+
let name = elementType(node);
if (name.length === 1) return undefined;
- // Get namespace if the type is JSXNamespacedName or JSXMemberExpression
- if (name.indexOf(':') > -1) {
- name = name.substring(0, name.indexOf(':'));
- } else if (name.indexOf('.') > -1) {
- name = name.substring(0, name.indexOf('.'));
+ // Get JSXIdentifier if the type is JSXNamespacedName or JSXMemberExpression
+ if (name.lastIndexOf(':') > -1) {
+ name = name.substring(name.lastIndexOf(':') + 1);
+ } else if (name.lastIndexOf('.') > -1) {
+ name = name.substring(name.lastIndexOf('.') + 1);
}
const isPascalCase = testPascalCase(name);
- const isCompatTag = jsxUtil.isDOMComponent(node);
const isAllowedAllCaps = allowAllCaps && testAllCaps(name);
const isIgnored = ignore.indexOf(name) !== -1;
- if (!isPascalCase && !isCompatTag && !isAllowedAllCaps && !isIgnored) {
+ if (!isPascalCase && !isAllowedAllCaps && !isIgnored) {
let message = `Imported JSX component ${name} must be in PascalCase`;
if (allowAllCaps) {
diff --git a/lib/util/jsx.js b/lib/util/jsx.js
index e3bcc23e3a..f41c3b42fe 100644
--- a/lib/util/jsx.js
+++ b/lib/util/jsx.js
@@ -6,23 +6,17 @@
const elementType = require('jsx-ast-utils/elementType');
-const COMPAT_TAG_REGEX = /^[a-z]|-/;
+// See https://github.com/babel/babel/blob/ce420ba51c68591e057696ef43e028f41c6e04cd/packages/babel-types/src/validators/react/isCompatTag.js
+// for why we only test for the first character
+const COMPAT_TAG_REGEX = /^[a-z]/;
/**
- * Checks if a node represents a DOM element.
+ * Checks if a node represents a DOM element according to React.
* @param {object} node - JSXOpeningElement to check.
* @returns {boolean} Whether or not the node corresponds to a DOM element.
*/
function isDOMComponent(node) {
- let name = elementType(node);
-
- // Get namespace if the type is JSXNamespacedName or JSXMemberExpression
- if (name.indexOf(':') > -1) {
- name = name.slice(0, name.indexOf(':'));
- } else if (name.indexOf('.') > -1) {
- name = name.slice(0, name.indexOf('.'));
- }
-
+ const name = elementType(node);
return COMPAT_TAG_REGEX.test(name);
}
diff --git a/lib/util/usedPropTypes.js b/lib/util/usedPropTypes.js
index f1ac14622c..ab0c188f32 100755
--- a/lib/util/usedPropTypes.js
+++ b/lib/util/usedPropTypes.js
@@ -170,7 +170,7 @@ function isPropArgumentInSetStateUpdater(context, name) {
unwrappedParentCalleeNode.property &&
unwrappedParentCalleeNode.property.name === 'setState' &&
// Make sure we are in the updater not the callback
- scope.block.parent.arguments[0].start === scope.block.start &&
+ scope.block.parent.arguments[0].range[0] === scope.block.range[0] &&
scope.block.parent.arguments[0].params &&
scope.block.parent.arguments[0].params.length > 1
) {
diff --git a/tests/lib/rules/jsx-pascal-case.js b/tests/lib/rules/jsx-pascal-case.js
index 8428783818..af9d914d55 100644
--- a/tests/lib/rules/jsx-pascal-case.js
+++ b/tests/lib/rules/jsx-pascal-case.js
@@ -29,6 +29,10 @@ const parserOptions = {
const ruleTester = new RuleTester({parserOptions});
ruleTester.run('jsx-pascal-case', rule, {
valid: [{
+ // The rule must not warn on components that start with a lowercase
+ // because they are interpreted as HTML elements by React
+ code: ''
+ }, {
code: ''
}, {
code: ''
@@ -52,6 +56,8 @@ ruleTester.run('jsx-pascal-case', rule, {
code: ''
}, {
code: ''
+ }, {
+ code: ''
}, {
code: '',
parser: parsers.BABEL_ESLINT