packages/eslint-config-fbjs/index.js (376 lines of code) (raw):

/** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ /** * This file resembles what we use for our internal configuration. Several changes * have been made to acoomodate the differences between our internal setup and * what we would expect to see in open source. * * Internally we also lint each file individually, allowing use to use the file * path to selectively enable/disable pieces of the lint configuration. For * example, we don't actually want jest globals to be enabled all the time so * we only enable that when we know we're linting a test file. That isn't possible * here so we just always enable that. * * We are also missing our growing library of custom rules. Many of those will * make their way out here soon, but it does mean we need to do some editing of * our configuration object. */ 'use strict'; const shared = require('./shared'); const maxLenIgnorePattern = shared.maxLenIgnorePattern; // see http://eslint.org/docs/user-guide/configuring.html#configuring-rules const OFF = 0; const WARNING = 1; const ERROR = 2; const INDENT_SIZE = 2; function getBaseConfig() { return { parser: 'babel-eslint', parserOptions: { ecmaVersion: 6, sourceType: 'module', }, plugins: [ 'babel', 'flowtype', 'jsx-a11y', 'react', ], // Tries to match the jshint configuration as closely as possible, with the // exeception of a few things that jshint doesn't check, but that we really // shouldn't be using anyways. // // Things that jshint checked for are errors, new rules are warnings. // // If you update eslint, be sure to check the changelog to figure out what // rules to add/remove to/from this list. rules: { // Possible Errors <http://eslint.org/docs/rules/#possible-errors> // Forked and moved to fb-www/comma-dangle 'comma-dangle': OFF, // equivalent to jshint boss 'no-cond-assign': OFF, // equivalent to jshint devel 'no-console': [WARNING, { allow: ['warn', 'error', 'time', 'timeEnd', 'timeStamp'], }], // prohibits things like `while (true)` 'no-constant-condition': OFF, // we need to be able to match these 'no-control-regex': OFF, // equivalent to jshint debug 'no-debugger': ERROR, // equivalent to jshint W004 'no-dupe-args': ERROR, // syntax error in strict mode, almost certainly unintended in any case 'no-dupe-keys': ERROR, // almost certainly a bug 'no-duplicate-case': WARNING, // almost certainly a bug 'no-empty-character-class': WARNING, // would warn on uncommented empty `catch (ex) {}` blocks 'no-empty': OFF, // can cause subtle bugs in IE 8, and we shouldn't do this anyways 'no-ex-assign': WARNING, // we shouldn't do this anyways 'no-extra-boolean-cast': WARNING, // parens may be used to improve clarity, equivalent to jshint W068 'no-extra-parens': [WARNING, 'functions'], // equivalent to jshint W032 'no-extra-semi': WARNING, // a function delaration shouldn't be rewritable 'no-func-assign': ERROR, // babel and es6 allow block-scoped functions 'no-inner-declarations': OFF, // will cause a runtime error 'no-invalid-regexp': WARNING, // disallow non-space or tab whitespace characters 'no-irregular-whitespace': WARNING, // write `if (!(a in b))`, not `if (!a in b)`, equivalent to jshint W007 'no-negated-in-lhs': ERROR, // will cause a runtime error 'no-obj-calls': ERROR, // improves legibility 'no-regex-spaces': WARNING, // equivalent to jshint elision 'no-sparse-arrays': ERROR, // equivalent to jshint W027 'no-unreachable': ERROR, // equivalent to jshint use-isnan 'use-isnan': ERROR, // probably too noisy ATM 'valid-jsdoc': OFF, // equivalent to jshint notypeof 'valid-typeof': ERROR, // we already require semicolons 'no-unexpected-multiline': OFF, // Best Practices <http://eslint.org/docs/rules/#best-practices> // probably a bug, we shouldn't actually even use this yet, because of IE8 'accessor-pairs': [WARNING, {setWithoutGet: true}], // probably too noisy ATM 'block-scoped-var': OFF, // cyclomatic complexity, we're too far gone 'complexity': OFF, // require return statements to either always or never specify values 'consistent-return': WARNING, // style guide: Always use brackets, even when optional. 'curly': [WARNING, 'all'], // we don't do this/care about this 'default-case': OFF, // disabled in favor of our temporary fork 'dot-notation': OFF, // we don't do this/care about this, but probably should eventually 'dot-location': OFF, // disabled as it's too noisy ATM 'eqeqeq': [OFF, 'allow-null'], // we don't do this/care about this, equivalent to jshint forin 'guard-for-in': OFF, // we have too many internal examples/tools using this 'no-alert': OFF, // incompatible with 'use strict' equivalent to jshint noarg 'no-caller': ERROR, // we don't care about this right now, but might later 'no-case-declarations': OFF, // we don't do this/care about this 'no-div-regex': OFF, // we don't do this/care about this 'no-else-return': OFF, // avoid mistaken variables when destructuring 'no-empty-pattern': WARNING, // see eqeqeq: we explicitly allow this, equivalent to jshint eqnull 'no-eq-null': OFF, // equivalent to jshint evil 'no-eval': ERROR, // should only be triggered on polyfills, which we can fix case-by-case 'no-extend-native': WARNING, // might be a sign of a bug 'no-extra-bind': WARNING, // equivalent to jshint W089 'no-fallthrough': WARNING, // equivalent to jshint W008 'no-floating-decimal': ERROR, // implicit coercion is often idiomatic 'no-implicit-coercion': OFF, // equivalent to jshint evil/W066 'no-implied-eval': ERROR, // will likely create more signal than noise 'no-invalid-this': OFF, // babel should handle this fine 'no-iterator': OFF, // Should be effectively equivalent to jshint W028 - allowing the use // of labels in very specific situations. ESLint no-empty-labels was // deprecated. 'no-labels': [ERROR, {allowLoop: true, allowSwitch: true}], // lone blocks create no scope, will ignore blocks with let/const 'no-lone-blocks': WARNING, // equivalent to jshint loopfunc 'no-loop-func': OFF, // we surely have these, don't bother with it 'no-magic-numbers': OFF, // we may use this for alignment in some places 'no-multi-spaces': OFF, // equivalent to jshint multistr, consider using es6 template strings 'no-multi-str': ERROR, // equivalent to jshint W02OFF, similar to no-extend-native 'no-native-reassign': ERROR, // equivalent to jshint evil/W054 'no-new-func': ERROR, // don't use constructors for side-effects, equivalent to jshint nonew 'no-new': WARNING, // very limited uses, mostly in third_party 'no-new-wrappers': WARNING, // deprecated in ES5, but we still use it in some places 'no-octal-escape': WARNING, // deprecated in ES5, may cause unexpected behavior 'no-octal': WARNING, // treats function parameters as constants, probably too noisy ATM 'no-param-reassign': OFF, // only relevant to node code 'no-process-env': OFF, // deprecated in ES3.WARNING, equivalent to jshint proto 'no-proto': ERROR, // jshint doesn't catch this, but this is inexcusable 'no-redeclare': WARNING, // equivalent to jshint boss 'no-return-assign': OFF, // equivalent to jshint scripturl 'no-script-url': ERROR, // not in jshint, but is in jslint, and is almost certainly a mistake 'no-self-compare': WARNING, // there are very limited valid use-cases for this 'no-sequences': WARNING, // we're already pretty good about this, and it hides stack traces 'no-throw-literal': ERROR, // breaks on `foo && foo.bar()` expression statements, which are common 'no-unused-expressions': OFF, // disallow unnecessary .call() and .apply() 'no-useless-call': WARNING, // disallow concatenating string literals 'no-useless-concat': WARNING, // this has valid use-cases, eg. to circumvent no-unused-expressions 'no-void': OFF, // this journey is 1% finished (allow TODO comments) 'no-warning-comments': OFF, // equivalent to jshint withstmt 'no-with': OFF, // require radix argument in parseInt, we do this in most places already 'radix': WARNING, // we don't do this/care about this 'vars-on-top': OFF, // equivalent to jshint immed 'wrap-iife': OFF, // probably too noisy ATM 'yoda': OFF, // Strict Mode <http://eslint.org/docs/rules/#strict-mode> // jshint wasn't checking this, and the compiler should add this anyways 'strict': OFF, // Variables <http://eslint.org/docs/rules/#variables> // we don't do this/care about this 'init-declarations': OFF, // equivalent to jshint W002, catches an IE8 bug 'no-catch-shadow': ERROR, // equivalent to jshint W051, is a strict mode violation 'no-delete-var': ERROR, // we should avoid labels anyways 'no-label-var': WARNING, // redefining undefined, NaN, Infinity, arguments, and eval is bad, mkay? 'no-shadow-restricted-names': WARNING, // a definite code-smell, but probably too noisy 'no-shadow': OFF, // it's nice to be explicit sometimes: `let foo = undefined;` 'no-undef-init': OFF, // equivalent to jshint undef, turned into an error in getConfig 'no-undef': WARNING, // using undefined is safe because we enforce no-shadow-restricted-names 'no-undefined': OFF, // equivalent to jshint unused 'no-unused-vars': [WARNING, {args: 'none', varsIgnorePattern: '^_'}], // too noisy 'no-use-before-define': OFF, // Node.js <http://eslint.org/docs/rules/#nodejs> // TODO: turn some of these on in places where we lint node code 'callback-return': OFF, 'global-require': OFF, 'handle-callback-err': OFF, 'no-mixed-requires': OFF, 'no-new-require': OFF, 'no-path-concat': OFF, 'no-process-exit': OFF, 'no-restricted-modules': OFF, 'no-sync': OFF, // Stylistic Issues <http://eslint.org/docs/rules/#stylistic-issues> // See also: https://our.intern.facebook.com/intern/dex/style-guide/ 'array-bracket-spacing': WARNING, // TODO: enable this with consensus on single line blocks 'block-spacing': OFF, 'brace-style': [WARNING, '1tbs', {allowSingleLine: true}], // too noisy at the moment, and jshint didn't check it 'camelcase': [OFF, {properties: 'always'}], 'comma-spacing': [WARNING, {before: false, after: true}], // jshint had laxcomma, but that was against our style guide 'comma-style': [WARNING, 'last'], 'computed-property-spacing': [WARNING, 'never'], // we may use more contextually relevant names for this than self 'consistent-this': [OFF, 'self'], // should be handled by a generic TXT linter instead 'eol-last': OFF, 'func-names': OFF, // too noisy ATM 'func-style': [OFF, 'declaration'], // no way we could enforce min/max lengths or patterns for vars 'id-length': OFF, 'id-match': OFF, // we weren't enforcing this with jshint, so erroring would be too noisy 'indent': [WARNING, INDENT_SIZE, {SwitchCase: 1}], // we use single quotes for JS literals, double quotes for JSX literals 'jsx-quotes': [WARNING, 'prefer-double'], // we may use extra spaces for alignment 'key-spacing': [OFF, {beforeColon: false, afterColon: true}], 'keyword-spacing': [WARNING], 'lines-around-comment': OFF, // should be handled by a generic TXT linter instead 'linebreak-style': [OFF, 'unix'], 'max-depth': OFF, 'max-len': [WARNING, 80, INDENT_SIZE, {'ignorePattern': maxLenIgnorePattern, 'ignoreUrls': true}, ], 'max-nested-callbacks': OFF, 'max-params': OFF, 'max-statements': OFF, // https://facebook.com/groups/995898333776940/1027358627297577 'new-cap': OFF, // equivalent to jshint W058 'new-parens': ERROR, 'newline-after-var': OFF, 'no-array-constructor': ERROR, 'no-bitwise': WARNING, 'no-continue': OFF, 'no-inline-comments': OFF, // doesn't play well with `if (__DEV__) {}` 'no-lonely-if': OFF, // stopgap, irrelevant if we can eventually turn `indent` on to error 'no-mixed-spaces-and-tabs': ERROR, // don't care 'no-multiple-empty-lines': OFF, 'no-negated-condition': OFF, // we do this a bunch of places, and it's less bad with proper indentation 'no-nested-ternary': OFF, // similar to FacebookWebJSLintLinter's checkPhpStyleArray 'no-new-object': WARNING, 'no-plusplus': OFF, 'no-restricted-syntax': OFF, 'no-spaced-func': WARNING, 'no-ternary': OFF, // should be handled by a generic TXT linter instead 'no-trailing-spaces': OFF, // we use this for private/protected identifiers 'no-underscore-dangle': OFF, // disallow `let isYes = answer === 1 ? true : false;` 'no-unneeded-ternary': WARNING, // too noisy ATM 'object-curly-spacing': OFF, // makes indentation warnings clearer 'one-var': [WARNING, {initialized: 'never'}], // prefer `x += 4` over `x = x + 4` 'operator-assignment': [WARNING, 'always'], // equivalent to jshint laxbreak 'operator-linebreak': OFF, 'padded-blocks': OFF, // probably too noisy on pre-ES5 code 'quote-props': [OFF, 'as-needed'], 'quotes': [ WARNING, 'single', { avoidEscape: true, allowTemplateLiterals: true, }, ], 'require-jsdoc': OFF, 'semi-spacing': [WARNING, {before: false, after: true}], // equivalent to jshint asi/W032 'semi': [WARNING, 'always'], 'sort-vars': OFF, // require `if () {` instead of `if (){` 'space-before-blocks': [WARNING, 'always'], // require `function foo()` instead of `function foo ()` 'space-before-function-paren': [ WARNING, {anonymous: 'never', named: 'never'}, ], // incompatible with our legacy inline type annotations 'space-in-parens': [OFF, 'never'], 'space-infix-ops': [WARNING, {int32Hint: true}], 'space-unary-ops': [WARNING, {words: true, nonwords: false}], // TODO: Figure out a way to do this that doesn't break typechecks // or wait for https://github.com/eslint/eslint/issues/2897 'spaced-comment': [OFF, 'always', {exceptions: ['jshint', 'jslint', 'eslint', 'global']}], 'wrap-regex': OFF, // ECMAScript 6 <http://eslint.org/docs/rules/#ecmascript-6> 'arrow-body-style': OFF, // Forked to fb-www/arrow-parens to fix issues with flow and add fixer 'arrow-parens': OFF, // tbgs finds *very few* places where we don't put spaces around => 'arrow-spacing': [WARNING, {before: true, after: true}], // violation of the ES6 spec, won't transform 'constructor-super': ERROR, // https://github.com/babel/babel-eslint#known-issues 'generator-star-spacing': OFF, 'no-class-assign': WARNING, 'no-confusing-arrow': OFF, // this is a runtime error 'no-const-assign': ERROR, 'no-dupe-class-members': ERROR, // violation of the ES6 spec, won't transform, `this` is part of the TDZ 'no-this-before-super': ERROR, 'no-useless-computed-key': WARNING, // we have way too much ES3 & ES5 code 'no-var': OFF, 'object-shorthand': OFF, 'prefer-const': OFF, 'prefer-spread': OFF, // we don't support/polyfill this yet 'prefer-reflect': OFF, 'prefer-template': OFF, // there are legitimate use-cases for an empty generator 'require-yield': OFF, // eslint-plugin-babel <https://github.com/babel/eslint-plugin-babel> 'babel/generator-star-spacing': OFF, 'babel/new-cap': OFF, 'babel/array-bracket-spacing': OFF, 'babel/object-curly-spacing': OFF, 'babel/object-shorthand': OFF, 'babel/arrow-parens': OFF, 'babel/no-await-in-loop': OFF, 'babel/flow-object-type': [WARNING, 'comma'], // eslint-plugin-react <https://github.com/yannickcr/eslint-plugin-react> // TODO: We're being extremely conservative here as we roll out eslint on // www. As we finish rollout, we can turn on more of these, and replace // some legacy regex rules in the process. 'react/display-name': OFF, 'react/forbid-prop-types': OFF, 'react/jsx-boolean-value': OFF, 'react/jsx-closing-bracket-location': OFF, 'react/jsx-curly-spacing': OFF, 'react/jsx-equals-spacing': WARNING, 'react/jsx-filename-extension': OFF, 'react/jsx-first-prop-new-line': OFF, 'react/jsx-handler-names': OFF, 'react/jsx-indent': OFF, 'react/jsx-indent-props': OFF, 'react/jsx-key': OFF, 'react/jsx-max-props-per-line': OFF, 'react/jsx-no-bind': OFF, 'react/jsx-no-duplicate-props': ERROR, 'react/jsx-no-literals': OFF, 'react/jsx-no-target-blank': OFF, 'react/jsx-no-undef': ERROR, 'react/jsx-pascal-case': OFF, 'react/jsx-sort-props': OFF, 'react/jsx-space-before-closing': OFF, // forked to fb-www/jsx-uses-react 'react/jsx-uses-react': OFF, 'react/jsx-uses-vars': ERROR, 'react/jsx-wrap-multilines': OFF, 'react/no-comment-textnodes': OFF, 'react/no-danger': OFF, 'react/no-deprecated': OFF, 'react/no-did-mount-set-state': OFF, 'react/no-did-update-set-state': OFF, 'react/no-direct-mutation-state': OFF, 'react/no-is-mounted': WARNING, 'react/no-multi-comp': OFF, 'react/no-render-return-value': OFF, 'react/no-set-state': OFF, 'react/no-string-refs': OFF, 'react/no-unknown-property': OFF, 'react/prefer-es6-class': OFF, 'react/prefer-stateless-function': OFF, 'react/prop-types': OFF, // forked to fb-www/react-in-jsx-scope 'react/react-in-jsx-scope': OFF, 'react/require-extension': OFF, 'react/require-optimization': OFF, 'react/require-render-return': OFF, 'react/self-closing-comp': OFF, 'react/sort-comp': OFF, 'react/sort-prop-types': OFF, // JSX Accessibility checks 'jsx-a11y/accessible-emoji': OFF, 'jsx-a11y/anchor-has-content': OFF, 'jsx-a11y/aria-activedescendant-has-tabindex': OFF, 'jsx-a11y/aria-props': WARNING, 'jsx-a11y/aria-proptypes': OFF, 'jsx-a11y/aria-role': WARNING, 'jsx-a11y/aria-unsupported-elements': OFF, 'jsx-a11y/click-events-have-key-events': OFF, 'jsx-a11y/heading-has-content': OFF, 'jsx-a11y/html-has-lang': OFF, 'jsx-a11y/iframe-has-title': OFF, 'jsx-a11y/img-has-alt': OFF, 'jsx-a11y/img-redundant-alt': OFF, 'jsx-a11y/interactive-supports-focus': [ WARNING, { tabbable: [ 'button', 'checkbox', 'link', 'searchbox', 'spinbutton', 'switch', 'textbox', ], }, ], 'jsx-a11y/label-has-for': OFF, 'jsx-a11y/lang': OFF, 'jsx-a11y/mouse-events-have-key-events': OFF, 'jsx-a11y/no-access-key': OFF, 'jsx-a11y/no-autofocus': OFF, 'jsx-a11y/no-distracting-elements': OFF, 'jsx-a11y/no-interactive-element-to-noninteractive-role': [ WARNING, { tr: ['none', 'presentation'], }, ], 'jsx-a11y/no-noninteractive-element-interactions': [ WARNING, { handlers: ['onClick'], }, ], 'jsx-a11y/no-noninteractive-element-to-interactive-role': [ WARNING, { ul: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'], ol: ['listbox', 'menu', 'menubar', 'radiogroup', 'tablist', 'tree', 'treegrid'], li: ['menuitem', 'option', 'row', 'tab', 'treeitem'], table: ['grid'], td: ['gridcell'], }, ], 'jsx-a11y/no-noninteractive-tabindex': WARNING, 'jsx-a11y/no-onchange': OFF, 'jsx-a11y/no-redundant-roles': OFF, 'jsx-a11y/no-static-element-interactions': [ WARNING, { handlers: ['onClick'], }, ], 'jsx-a11y/role-has-required-aria-props': WARNING, 'jsx-a11y/role-supports-aria-props': WARNING, 'jsx-a11y/scope': OFF, 'jsx-a11y/tabindex-no-positive': WARNING, // eslint-plugin-flowtype // These don't actually result in warnings. Enabling them ensures they run // and mark variables as used, avoiding false positives with Flow // annotations. 'flowtype/define-flow-type': WARNING, 'flowtype/use-flow-type': WARNING, }, // Defines a basic set of globals env: { browser: true, es6: true, }, globals: shared.globals, }; } // Override some rules for open source. Due to the way we apply our configuation // internally, these are effectively part of the same configuration we apply. var config = getBaseConfig(); var extendedConfig = { env: { // Enable these blindly because we can't make a per-file decision about this. node: true, jest: true, jasmine: true, }, rules: { // just turned into an error here since we almost always do that anyway. 'no-undef': ERROR, // Re-enable some forked rules. Good enough for open source 'comma-dangle': [WARNING, 'always-multiline'], 'react/jsx-uses-react': ERROR, 'react/react-in-jsx-scope': ERROR, // To keep base config in sync with internal codebase but still make // open source happy, disable a deprecated rule and enable different one. 'babel/flow-object-type': OFF, 'flowtype/object-type-delimiter': [WARNING, 'comma'], }, }; Object.keys(extendedConfig).forEach((key) => { config[key] = Object.assign(config[key], extendedConfig[key]); }); module.exports = config;