eslint-plugin-react
Advanced tools
Comparing version 7.25.1 to 7.25.2
@@ -52,3 +52,3 @@ /** | ||
const linkIndex = findLastIndex(node.attributes, (attr) => attr.name && attr.name.name === linkAttribute); | ||
const foundExternalLink = linkIndex !== -1 && ((attr) => attr.value.type === 'Literal' && /^(?:\w+:|\/\/)/.test(attr.value.value))( | ||
const foundExternalLink = linkIndex !== -1 && ((attr) => attr.value && attr.value.type === 'Literal' && /^(?:\w+:|\/\/)/.test(attr.value.value))( | ||
node.attributes[linkIndex]); | ||
@@ -55,0 +55,0 @@ return foundExternalLink || (warnOnSpreadAttributes && linkIndex < spreadAttributeIndex); |
@@ -80,6 +80,2 @@ /** | ||
function isFragmentWithSingleExpression(node) { | ||
return node && node.children.length === 1 && node.children[0].type === 'JSXExpressionContainer'; | ||
} | ||
module.exports = { | ||
@@ -119,2 +115,11 @@ meta: { | ||
function isFragmentWithSingleExpression(node) { | ||
const children = node && node.children.filter((child) => !isPaddingSpaces(child)); | ||
return ( | ||
children | ||
&& children.length === 1 | ||
&& children[0].type === 'JSXExpressionContainer' | ||
); | ||
} | ||
/** | ||
@@ -121,0 +126,0 @@ * Test whether a JSXElement has less than two children, excluding paddings spaces. |
@@ -14,2 +14,5 @@ /** | ||
const isTagNameRe = /^[a-z]/; | ||
const isTagName = (name) => isTagNameRe.test(name); | ||
module.exports = { | ||
@@ -37,2 +40,6 @@ meta: { | ||
name = node.name.name; | ||
// Exclude lowercase tag names like <div> | ||
if (isTagName(name)) { | ||
return; | ||
} | ||
} else if (node.name.object) { | ||
@@ -39,0 +46,0 @@ // <Foo...Bar> |
@@ -54,3 +54,3 @@ /** | ||
if (!isFlowPropertyType(prop.node)) { | ||
if (!prop.node || !isFlowPropertyType(prop.node)) { | ||
return; | ||
@@ -57,0 +57,0 @@ } |
@@ -63,2 +63,5 @@ /** | ||
const prop = propTypes[propName]; | ||
if (!prop.node) { | ||
return; | ||
} | ||
if (prop.isRequired) { | ||
@@ -65,0 +68,0 @@ if (forbidDefaultForRequired && defaultProps[propName]) { |
@@ -133,2 +133,3 @@ /** | ||
} | ||
this.skip(); | ||
break; | ||
@@ -135,0 +136,0 @@ case 'Literal': |
@@ -103,3 +103,3 @@ /** | ||
const customValidators = configuration.customValidators; | ||
const allowedGenericTypes = new Set(['SFC', 'StatelessComponent', 'FunctionComponent', 'FC']); | ||
const allowedGenericTypes = new Set(['PropsWithChildren', 'SFC', 'StatelessComponent', 'FunctionComponent', 'FC']); | ||
const genericReactTypesImport = new Set(); | ||
@@ -500,2 +500,32 @@ | ||
function isValidReactGenericTypeAnnotation(annotation) { | ||
if (annotation.typeName) { | ||
if (annotation.typeName.name) { // if FC<Props> | ||
const typeName = annotation.typeName.name; | ||
if (!genericReactTypesImport.has(typeName)) { | ||
return false; | ||
} | ||
} else if (annotation.typeName.right.name) { // if React.FC<Props> | ||
const right = annotation.typeName.right.name; | ||
const left = annotation.typeName.left.name; | ||
if (!genericReactTypesImport.has(left) || !allowedGenericTypes.has(right)) { | ||
return false; | ||
} | ||
} | ||
} | ||
return true; | ||
} | ||
/** | ||
* Returns the left most typeName of a node, e.g: FC<Props>, React.FC<Props> | ||
* The representation is used to verify nested used properties. | ||
* @param {ASTNode} node | ||
* @return {string | undefined} | ||
*/ | ||
function getTypeName(node) { | ||
if (node.name) return node.name; | ||
if (node.left) return getTypeName(node.left); | ||
} | ||
class DeclarePropTypesForTSTypeAnnotation { | ||
@@ -554,4 +584,9 @@ constructor(propTypes, declaredPropTypes) { | ||
typeName = node.typeName.name; | ||
const shouldTraverseTypeParams = !typeName || genericReactTypesImport.has(typeName); | ||
const shouldTraverseTypeParams = genericReactTypesImport.has(getTypeName(node.typeName)); | ||
if (shouldTraverseTypeParams && node.typeParameters && node.typeParameters.length !== 0) { | ||
// All react Generic types are derived from: | ||
// type PropsWithChildren<P> = P & { children?: ReactNode | undefined } | ||
// So we should construct an optional children prop | ||
this.shouldSpecifyOptionalChildrenProps = true; | ||
const nextNode = node.typeParameters.params[0]; | ||
@@ -731,2 +766,9 @@ this.visitTSNode(nextNode); | ||
endAndStructDeclaredPropTypes() { | ||
if (this.shouldSpecifyOptionalChildrenProps) { | ||
this.declaredPropTypes.children = { | ||
fullName: 'children', | ||
name: 'children', | ||
isRequired: false | ||
}; | ||
} | ||
this.foundDeclaredPropertiesList.forEach((tsInterfaceBody) => { | ||
@@ -935,2 +977,12 @@ if (tsInterfaceBody && (tsInterfaceBody.type === 'TSPropertySignature' || tsInterfaceBody.type === 'TSMethodSignature')) { | ||
} else { | ||
// check if its a valid generic type when `X<{...}>` | ||
if ( | ||
param.typeAnnotation | ||
&& param.typeAnnotation.typeAnnotation | ||
&& param.typeAnnotation.typeAnnotation.type === 'TSTypeReference' | ||
&& param.typeAnnotation.typeAnnotation.typeParameters != null | ||
&& !isValidReactGenericTypeAnnotation(param.typeAnnotation.typeAnnotation) | ||
) { | ||
return; | ||
} | ||
markPropTypesAsDeclared(node, resolveTypeAnnotation(param)); | ||
@@ -950,17 +1002,4 @@ } | ||
if (annotation.typeName) { | ||
if (annotation.typeName.name) { // if FC<Props> | ||
const typeName = annotation.typeName.name; | ||
if (!genericReactTypesImport.has(typeName)) { | ||
return; | ||
} | ||
} else if (annotation.typeName.right.name) { // if React.FC<Props> | ||
const right = annotation.typeName.right.name; | ||
const left = annotation.typeName.left.name; | ||
if (!isValidReactGenericTypeAnnotation(annotation)) return; | ||
if (!genericReactTypesImport.has(left) || !allowedGenericTypes.has(right)) { | ||
return; | ||
} | ||
} | ||
} | ||
markPropTypesAsDeclared(node, resolveTypeAnnotation(siblingIdentifier)); | ||
@@ -967,0 +1006,0 @@ } |
@@ -457,3 +457,3 @@ /** | ||
if (node.value && astUtil.isFunctionLikeExpression(node.value)) { | ||
if (node && node.value && astUtil.isFunctionLikeExpression(node.value)) { | ||
markPropTypesAsUsed(node.value); | ||
@@ -460,0 +460,0 @@ } |
{ | ||
"name": "eslint-plugin-react", | ||
"version": "7.25.1", | ||
"version": "7.25.2", | ||
"author": "Yannick Croissant <yannick.croissant+npm@gmail.com>", | ||
@@ -57,3 +57,3 @@ "description": "React specific linting rules for ESLint", | ||
"eslint-remote-tester": "^1.3.0", | ||
"eslint-remote-tester-repositories": "^0.0.2", | ||
"eslint-remote-tester-repositories": "^0.0.3", | ||
"espree": "^3.5.4", | ||
@@ -60,0 +60,0 @@ "istanbul": "^0.4.5", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
633642
17711