Skip to content

Commit

Permalink
Add skipUndeclared option to prop-types rule
Browse files Browse the repository at this point in the history
  • Loading branch information
pfhayes authored and yannickcr committed Oct 1, 2016
1 parent cc39fb8 commit b464cf1
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/rules/prop-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ This rule can take one argument to ignore some specific props during validation.
* `enabled`: for enabling the rule. 0=off, 1=warn, 2=error. Defaults to 0.
* `ignore`: optional array of props name to ignore during validation.
* `customValidators`: optional array of validators used for propTypes validation.
* `skipUndeclared`: only error on components that have a propTypes block declared

### As for "exceptions"

Expand Down
9 changes: 7 additions & 2 deletions lib/rules/prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ module.exports = {
items: {
type: 'string'
}
},
skipUndeclared: {
type: 'boolean'
}
},
additionalProperties: false
Expand All @@ -54,6 +57,7 @@ module.exports = {
var configuration = context.options[0] || {};
var ignored = configuration.ignore || [];
var customValidators = configuration.customValidators || [];
var skipUndeclared = configuration.skipUndeclared || false;
// Used to track the type annotations in scope.
// Necessary because babel's scopes do not track type annotations.
var stack = null;
Expand Down Expand Up @@ -134,7 +138,6 @@ module.exports = {
* @returns {Boolean} True if we are declaring a prop, false if not.
*/
function isPropTypesDeclaration(node) {

// Special case for class properties
// (babel-eslint does not expose property name so we have to rely on tokens)
if (node && node.type === 'ClassProperty') {
Expand Down Expand Up @@ -179,10 +182,12 @@ module.exports = {
* @returns {Boolean} True if the component must be validated, false if not.
*/
function mustBeValidated(component) {
var isSkippedByConfig = skipUndeclared && typeof component.declaredPropTypes === 'undefined';
return Boolean(
component &&
component.usedPropTypes &&
!component.ignorePropsValidation
!component.ignorePropsValidation &&
!isSkippedByConfig
);
}

Expand Down
135 changes: 135 additions & 0 deletions tests/lib/rules/prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,62 @@ ruleTester.run('prop-types', rule, {
'}'
].join('\n'),
parser: 'babel-eslint'
}, {
code: [
'var Hello = React.createClass({',
' render: function() {',
' return <div>{this.props.name}</div>;',
' }',
'});'
].join('\n'),
options: [{skipUndeclared: true}],
parserOptions: parserOptions
}, {
code: [
'var Hello = React.createClass({',
' render: function() {',
' return <div>{this.props.name}</div>;',
' }',
'});'
].join('\n'),
options: [{skipUndeclared: true}],
parserOptions: parserOptions
}, {
code: [
'class Hello extends React.Component {',
' render() {',
' return <div>{this.props.name}</div>;',
' }',
'}'
].join('\n'),
options: [{skipUndeclared: true}],
parserOptions: parserOptions
}, {
code: [
'var Hello = React.createClass({',
' propTypes: {',
' name: React.PropTypes.object.isRequired',
' },',
' render: function() {',
' return <div>{this.props.name}</div>;',
' }',
'});'
].join('\n'),
options: [{skipUndeclared: true}],
parserOptions: parserOptions
}, {
code: [
'var Hello = React.createClass({',
' propTypes: {',
' name: React.PropTypes.object.isRequired',
' },',
' render: function() {',
' return <div>{this.props.name}</div>;',
' }',
'});'
].join('\n'),
options: [{skipUndeclared: false}],
parserOptions: parserOptions
}
],

Expand Down Expand Up @@ -2312,6 +2368,85 @@ ruleTester.run('prop-types', rule, {
column: 27,
type: 'Property'
}]
}, {
code: [
'var Hello = React.createClass({',
' propTypes: {},',
' render: function() {',
' return <div>{this.props.firstname}</div>;',
' }',
'});'
].join('\n'),
options: [{skipUndeclared: true}],
parserOptions: parserOptions,
errors: [{
message: '\'firstname\' is missing in props validation',
line: 4,
column: 29
}]
}, {
code: [
'var Hello = function(props) {',
' return <div>{props.firstname}</div>;',
'};',
'Hello.propTypes = {}'
].join('\n'),
options: [{skipUndeclared: true}],
parserOptions: parserOptions,
errors: [{
message: '\'firstname\' is missing in props validation',
line: 2,
column: 22
}]
}, {
code: [
'class Hello extends React.Component {',
' static get propTypes() {',
' return {};',
' }',
' render() {',
' return <div>{this.props.firstname}</div>;',
' }',
'}'
].join('\n'),
options: [{skipUndeclared: true}],
parserOptions: parserOptions,
errors: [{
message: '\'firstname\' is missing in props validation',
line: 6,
column: 29
}]
}, {
code: [
'class Hello extends React.Component {',
' render() {',
' return <div>{this.props.firstname}</div>;',
' }',
'}',
'Hello.propTypes = {};'
].join('\n'),
options: [{skipUndeclared: true}],
parserOptions: parserOptions,
errors: [{
message: '\'firstname\' is missing in props validation',
line: 3,
column: 29
}]
}, {
code: [
'var Hello = React.createClass({',
' render: function() {',
' return <div>{this.props.firstname}</div>;',
' }',
'});'
].join('\n'),
options: [{skipUndeclared: false}],
parserOptions: parserOptions,
errors: [{
message: '\'firstname\' is missing in props validation',
line: 3,
column: 29
}]
}
]
});

0 comments on commit b464cf1

Please sign in to comment.