2023-01-03 19:55:46 +00:00
// Copyright 2018 Signal Messenger, LLC
2020-10-30 20:34:04 +00:00
// SPDX-License-Identifier: AGPL-3.0-only
2023-01-05 22:43:33 +00:00
const { messagesCacheKey } = require ( './.eslint/rules/valid-i18n-keys' ) ;
2020-10-30 20:34:04 +00:00
2018-01-08 21:19:25 +00:00
// For reference: https://github.com/airbnb/javascript
2020-09-03 14:59:24 +00:00
const rules = {
'comma-dangle' : [
'error' ,
{
arrays : 'always-multiline' ,
objects : 'always-multiline' ,
imports : 'always-multiline' ,
exports : 'always-multiline' ,
functions : 'never' ,
} ,
] ,
2022-09-13 21:48:09 +00:00
// No omitting braces, keep on the same line
'brace-style' : [ 'error' , '1tbs' , { allowSingleLine : false } ] ,
curly : [ 'error' , 'all' ] ,
2023-10-04 00:12:57 +00:00
// Immer support
'no-param-reassign' : [
'error' ,
{
props : true ,
ignorePropertyModificationsForRegex : [ '^draft' ] ,
ignorePropertyModificationsFor : [ 'acc' , 'ctx' , 'context' ] ,
} ,
] ,
2022-09-14 21:40:44 +00:00
// Always use === and !== except when directly comparing to null
// (which only will equal null or undefined)
eqeqeq : [ 'error' , 'always' , { null : 'never' } ] ,
2020-09-03 14:59:24 +00:00
// prevents us from accidentally checking in exclusive tests (`.only`):
'mocha/no-exclusive-tests' : 'error' ,
// encourage consistent use of `async` / `await` instead of `then`
'more/no-then' : 'error' ,
// it helps readability to put public API at top,
'no-use-before-define' : 'off' ,
2021-12-14 01:15:24 +00:00
'@typescript-eslint/no-use-before-define' : 'off' ,
2020-09-03 14:59:24 +00:00
// useful for unused or internal fields
'no-underscore-dangle' : 'off' ,
2022-09-15 19:17:15 +00:00
// Temp: We have because TypeScript's `allowUnreachableCode` option is on.
'no-unreachable' : 'error' ,
2020-09-03 14:59:24 +00:00
// though we have a logger, we still remap console to log to disk
'no-console' : 'error' ,
// consistently place operators at end of line except ternaries
'operator-linebreak' : [
'error' ,
'after' ,
{ overrides : { '?' : 'ignore' , ':' : 'ignore' } } ,
] ,
quotes : [
'error' ,
'single' ,
{ avoidEscape : true , allowTemplateLiterals : false } ,
] ,
2020-10-28 01:00:28 +00:00
'no-continue' : 'off' ,
2021-08-30 21:32:56 +00:00
'lines-between-class-members' : 'off' ,
2021-11-04 21:04:51 +00:00
'class-methods-use-this' : 'off' ,
2020-10-28 01:00:28 +00:00
2020-09-03 14:59:24 +00:00
// Prettier overrides:
'arrow-parens' : 'off' ,
'function-paren-newline' : 'off' ,
'max-len' : [
'error' ,
{
// Prettier generally limits line length to 80 but sometimes goes over.
// The `max-len` plugin doesn’ t let us omit `code` so we set it to a
// high value as a buffer to let Prettier control the line length:
code : 999 ,
// We still want to limit comments as before:
comments : 90 ,
ignoreUrls : true ,
} ,
] ,
2020-09-12 00:46:52 +00:00
'react/jsx-props-no-spreading' : 'off' ,
// Updated to reflect future airbnb standard
// Allows for declaring defaultProps inside a class
'react/static-property-placement' : [ 'error' , 'static public field' ] ,
// JIRA: DESKTOP-657
'react/sort-comp' : 'off' ,
// We don't have control over the media we're sharing, so can't require
// captions.
'jsx-a11y/media-has-caption' : 'off' ,
// We prefer named exports
2020-09-03 14:59:24 +00:00
'import/prefer-default-export' : 'off' ,
2020-09-12 00:46:52 +00:00
// Prefer functional components with default params
'react/require-default-props' : 'off' ,
2020-09-14 21:56:35 +00:00
2022-11-18 00:45:19 +00:00
// Empty fragments are used in adapters between backbone and react views.
2022-12-02 22:09:13 +00:00
'react/jsx-no-useless-fragment' : [
'error' ,
{
allowExpressions : true ,
} ,
] ,
2022-11-18 00:45:19 +00:00
// Our code base has tons of arrow functions passed directly to components.
'react/jsx-no-bind' : 'off' ,
// Does not support forwardRef
'react/no-unused-prop-types' : 'off' ,
// Not useful for us as we have lots of complicated types.
'react/destructuring-assignment' : 'off' ,
2022-12-02 22:09:13 +00:00
'react/function-component-definition' : [
'error' ,
{
namedComponents : 'function-declaration' ,
unnamedComponents : 'arrow-function' ,
} ,
] ,
2022-11-18 00:45:19 +00:00
'react/display-name' : 'error' ,
2023-02-23 18:38:09 +00:00
'react/jsx-pascal-case' : [ 'error' , { allowNamespace : true } ] ,
2023-01-25 23:51:08 +00:00
2022-11-18 00:45:19 +00:00
// Allow returning values from promise executors for brevity.
'no-promise-executor-return' : 'off' ,
// Redux ducks use this a lot
'default-param-last' : 'off' ,
2020-09-14 21:56:35 +00:00
'jsx-a11y/label-has-associated-control' : [ 'error' , { assert : 'either' } ] ,
2020-09-16 14:26:06 +00:00
2021-01-14 18:07:05 +00:00
'no-restricted-syntax' : [
'error' ,
{
selector : 'TSInterfaceDeclaration' ,
message :
'Prefer `type`. Interfaces are mutable and less powerful, so we prefer `type` for simplicity.' ,
} ,
// Defaults
{
selector : 'ForInStatement' ,
message :
'for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.' ,
} ,
{
selector : 'LabeledStatement' ,
message :
'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.' ,
} ,
{
selector : 'WithStatement' ,
message :
'`with` is disallowed in strict mode because it makes code impossible to predict and optimize.' ,
} ,
] ,
2020-09-03 14:59:24 +00:00
} ;
2021-07-02 19:09:34 +00:00
const typescriptRules = {
... rules ,
2022-09-13 21:48:09 +00:00
// Override brace style to enable typescript-specific syntax
'brace-style' : 'off' ,
'@typescript-eslint/brace-style' : [
'error' ,
'1tbs' ,
{ allowSingleLine : false } ,
] ,
2021-07-08 21:55:48 +00:00
'@typescript-eslint/array-type' : [ 'error' , { default : 'generic' } ] ,
2021-12-17 22:24:54 +00:00
'no-restricted-imports' : 'off' ,
'@typescript-eslint/no-restricted-imports' : [
'error' ,
{
paths : [
2022-01-19 19:19:08 +00:00
{
name : 'chai' ,
importNames : [ 'expect' , 'should' , 'Should' ] ,
message : 'Please use assert' ,
allowTypeImports : true ,
} ,
2021-12-17 22:24:54 +00:00
] ,
} ,
] ,
2021-07-02 19:09:34 +00:00
// Overrides recommended by typescript-eslint
// https://github.com/typescript-eslint/typescript-eslint/releases/tag/v4.0.0
'@typescript-eslint/no-redeclare' : 'error' ,
'@typescript-eslint/no-shadow' : 'error' ,
'@typescript-eslint/no-useless-constructor' : [ 'error' ] ,
2022-12-21 18:41:48 +00:00
'@typescript-eslint/no-misused-promises' : [
'error' ,
{
2023-01-03 19:55:46 +00:00
checksVoidReturn : false ,
} ,
2022-12-21 18:41:48 +00:00
] ,
'@typescript-eslint/no-floating-promises' : 'error' ,
// We allow "void promise", but new call-sites should use `drop(promise)`.
2023-01-03 19:55:46 +00:00
'no-void' : [ 'error' , { allowAsStatement : true } ] ,
2022-12-21 18:41:48 +00:00
2021-07-02 19:09:34 +00:00
'no-shadow' : 'off' ,
'no-useless-constructor' : 'off' ,
// useful for unused parameters
'@typescript-eslint/no-unused-vars' : [ 'error' , { argsIgnorePattern : '^_' } ] ,
// Upgrade from a warning
'@typescript-eslint/explicit-module-boundary-types' : 'error' ,
2021-10-26 19:15:33 +00:00
'@typescript-eslint/consistent-type-imports' : 'error' ,
2023-03-28 18:26:46 +00:00
// Future: Maybe switch to never and always use `satisfies`
'@typescript-eslint/consistent-type-assertions' : [
'error' ,
{
assertionStyle : 'as' ,
// Future: Maybe switch to allow-as-parameter or never
objectLiteralTypeAssertions : 'allow' ,
} ,
] ,
2021-07-02 19:09:34 +00:00
// Already enforced by TypeScript
'consistent-return' : 'off' ,
2022-12-02 22:09:13 +00:00
// TODO: DESKTOP-4655
'import/no-cycle' : 'off' ,
2023-01-05 22:43:33 +00:00
'local-rules/valid-i18n-keys' : [ 'error' , { messagesCacheKey } ] ,
2021-07-02 19:09:34 +00:00
} ;
2018-01-08 21:19:25 +00:00
module . exports = {
2020-09-01 00:09:28 +00:00
root : true ,
2018-01-08 21:19:25 +00:00
settings : {
2020-09-01 00:09:28 +00:00
react : {
version : 'detect' ,
} ,
2018-04-27 21:25:04 +00:00
'import/core-modules' : [ 'electron' ] ,
2018-01-08 21:19:25 +00:00
} ,
2018-04-27 21:25:04 +00:00
extends : [ 'airbnb-base' , 'prettier' ] ,
2018-01-08 21:19:25 +00:00
2023-01-05 22:43:33 +00:00
plugins : [ 'mocha' , 'more' , 'local-rules' ] ,
2018-02-22 18:21:53 +00:00
2020-09-01 00:09:28 +00:00
overrides : [
{
2022-06-13 21:39:35 +00:00
files : [
'ts/**/*.ts' ,
'ts/**/*.tsx' ,
'app/**/*.ts' ,
2022-10-03 21:19:54 +00:00
'build/intl-linter/**/*.ts' ,
2020-09-01 00:09:28 +00:00
] ,
2020-09-14 21:56:35 +00:00
parser : '@typescript-eslint/parser' ,
parserOptions : {
2022-06-13 21:39:35 +00:00
project : 'tsconfig.json' ,
2020-09-14 21:56:35 +00:00
ecmaFeatures : {
jsx : true ,
} ,
ecmaVersion : 2018 ,
sourceType : 'module' ,
} ,
plugins : [ '@typescript-eslint' ] ,
extends : [
'eslint:recommended' ,
'plugin:@typescript-eslint/recommended' ,
'plugin:react/recommended' ,
'airbnb-typescript-prettier' ,
] ,
2021-07-02 19:09:34 +00:00
rules : typescriptRules ,
2020-09-14 21:56:35 +00:00
} ,
2020-09-01 00:09:28 +00:00
{
2022-10-03 21:19:54 +00:00
files : [
'**/*.stories.tsx' ,
'ts/build/**' ,
'ts/test-*/**' ,
'build/intl-linter/**/*.ts' ,
] ,
2020-09-01 00:09:28 +00:00
rules : {
2021-07-02 19:09:34 +00:00
... typescriptRules ,
2020-09-01 00:09:28 +00:00
'import/no-extraneous-dependencies' : 'off' ,
2020-09-14 19:51:27 +00:00
'react/no-array-index-key' : 'off' ,
2020-09-01 00:09:28 +00:00
} ,
} ,
2023-01-13 20:07:26 +00:00
{
files : [ 'ts/state/ducks/**/*.ts' ] ,
rules : {
'local-rules/type-alias-readonlydeep' : 'error' ,
} ,
} ,
2020-09-01 00:09:28 +00:00
] ,
2022-12-02 22:09:13 +00:00
rules : {
... rules ,
'import/no-unresolved' : 'off' ,
'import/extensions' : 'off' ,
} ,
2022-06-03 21:07:51 +00:00
reportUnusedDisableDirectives : true ,
2018-01-08 21:19:25 +00:00
} ;