[lint] Add lint rule enforcing React Fragment shorthand (#8585)

This commit is contained in:
Erik Ritter 2019-11-18 16:17:12 -08:00 committed by GitHub
parent ff6ab10893
commit 7d14b71a93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 94 additions and 51 deletions

View File

@ -27,21 +27,28 @@
"env": {
"browser": true
},
"plugins": ["react"],
"rules": {
"camelcase": ["error", {
"allow": ["^UNSAFE_"],
"properties": "never"
}],
"camelcase": [
"error",
{
"allow": ["^UNSAFE_"],
"properties": "never"
}
],
"class-methods-use-this": 0,
"func-names": 0,
"guard-for-in": 0,
"import/extensions": ["error", {
".js": "always",
".jsx": "always",
".ts": "always",
".tsx": "always",
".json": "always"
}],
"import/extensions": [
"error",
{
".js": "always",
".jsx": "always",
".ts": "always",
".tsx": "always",
".json": "always"
}
],
"import/no-named-as-default": 0,
"import/prefer-default-export": 0,
"indent": 0,
@ -68,9 +75,14 @@
"react/no-string-refs": 0,
"react/no-unescaped-entities": 0,
"react/no-unused-prop-types": 0,
"react/require-default-props": 0
"react/require-default-props": 0,
"react/jsx-fragments": 1,
"react/prop-types": 0
},
"settings": {
"import/resolver": "webpack"
"import/resolver": "webpack",
"react": {
"version": "detect"
}
}
}

View File

@ -10271,25 +10271,56 @@
}
},
"eslint-plugin-react": {
"version": "7.11.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz",
"integrity": "sha512-cVVyMadRyW7qsIUh3FHp3u6QHNhOgVrLQYdQEB1bPWBsgbNCHdFAeNMquBMCcZJu59eNthX053L70l7gRt4SCw==",
"version": "7.16.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.16.0.tgz",
"integrity": "sha512-GacBAATewhhptbK3/vTP09CbFrgUJmBSaaRcWdbQLFvUZy9yVcQxigBNHGPU/KE2AyHpzj3AWXpxoMTsIDiHug==",
"dev": true,
"requires": {
"array-includes": "^3.0.3",
"doctrine": "^2.1.0",
"has": "^1.0.3",
"jsx-ast-utils": "^2.0.1",
"prop-types": "^15.6.2"
"jsx-ast-utils": "^2.2.1",
"object.entries": "^1.1.0",
"object.fromentries": "^2.0.0",
"object.values": "^1.1.0",
"prop-types": "^15.7.2",
"resolve": "^1.12.0"
},
"dependencies": {
"jsx-ast-utils": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz",
"integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=",
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz",
"integrity": "sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA==",
"dev": true,
"requires": {
"array-includes": "^3.0.3"
"array-includes": "^3.0.3",
"object.assign": "^4.1.0"
}
},
"prop-types": {
"version": "15.7.2",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
"dev": true,
"requires": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
"react-is": "^16.8.1"
}
},
"react-is": {
"version": "16.12.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz",
"integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==",
"dev": true
},
"resolve": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
"integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
"dev": true,
"requires": {
"path-parse": "^1.0.6"
}
}
}
@ -10778,7 +10809,7 @@
"dependencies": {
"core-js": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
"resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
"integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
}
}

View File

@ -183,7 +183,7 @@
"eslint-plugin-jsx-a11y": "^5.1.1",
"eslint-plugin-no-only-tests": "^2.0.1",
"eslint-plugin-prettier": "^2.6.0",
"eslint-plugin-react": "^7.0.1",
"eslint-plugin-react": "^7.16.0",
"exports-loader": "^0.7.0",
"fetch-mock": "^7.0.0-alpha.6",
"file-loader": "^1.1.11",

View File

@ -109,10 +109,10 @@ class App extends React.PureComponent {
);
} else {
content = (
<React.Fragment>
<>
<QueryAutoRefresh />
<TabbedSqlEditors />
</React.Fragment>
</>
);
}
return (

View File

@ -184,7 +184,7 @@ class ExploreResultsButton extends React.PureComponent {
render() {
const allowsSubquery = this.props.database && this.props.database.allows_subquery;
return (
<React.Fragment>
<>
<Button
bsSize="small"
onClick={this.onClick}
@ -198,7 +198,7 @@ class ExploreResultsButton extends React.PureComponent {
this.dialog = el;
}}
/>
</React.Fragment>
</>
);
}
}

View File

@ -213,7 +213,7 @@ export default class ResultSet extends React.PureComponent {
? results.expanded_columns.map(col => col.name)
: [];
return (
<React.Fragment>
<>
{this.renderControls.bind(this)()}
{sql}
<FilterableTable
@ -223,7 +223,7 @@ export default class ResultSet extends React.PureComponent {
filterText={this.state.searchText}
expandedColumns={expandedColumns}
/>
</React.Fragment>
</>
);
} else if (data && data.length === 0) {
return <Alert bsStyle="warning">{t('The query returned no data')}</Alert>;

View File

@ -238,10 +238,10 @@ class TabbedSqlEditors extends React.PureComponent {
const state = latestQuery ? latestQuery.state : '';
const title = (
<React.Fragment>
<>
<TabStatusIcon onClose={() => this.removeQueryEditor(qe)} tabState={state} />{' '}
{qe.title}{' '}
</React.Fragment>
</>
);
const tabTitle = (
<SplitButton

View File

@ -208,7 +208,7 @@ class ChartRenderer extends React.Component {
} = this.props;
return (
<React.Fragment>
<>
{this.renderTooltip()}
<SuperChart
disableErrorBoundary
@ -226,7 +226,7 @@ class ChartRenderer extends React.Component {
onRenderSuccess={this.handleRenderSuccess}
onRenderFailure={this.handleRenderFailure}
/>
</React.Fragment>
</>
);
}
}

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import React, { Fragment } from 'react';
import React from 'react';
import PropTypes from 'prop-types';
import { Modal, MenuItem } from 'react-bootstrap';
import cx from 'classnames';
@ -105,7 +105,7 @@ export default class ModalTrigger extends React.Component {
});
if (this.props.isButton) {
return (
<Fragment>
<>
<Button
className="modal-trigger"
tooltip={this.props.tooltip}
@ -114,26 +114,26 @@ export default class ModalTrigger extends React.Component {
{this.props.triggerNode}
</Button>
{this.renderModal()}
</Fragment>
</>
);
} else if (this.props.isMenuItem) {
return (
<Fragment>
<>
<MenuItem onClick={this.open}>
{this.props.triggerNode}
</MenuItem>
{this.renderModal()}
</Fragment>
</>
);
}
/* eslint-disable jsx-a11y/interactive-supports-focus */
return (
<Fragment>
<>
<span className={classNames} onClick={this.open} role="button">
{this.props.triggerNode}
</span>
{this.renderModal()}
</Fragment>
</>
);
}
}

View File

@ -173,10 +173,10 @@ class Dashboard extends React.PureComponent {
render() {
return (
<React.Fragment>
<>
<OmniContainer logEvent={this.props.actions.logEvent} />
<DashboardBuilder />
</React.Fragment>
</>
);
}
}

View File

@ -53,7 +53,7 @@ class FilterIndicatorGroup extends React.PureComponent {
return (
<FilterTooltipWrapper
tooltip={
<React.Fragment>
<>
<div className="group-title">
{t('%s filters', indicators.length)}
</div>
@ -68,7 +68,7 @@ class FilterIndicatorGroup extends React.PureComponent {
</li>
))}
</ul>
</React.Fragment>
</>
}
>
<div

View File

@ -55,7 +55,7 @@ class FilterTooltipWrapper extends React.Component {
render() {
const { show, target } = this.state;
return (
<React.Fragment>
<>
<Overlay container={this} target={target} show={show} placement="left">
<Tooltip id="filter-indicator-tooltip">
<div onMouseOver={this.showTooltip} onMouseOut={this.hideTooltip}>
@ -72,7 +72,7 @@ class FilterTooltipWrapper extends React.Component {
>
{this.props.children}
</div>
</React.Fragment>
</>
);
}
}

View File

@ -440,7 +440,7 @@ export default class FilterScopeSelector extends React.PureComponent {
checkedFilterFields,
});
return (
<React.Fragment>
<>
<input
className="filter-text scope-search multi-edit-mode"
placeholder={t('Search...')}
@ -458,7 +458,7 @@ export default class FilterScopeSelector extends React.PureComponent {
// to hide checkbox for selected filter field itself
selectedChartId={selectedChartId}
/>
</React.Fragment>
</>
);
}

View File

@ -151,14 +151,14 @@ export default class VizTypeControl extends React.PureComponent {
<Tooltip id="error-tooltip">{t('Click to change visualization type')}</Tooltip>
}
>
<React.Fragment>
<>
<Label onClick={this.toggleModal} style={LABEL_STYLE}>
{registry.has(value) ? registry.get(value).name : `${value}`}
</Label>
{(!registry.has(value) && <div className="text-danger">
<i className="fa fa-exclamation-circle text-danger" /> <small>{t('This visualization type is not supported.')}</small>
</div>)}
</React.Fragment>
</>
</OverlayTrigger>
<Modal
show={showModal}