Skip to content

Commit

Permalink
Merge branch 'yannickcr:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
ngtan committed Sep 19, 2021
2 parents 425860f + 227e967 commit 8e5bbfb
Show file tree
Hide file tree
Showing 36 changed files with 802 additions and 94 deletions.
14 changes: 13 additions & 1 deletion .github/workflows/node-4+.yml
Expand Up @@ -30,7 +30,19 @@ jobs:
- 6
- 5
- 4
babel-eslint:
- 10
- 9
- 8
exclude:
- node-version: 5
babel-eslint: 10
- node-version: 5
babel-eslint: 9
- node-version: 4
babel-eslint: 10
- node-version: 4
babel-eslint: 9
- node-version: 9
eslint: 7
- node-version: 8
Expand Down Expand Up @@ -62,7 +74,7 @@ jobs:
name: 'nvm install ${{ matrix.node-version }} && npm install'
with:
node-version: ${{ matrix.node-version }}
after_install: npm install --no-save "eslint@${{ matrix.eslint }}" "@typescript-eslint/parser@${{ matrix.node-version >= 10 && '3' || '2' }}"
after_install: npm install --no-save "eslint@${{ matrix.eslint }}" "@typescript-eslint/parser@${{ matrix.node-version >= 10 && '4.0' || (matrix.node-version >= 8 && '3' || '2') }}" "babel-eslint@${{ matrix.babel-eslint }}"
skip-ls-check: true
env:
NPM_CONFIG_LEGACY_PEER_DEPS: true
Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/smoke-test.yml
Expand Up @@ -6,14 +6,11 @@ on:
workflow_dispatch:

jobs:
lint:
smoke-test:
if: ${{ github.repository == 'yannickcr/eslint-plugin-react' || github.event_name == 'workflow_dispatch' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 14
- uses: ljharb/actions/node/install@main
name: 'nvm install lts/* && npm install'
with:
Expand Down
48 changes: 47 additions & 1 deletion CHANGELOG.md
Expand Up @@ -5,12 +5,44 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel

## Unreleased

### Fixed
* [`prop-types`], `propTypes`: bail out unknown generic types inside func params ([#3076] @vedadeepta)

[#3076]: https://github.com/yannickcr/eslint-plugin-react/pull/3076

## [7.25.2] - 2021.09.16

### Fixed
* [`jsx-no-useless-fragments`]: Handle insignificant whitespace correctly when `allowExpressions` is `true` ([#3061][] @benj-dobs)
* [`prop-types`], `propTypes`: handle implicit `children` prop in react's generic types ([#3064][] @vedadeepta)
* [`display-name`]: fix arrow function returning result of function call with JSX arguments being interpreted as component ([#3065][] @danielfinke)
* [`jsx-no-target-blank`]: avoid crash on attr-only href ([#3066][] @ljharb @gaz77a)
* [`jsx-uses-vars`]: ignore lowercase tag names ([#3070][] @alanorozco)

[7.25.2]: https://github.com/yannickcr/eslint-plugin-react/compare/v7.25.1...v7.25.2
[#3070]: https://github.com/yannickcr/eslint-plugin-react/pull/3070
[#3066]: https://github.com/yannickcr/eslint-plugin-react/issue/3066
[#3065]: https://github.com/yannickcr/eslint-plugin-react/pull/3065
[#3064]: https://github.com/yannickcr/eslint-plugin-react/pull/3064
[#3061]: https://github.com/yannickcr/eslint-plugin-react/pull/3061

## [7.25.1] - 2021.08.29

### Fixed
* [`no-this-in-sfc`], component detection: Improve stateless component detection ([#3056][] @Wesitos)

[7.25.1]: https://github.com/yannickcr/eslint-plugin-react/compare/v7.25.0...v7.25.1
[#3056]: https://github.com/yannickcr/eslint-plugin-react/pull/3056

## [7.25.0] - 2021.08.27

### Added
* [`jsx-no-useless-fragments`]: add option to allow single expressions in fragments ([#3006][] @mattdarveniza)
* add [`prefer-exact-props`] rule ([#1547][] @jomasti)
* [`jsx-no-target-blank`]: add `forms` option ([#1617][] @jaaberg)
* [`jsx-pascal-case`]: add `allowLeadingUnderscore` option ([#3039][] @pangaeatech)
* [`no-children-prop`]: Add `allowFunctions` option ([#1903][] @alexzherdev)
* [`jsx-runtime`]: set `parserOptions.jsxPragma` for `@typescript-eslint/parser` ([bb64df65][] @ljharb)

### Fixed
* component detection: use `estraverse` to improve component detection ([#2992][] @Wesitos)
Expand All @@ -19,14 +51,28 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
* [`destructuring-assignment`]: get the contextName correctly ([#3025][] @ohhoney1)
* [`no-typos`]: prevent crash on styled components and forwardRefs ([#3036][] @ljharb)
* [`destructuring-assignment`], component detection: handle default exports edge case ([#3038][] @vedadeepta)
* [`no-typos`]: fix crash on private methods ([#3043][] @ljharb)
* [`jsx-no-bind`]: handle local function declarations ([#3048][] @p7g)
* [`prop-types`], `propTypes`: handle React.* TypeScript types ([#3049][] @vedadeepta)
* [`prop-types`], `propTypes`: add handling for `FC<Props>`, improve tests ([#3051][] @vedadeepta)
* [`prop-types`], `propTypes`: prevent crash introduced in [#3051][] ([#3053][] @ljharb)

### Changed
* [Docs] [`jsx-no-bind`]: updates discussion of refs ([#2998][] @dimitropoulos)
* [Refactor] `utils/Components`: correct spelling and delete unused code ([#3026][] @ohhoney1)
* [Docs] [`jsx-uses-react`], [`react-in-jsx-scope`]: document [`react/jsx-runtime`] config ([#3018][] @pkuczynski @ljharb)
* [Docs] [`require-default-props`]: fix small typo ([#2994][] @evsasse)
* [Tests] add weekly scheduled smoke tests ([#2963][] @AriPerkkio)

* [Docs] improve instructions for `jsx-runtime` config ([#3052][] @ljharb)

[7.25.0]: https://github.com/yannickcr/eslint-plugin-react/compare/v7.24.0...v7.25.0
[bb64df65]: https://github.com/yannickcr/eslint-plugin-react/commit/bb64df6505b3e9a01da5b61626ab9f544caea438
[#3053]: https://github.com/yannickcr/eslint-plugin-react/issues/3053
[#3052]: https://github.com/yannickcr/eslint-plugin-react/issues/3052
[#3051]: https://github.com/yannickcr/eslint-plugin-react/pull/3051
[#3049]: https://github.com/yannickcr/eslint-plugin-react/pull/3049
[#3048]: https://github.com/yannickcr/eslint-plugin-react/pull/3048
[#3043]: https://github.com/yannickcr/eslint-plugin-react/issues/3043
[#3039]: https://github.com/yannickcr/eslint-plugin-react/pull/3039
[#3038]: https://github.com/yannickcr/eslint-plugin-react/pull/3038
[#3036]: https://github.com/yannickcr/eslint-plugin-react/issues/3036
Expand Down
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -31,7 +31,7 @@ Use [our preset](#recommended) to get reasonable defaults:
]
```

If you are using the [new JSX transform from React 17](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html#removing-unused-react-imports), extend [`react/jsx-runtime`](https://github.com/yannickcr/eslint-plugin-react/blob/HEAD/index.js#L163-L176) in your eslint config to disable the relevant rules.
If you are using the [new JSX transform from React 17](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html#removing-unused-react-imports), extend [`react/jsx-runtime`](https://github.com/yannickcr/eslint-plugin-react/blob/HEAD/index.js#L163-L176) in your eslint config (add `"plugin:react/jsx-runtime"` to `"extends"`) to disable the relevant rules.

You should also specify settings that will be shared across all the plugin rules. ([More about eslint shared settings](https://eslint.org/docs/user-guide/configuring/configuration-files#adding-shared-settings))

Expand Down Expand Up @@ -241,7 +241,7 @@ To enable this configuration use the `extends` property in your `.eslintrc` conf
}
```

See [ESLint documentation](http://eslint.org/docs/user-guide/configuring#extending-configuration-files) for more information about extending configuration files.
See [ESLint documentation](https://eslint.org/docs/user-guide/configuring/configuration-files#extending-configuration-files) for more information about extending configuration files.

## All

Expand Down
9 changes: 9 additions & 0 deletions docs/rules/jsx-no-bind.md
Expand Up @@ -14,6 +14,10 @@ Examples of **incorrect** code for this rule:
```jsx
<Foo onClick={() => console.log('Hello!')}></Foo>
```
```jsx
function onClick() { console.log('Hello!'); }
<Foo onClick={onClick} />
```

Examples of **correct** code for this rule:
```jsx
Expand Down Expand Up @@ -76,6 +80,11 @@ Examples of **correct** code for this rule, when `allowFunctions` is `true`:
<Foo onClick={function () { alert("1337") }} />
```
```jsx
function onClick() { alert("1337"); }
<Foo onClick={onClick} />
```
### `allowBind`
Examples of **correct** code for this rule, when `allowBind` is `true`:
Expand Down
4 changes: 4 additions & 0 deletions docs/rules/jsx-no-useless-fragment.md
Expand Up @@ -64,4 +64,8 @@ Examples of **correct** code for the rule, when `"allowExpressions"` is `true`:

```jsx
<>{foo}</>

<>
{foo}
</>
```
2 changes: 1 addition & 1 deletion docs/rules/jsx-uses-react.md
Expand Up @@ -45,4 +45,4 @@ var Hello = <div>Hello {this.props.name}</div>;

If you are not using JSX, if React is declared as global variable, or if you do not use the `no-unused-vars` rule.

If you are using the [new JSX transform from React 17](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html#removing-unused-react-imports), you should disable this rule by extending [`react/jsx-runtime`](https://github.com/yannickcr/eslint-plugin-react/blob/HEAD/index.js#L163-L176) in your eslint config.
If you are using the [new JSX transform from React 17](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html#removing-unused-react-imports), you should disable this rule by extending [`react/jsx-runtime`](https://github.com/yannickcr/eslint-plugin-react/blob/HEAD/index.js#L163-L176) in your eslint config (add `"plugin:react/jsx-runtime"` to `"extends"`).
2 changes: 1 addition & 1 deletion docs/rules/react-in-jsx-scope.md
Expand Up @@ -44,4 +44,4 @@ var Hello = <div>Hello {this.props.name}</div>;

If you are not using JSX, or if you are setting `React` as a global variable.

If you are using the [new JSX transform from React 17](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html#removing-unused-react-imports), you should disable this rule by extending [`react/jsx-runtime`](https://github.com/yannickcr/eslint-plugin-react/blob/HEAD/index.js#L163-L176) in your eslint config.
If you are using the [new JSX transform from React 17](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html#removing-unused-react-imports), you should disable this rule by extending [`react/jsx-runtime`](https://github.com/yannickcr/eslint-plugin-react/blob/HEAD/index.js#L163-L176) in your eslint config (add `"plugin:react/jsx-runtime"` to `"extends"`).
3 changes: 2 additions & 1 deletion index.js
Expand Up @@ -169,7 +169,8 @@ module.exports = {
parserOptions: {
ecmaFeatures: {
jsx: true
}
},
jsxPragma: null // for @typescript/eslint-parser
},
rules: {
'react/react-in-jsx-scope': 0,
Expand Down
14 changes: 13 additions & 1 deletion lib/rules/jsx-no-bind.js
Expand Up @@ -96,7 +96,10 @@ module.exports = {
if (!configuration.allowArrowFunctions && nodeType === 'ArrowFunctionExpression') {
return 'arrowFunc';
}
if (!configuration.allowFunctions && nodeType === 'FunctionExpression') {
if (
!configuration.allowFunctions
&& (nodeType === 'FunctionExpression' || nodeType === 'FunctionDeclaration')
) {
return 'func';
}
if (!configuration.allowBind && nodeType === 'BindExpression') {
Expand Down Expand Up @@ -144,6 +147,15 @@ module.exports = {
setBlockVariableNameSet(node.range[0]);
},

FunctionDeclaration(node) {
const blockAncestors = getBlockStatementAncestors(node);
const variableViolationType = getNodeViolationType(node);

if (blockAncestors.length > 0 && variableViolationType) {
addVariableNameToSet(variableViolationType, node.id.name, blockAncestors[0].range[0]);
}
},

VariableDeclarator(node) {
if (!node.init) {
return;
Expand Down
2 changes: 1 addition & 1 deletion lib/rules/jsx-no-target-blank.js
Expand Up @@ -49,7 +49,7 @@ function attributeValuePossiblyBlank(attribute) {

function hasExternalLink(node, linkAttribute, warnOnSpreadAttributes, spreadAttributeIndex) {
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]);
return foundExternalLink || (warnOnSpreadAttributes && linkIndex < spreadAttributeIndex);
}
Expand Down
13 changes: 9 additions & 4 deletions lib/rules/jsx-no-useless-fragment.js
Expand Up @@ -77,10 +77,6 @@ function containsCallExpression(node) {
&& node.expression.type === 'CallExpression';
}

function isFragmentWithSingleExpression(node) {
return node && node.children.length === 1 && node.children[0].type === 'JSXExpressionContainer';
}

module.exports = {
meta: {
type: 'suggestion',
Expand Down Expand Up @@ -115,6 +111,15 @@ module.exports = {
&& arrayIncludes(node.raw, '\n');
}

function isFragmentWithSingleExpression(node) {
const children = node && node.children.filter((child) => !isPaddingSpaces(child));
return (
children
&& children.length === 1
&& children[0].type === 'JSXExpressionContainer'
);
}

/**
* Test whether a JSXElement has less than two children, excluding paddings spaces.
* @param {JSXElement|JSXFragment} node
Expand Down
7 changes: 7 additions & 0 deletions lib/rules/jsx-uses-vars.js
Expand Up @@ -11,6 +11,9 @@ const docsUrl = require('../util/docsUrl');
// Rule Definition
// ------------------------------------------------------------------------------

const isTagNameRe = /^[a-z]/;
const isTagName = (name) => isTagNameRe.test(name);

module.exports = {
meta: {
docs: {
Expand All @@ -33,6 +36,10 @@ module.exports = {
if (node.name.name) {
// <Foo>
name = node.name.name;
// Exclude lowercase tag names like <div>
if (isTagName(name)) {
return;
}
} else if (node.name.object) {
// <Foo...Bar>
let parent = node.name.object;
Expand Down
9 changes: 5 additions & 4 deletions lib/rules/no-typos.js
Expand Up @@ -157,11 +157,12 @@ module.exports = {
}

function reportErrorIfLifecycleMethodCasingTypo(node) {
let nodeKeyName = node.key.name;
if (node.key.type === 'Literal') {
nodeKeyName = node.key.value;
const key = node.key;
let nodeKeyName = key.name;
if (key.type === 'Literal') {
nodeKeyName = key.value;
}
if (node.computed && typeof nodeKeyName !== 'string') {
if (key.type === 'PrivateName' || (node.computed && typeof nodeKeyName !== 'string')) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/rules/prefer-read-only-props.js
Expand Up @@ -51,7 +51,7 @@ module.exports = {
Object.keys(component.declaredPropTypes).forEach((propName) => {
const prop = component.declaredPropTypes[propName];

if (!isFlowPropertyType(prop.node)) {
if (!prop.node || !isFlowPropertyType(prop.node)) {
return;
}

Expand Down
3 changes: 3 additions & 0 deletions lib/rules/require-default-props.js
Expand Up @@ -60,6 +60,9 @@ module.exports = {

Object.keys(propTypes).forEach((propName) => {
const prop = propTypes[propName];
if (!prop.node) {
return;
}
if (prop.isRequired) {
if (forbidDefaultForRequired && defaultProps[propName]) {
context.report({
Expand Down

0 comments on commit 8e5bbfb

Please sign in to comment.