Skip to content

Commit

Permalink
[New] Change allowed propWrapperFunctions setting values
Browse files Browse the repository at this point in the history
This change is adapting the `propWrapperFunctions` setting to allow for
using objects along side the already present strings. This will help
facilitate adding extra attributes to these objects like for exact prop
functions.

Precursor to jsx-eslint#1547.
  • Loading branch information
jomasti authored and ljharb committed Dec 2, 2018
1 parent 5877629 commit a33bfb1
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 17 deletions.
10 changes: 6 additions & 4 deletions README.md
Expand Up @@ -42,10 +42,12 @@ You should also specify settings that will be shared across all the plugin rules
"version": "15.0", // React version, default to the latest React stable release
"flowVersion": "0.53" // Flow version
},
"propWrapperFunctions": [ "forbidExtraProps" ] // The names of any functions used to wrap the
// propTypes object, e.g. `forbidExtraProps`.
// If this isn't set, any propTypes wrapped in
// a function will be skipped.
"propWrapperFunctions": [
// The names of any function used to wrap propTypes, e.g. `forbidExtraProps`. If this isn't set, any propTypes wrapped in a function will be skipped.
"forbidExtraProps",
{"property": "freeze", "object": "Object"}
{"property": "myFavoriteWrapper"}
]
}
}
```
Expand Down
6 changes: 3 additions & 3 deletions lib/rules/boolean-prop-naming.js
Expand Up @@ -7,6 +7,7 @@
const Components = require('../util/Components');
const propsUtil = require('../util/props');
const docsUrl = require('../util/docsUrl');
const propWrapperUtil = require('../util/propWrapper');

// ------------------------------------------------------------------------------
// Rule Definition
Expand Down Expand Up @@ -51,7 +52,6 @@ module.exports = {
const config = context.options[0] || {};
const rule = config.rule ? new RegExp(config.rule) : null;
const propTypeNames = config.propTypeNames || ['bool'];
const propWrapperFunctions = new Set(context.settings.propWrapperFunctions || []);

// Remembers all Flowtype object definitions
const objectTypeAnnotations = new Map();
Expand Down Expand Up @@ -171,7 +171,7 @@ module.exports = {
if (!rule || !propsUtil.isPropTypesDeclaration(node)) {
return;
}
if (node.value && node.value.type === 'CallExpression' && propWrapperFunctions.has(sourceCode.getText(node.value.callee))) {
if (node.value && node.value.type === 'CallExpression' && propWrapperUtil.isPropWrapperFunction(context, sourceCode.getText(node.value.callee))) {
checkPropWrapperArguments(node, node.value.arguments);
}
if (node.value && node.value.properties) {
Expand All @@ -191,7 +191,7 @@ module.exports = {
return;
}
const right = node.parent.right;
if (right.type === 'CallExpression' && propWrapperFunctions.has(sourceCode.getText(right.callee))) {
if (right.type === 'CallExpression' && propWrapperUtil.isPropWrapperFunction(context, sourceCode.getText(right.callee))) {
checkPropWrapperArguments(component.node, right.arguments);
return;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/rules/forbid-prop-types.js
Expand Up @@ -7,6 +7,7 @@ const variableUtil = require('../util/variable');
const propsUtil = require('../util/props');
const astUtil = require('../util/ast');
const docsUrl = require('../util/docsUrl');
const propWrapperUtil = require('../util/propWrapper');

// ------------------------------------------------------------------------------
// Constants
Expand Down Expand Up @@ -48,7 +49,6 @@ module.exports = {
},

create: function(context) {
const propWrapperFunctions = new Set(context.settings.propWrapperFunctions || []);
const configuration = context.options[0] || {};
const checkContextTypes = configuration.checkContextTypes || false;
const checkChildContextTypes = configuration.checkChildContextTypes || false;
Expand Down Expand Up @@ -125,7 +125,7 @@ module.exports = {
break;
case 'CallExpression':
const innerNode = node.arguments && node.arguments[0];
if (propWrapperFunctions.has(node.callee.name) && innerNode) {
if (propWrapperUtil.isPropWrapperFunction(context, node.callee.name) && innerNode) {
checkNode(innerNode);
}
break;
Expand Down
4 changes: 2 additions & 2 deletions lib/rules/jsx-sort-default-props.js
Expand Up @@ -6,6 +6,7 @@

const variableUtil = require('../util/variable');
const docsUrl = require('../util/docsUrl');
const propWrapperUtil = require('../util/propWrapper');

// ------------------------------------------------------------------------------
// Rule Definition
Expand Down Expand Up @@ -35,7 +36,6 @@ module.exports = {
const sourceCode = context.getSourceCode();
const configuration = context.options[0] || {};
const ignoreCase = configuration.ignoreCase || false;
const propWrapperFunctions = new Set(context.settings.propWrapperFunctions || []);

/**
* Get properties name
Expand Down Expand Up @@ -134,7 +134,7 @@ module.exports = {
break;
case 'CallExpression':
const innerNode = node.arguments && node.arguments[0];
if (propWrapperFunctions.has(node.callee.name) && innerNode) {
if (propWrapperUtil.isPropWrapperFunction(context, node.callee.name) && innerNode) {
checkNode(innerNode);
}
break;
Expand Down
4 changes: 2 additions & 2 deletions lib/rules/sort-prop-types.js
Expand Up @@ -6,6 +6,7 @@
const variableUtil = require('../util/variable');
const propsUtil = require('../util/props');
const docsUrl = require('../util/docsUrl');
const propWrapperUtil = require('../util/propWrapper');

// ------------------------------------------------------------------------------
// Rule Definition
Expand Down Expand Up @@ -54,7 +55,6 @@ module.exports = {
const ignoreCase = configuration.ignoreCase || false;
const noSortAlphabetically = configuration.noSortAlphabetically || false;
const sortShapeProp = configuration.sortShapeProp || false;
const propWrapperFunctions = new Set(context.settings.propWrapperFunctions || []);

function getKey(node) {
if (node.key && node.key.value) {
Expand Down Expand Up @@ -250,7 +250,7 @@ module.exports = {
break;
case 'CallExpression':
const innerNode = node.arguments && node.arguments[0];
if (propWrapperFunctions.has(node.callee.name) && innerNode) {
if (propWrapperUtil.isPropWrapperFunction(context, node.callee.name) && innerNode) {
checkNode(innerNode);
}
break;
Expand Down
4 changes: 2 additions & 2 deletions lib/util/defaultProps.js
Expand Up @@ -7,12 +7,12 @@ const fromEntries = require('object.fromentries');
const astUtil = require('./ast');
const propsUtil = require('./props');
const variableUtil = require('./variable');
const propWrapperUtil = require('../util/propWrapper');

const QUOTES_REGEX = /^["']|["']$/g;

module.exports = function defaultPropsInstructions(context, components, utils) {
const sourceCode = context.getSourceCode();
const propWrapperFunctions = new Set(context.settings.propWrapperFunctions || []);

/**
* Try to resolve the node passed in to a variable in the current scope. If the node passed in is not
Expand All @@ -26,7 +26,7 @@ module.exports = function defaultPropsInstructions(context, components, utils) {
}
if (
node.type === 'CallExpression' &&
propWrapperFunctions.has(node.callee.name) &&
propWrapperUtil.isPropWrapperFunction(context, node.callee.name) &&
node.arguments && node.arguments[0]
) {
return resolveNodeValue(node.arguments[0]);
Expand Down
4 changes: 2 additions & 2 deletions lib/util/propTypes.js
Expand Up @@ -7,6 +7,7 @@ const annotations = require('./annotations');
const propsUtil = require('./props');
const variableUtil = require('./variable');
const versionUtil = require('./version');
const propWrapperUtil = require('../util/propWrapper');

/**
* Checks if we are declaring a props as a generic type in a flow-annotated class.
Expand Down Expand Up @@ -76,7 +77,6 @@ module.exports = function propTypesInstructions(context, components, utils) {
const configuration = Object.assign({}, defaults, context.options[0] || {});
const customValidators = configuration.customValidators;
const sourceCode = context.getSourceCode();
const propWrapperFunctions = new Set(context.settings.propWrapperFunctions);

/**
* Returns the full scope.
Expand Down Expand Up @@ -522,7 +522,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
break;
case 'CallExpression':
if (
propWrapperFunctions.has(sourceCode.getText(propTypes.callee)) &&
propWrapperUtil.isPropWrapperFunction(context, sourceCode.getText(propTypes.callee)) &&
propTypes.arguments && propTypes.arguments[0]
) {
markPropTypesAsDeclared(node, propTypes.arguments[0]);
Expand Down
24 changes: 24 additions & 0 deletions lib/util/propWrapper.js
@@ -0,0 +1,24 @@
/**
* @fileoverview Utility functions for propWrapperFunctions setting
*/
'use strict';

function getPropWrapperFunctions(context) {
return new Set(context.settings.propWrapperFunctions || []);
}

function isPropWrapperFunction(context, name) {
const propWrapperFunctions = getPropWrapperFunctions(context);
const splitName = name.split('.');
return Array.from(propWrapperFunctions).some(func => {
if (splitName.length === 2 && func.object === splitName[0] && func.property === splitName[1]) {
return true;
}
return name === func || func.property === name;
});
}

module.exports = {
getPropWrapperFunctions: getPropWrapperFunctions,
isPropWrapperFunction: isPropWrapperFunction
};
62 changes: 62 additions & 0 deletions tests/util/propWrapper.js
@@ -0,0 +1,62 @@
/* eslint-env mocha */
'use strict';

const assert = require('assert');
const propWrapperUtil = require('../../lib/util/propWrapper');

describe('PropWrapperFunctions', () => {
describe('getPropWrapperFunctions', () => {
it('returns set of functions if setting exists', () => {
const propWrapperFunctions = ['Object.freeze', {
property: 'forbidExtraProps'
}];
const context = {
settings: {
propWrapperFunctions: propWrapperFunctions
}
};
assert.deepStrictEqual(propWrapperUtil.getPropWrapperFunctions(context), new Set(propWrapperFunctions));
});

it('returns empty array if no setting', () => {
const context = {
settings: {}
};
assert.deepStrictEqual(propWrapperUtil.getPropWrapperFunctions(context), new Set([]));
});
});

describe('isPropWrapperFunction', () => {
it('with string', () => {
const context = {
settings: {
propWrapperFunctions: ['Object.freeze']
}
};
assert.equal(propWrapperUtil.isPropWrapperFunction(context, 'Object.freeze'), true);
});

it('with Object with object and property keys', () => {
const context = {
settings: {
propWrapperFunctions: [{
property: 'freeze',
object: 'Object'
}]
}
};
assert.equal(propWrapperUtil.isPropWrapperFunction(context, 'Object.freeze'), true);
});

it('with Object with only property key', () => {
const context = {
settings: {
propWrapperFunctions: [{
property: 'forbidExtraProps'
}]
}
};
assert.equal(propWrapperUtil.isPropWrapperFunction(context, 'forbidExtraProps'), true);
});
});
});

0 comments on commit a33bfb1

Please sign in to comment.