Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New] jsx-max-depth: validate a specific depth for JSX #1260

Merged
merged 1 commit into from Feb 19, 2018

Conversation

chriswong
Copy link
Contributor

Fixes #1219

Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also add test cases for nested inline JSX?

In other words, with a limit of 2, <div>{<div><div><span /></div></div>}</div> should still error on the inner piece - also, ideally, with a limit of 2, <div>{<div><span /></div>}</div> should also error because the total is 3, even tho it's never more than 2 in a chunk.

Similarly, const x = <div><span /><div>; <div>{x}</div> would be nice to fail also.


```js
...
"react/jsx-no-depth": [<enabled>, <number>]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's make an initial schema that's extensible; in other words, { "max": <number> } instead of just the number.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


var MESSAGE = 'JSX Element are nested too deeply ({{depth}}).';

var maxDepth = context.options[0] || 3;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in new code, let's use const/let over var

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


create: function(context) {

var MESSAGE = 'JSX Element are nested too deeply ({{depth}}).';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's also include the current max length in the message, like max-len does.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

var RuleTester = require('eslint').RuleTester;

var parserOptions = {
ecmaVersion: 8,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's set this to 6, since we shouldn't need ES2017 for this rule

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

ecmaVersion: 8,
sourceType: 'module',
ecmaFeatures: {
experimentalObjectRestSpread: true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similarly, this feature isn't required here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@chriswong chriswong force-pushed the max-depth branch 2 times, most recently from 0132b8a to 3f91f7a Compare June 21, 2017 14:16
Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is looking much better.

schema: [{
oneOf: [
{
type: 'integer',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to not even allow this as an option, if possible - meaning, to only have the object schema.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

function findJSXElement(variables, name) {
let find = function(refs) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const - or a function declaration

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Changed to function declaration.

let i = refs.length;

while (--i >= 0) {
if ('writeExpr' in refs[i]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use the has package rather than in, to avoid traversing the prototype chain.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


while (--i >= 0) {
if ('writeExpr' in refs[i]) {
let writeExpr = refs[i].writeExpr;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

let writeExpr = refs[i].writeExpr;

return isJSXElement(writeExpr)
&& writeExpr
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these chained lines should be indented one level further in

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

let element = findJSXElement(variables, node.expression.name);

if (element) {
let baseDepth = getDepth(node);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

function isLeaf(node) {
let children = node.children;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

const DEFAULT_DEPTH = 3;

let option = context.options[0] || DEFAULT_DEPTH;
let maxDepth = (typeof option === 'number' ? option : option.max) || DEFAULT_DEPTH;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const

Also, what happens if I pass a value of 0? This looks like it will always set 0 to 3. Please add some tests for values of 0 - ie, no nesting allowed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

          max: {
            type: 'integer',
            minimum: 1
          }

0 is no a valid value now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't zero a valid value? I'd think prohibiting nesting entirely is a totally valid option.

const MESSAGE = 'Expected the depth of JSX Elements nested should be {{needed}} but found {{gotten}}.';
const DEFAULT_DEPTH = 3;

let option = context.options[0] || DEFAULT_DEPTH;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}]
},
create: function(context) {
const MESSAGE = 'Expected the depth of JSX Elements nested should be {{needed}} but found {{gotten}}.';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"gotten" seems like an odd word choice; maybe "found"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

properties: {
max: {
type: 'integer',
minimum: 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this should be made to work with 0.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this rule is called "max-depth", I think it should detect the "depth" but not "nesting depth" of jsx, a depth of 0 means "no element here" which is absolutely useless

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that's true, then a max of 1 would permit <div /> but forbid <div><span /><div>; is that what the current PR's docs and test cases indicate?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifically, I want it to be configurable so I can forbid any nesting whatsoever - a depth of 0 means "flat", so in fact <div /> has a depth of zero.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OKey.

@jseminck
Copy link
Contributor

Is there anything stopping this rule from moving forward? This seems pretty useful to me! 😄

It probably needs a rebase though, at least one file has a conflict.

@ljharb
Copy link
Member

ljharb commented Aug 31, 2017

Happy to rereview after a rebase.

@jseminck
Copy link
Contributor

@chriswong any chance you could rebase this?

@forabi
Copy link

forabi commented Feb 4, 2018

@ljharb I rebased this on master. How should I submit the changes?

@ljharb
Copy link
Member

ljharb commented Feb 4, 2018

Certainly not with a duplicate PR, which I can never delete from my git history :-( Posting a link to the branch would be more than sufficient.

@ljharb
Copy link
Member

ljharb commented Feb 4, 2018

I've rebased this properly and pushed the changes up to here and to #1676.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

None yet

5 participants