1/* 2 * Copyright (c) 2024-2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import stylistic from '@stylistic/eslint-plugin'; 17import _import from 'eslint-plugin-import'; 18import n from 'eslint-plugin-n'; 19import { fixupPluginRules } from '@eslint/compat'; 20import eslint from '@eslint/js'; 21import tseslint from 'typescript-eslint'; 22 23export default tseslint.config( 24 { 25 // config with just ignores is the replacement for `.eslintignore` 26 ignores: [ 27 'bin/**/*', 28 'build/**/*', 29 'bundle/**/*', 30 'dist/**/*', 31 'docs/**/*', 32 'node_modules/**/*', 33 'scripts/**/*', 34 'third_party/**/*', 35 'test/**/*', 36 '**/**.json', 37 '**/**.js', 38 'arkanalyzer/*', 39 'homecheck/*' 40 ] 41 }, 42 { 43 files: ['**/*.ts'], 44 extends: [eslint.configs.recommended, tseslint.configs.recommended], 45 plugins: { 46 '@typescript-eslint': tseslint.plugin, 47 '@stylistic': stylistic, 48 import: fixupPluginRules(_import), 49 n 50 }, 51 languageOptions: { 52 parser: tseslint.parser, 53 ecmaVersion: 'latest', 54 sourceType: 'module', 55 parserOptions: { 56 project: true 57 } 58 }, 59 rules: { 60 // suggestions 61 'accessor-pairs': 'error', 62 'arrow-body-style': ['error', 'always'], 63 camelcase: 'off', // we use naming-convention rule to enforce naming scheme 64 'class-methods-use-this': ['error', { exceptMethods: [], enforceForClassFields: true }], 65 complexity: ['error', { max: 15 }], 66 'consistent-return': ['error', { treatUndefinedAsUnspecified: false }], 67 curly: ['error', 'all'], 68 'default-case': 'error', 69 'default-param-last': 'warn', 70 'dot-notation': 'error', 71 eqeqeq: ['error', 'smart'], 72 'func-style': ['error', 'declaration', { allowArrowFunctions: true }], 73 'max-depth': ['error', { max: 4 }], 74 'max-lines-per-function': ['error', { max: 50 }], 75 'max-params': ['error', 5], 76 'multiline-comment-style': ['error', 'starred-block'], 77 'no-else-return': ['error', { allowElseIf: true }], 78 'no-eval': ['error', { allowIndirect: false }], 79 'no-extra-bind': 'error', 80 'no-implied-eval': 'error', 81 'no-lonely-if': 'error', 82 'no-nested-ternary': 'warn', 83 'no-param-reassign': 'warn', 84 'no-prototype-builtins': 'error', 85 'no-regex-spaces': 'error', 86 'no-return-await': 'error', 87 'no-throw-literal': 'error', 88 'no-undef-init': 'error', 89 'no-unneeded-ternary': 'error', 90 'no-useless-return': 'error', 91 'no-var': 'error', 92 'one-var': ['error', 'never'], 93 'one-var-declaration-per-line': 'error', 94 'prefer-const': 'error', 95 'prefer-named-capture-group': 'warn', 96 'prefer-rest-params': 'error', 97 strict: 'error', 98 'spaced-comment': ['error', 'always'], 99 'vars-on-top': 'error', 100 101 // imports 102 'import/no-absolute-path': 'error', 103 'n/file-extension-in-import': ['error', 'never', { '.json': 'always' }], 104 105 // style 106 '@stylistic/array-bracket-newline': ['error', 'consistent'], 107 '@stylistic/array-bracket-spacing': ['error', 'never'], 108 '@stylistic/array-element-newline': ['error', 'consistent'], 109 '@stylistic/arrow-parens': ['error', 'always'], 110 '@stylistic/arrow-spacing': ['error', { before: true, after: true }], 111 '@stylistic/block-spacing': ['error', 'always'], 112 '@stylistic/brace-style': ['error', '1tbs', { allowSingleLine: true }], 113 '@stylistic/comma-dangle': [ 114 'error', 115 { 116 arrays: 'never', 117 objects: 'never', 118 imports: 'never', 119 exports: 'never', 120 functions: 'never' 121 } 122 ], 123 '@stylistic/comma-spacing': ['error', { before: false, after: true }], 124 '@stylistic/comma-style': ['error', 'last'], 125 '@stylistic/computed-property-spacing': ['error', 'never', { enforceForClassMembers: true }], 126 '@stylistic/dot-location': ['error', 'object'], 127 '@stylistic/eol-last': ['error', 'always'], 128 '@stylistic/no-confusing-arrow': 'error', 129 '@stylistic/no-floating-decimal': 'error', 130 '@stylistic/func-call-spacing': ['error', 'never'], 131 '@stylistic/function-call-argument-newline': ['error', 'consistent'], 132 '@stylistic/function-paren-newline': ['error', 'consistent'], 133 '@stylistic/generator-star-spacing': ['error', { before: true, after: false }], 134 '@stylistic/implicit-arrow-linebreak': ['error', 'beside'], 135 '@stylistic/indent': [ 136 'error', 137 2, 138 { 139 ignoredNodes: [], 140 SwitchCase: 1, 141 VariableDeclarator: 1, 142 outerIIFEBody: 1, 143 MemberExpression: 1, 144 FunctionDeclaration: { 145 parameters: 1, 146 body: 1 147 }, 148 FunctionExpression: { 149 parameters: 1, 150 body: 1 151 }, 152 CallExpression: { 153 arguments: 1 154 }, 155 ArrayExpression: 1, 156 ObjectExpression: 1, 157 ImportDeclaration: 1, 158 flatTernaryExpressions: true, 159 offsetTernaryExpressions: false, 160 ignoreComments: false 161 } 162 ], 163 '@stylistic/jsx-quotes': ['error', 'prefer-double'], 164 '@stylistic/keyword-spacing': ['error', { before: true, after: true }], 165 'line-comment-position': ['error', { position: 'above' }], 166 '@stylistic/linebreak-style': ['error', 'unix'], 167 '@stylistic/lines-around-comment': ['error', { beforeBlockComment: true }], 168 '@stylistic/lines-between-class-members': [ 169 'error', 170 { 171 enforce: [ 172 { blankLine: 'always', prev: '*', next: 'method' }, 173 { blankLine: 'always', prev: 'method', next: '*' } 174 ] 175 } 176 ], 177 '@stylistic/max-len': [ 178 'error', 179 { 180 code: 120, 181 tabWidth: 2, 182 ignoreComments: true, 183 ignoreStrings: true 184 } 185 ], 186 '@stylistic/max-statements-per-line': ['error', { max: 1 }], 187 '@stylistic/multiline-ternary': ['error', 'always-multiline'], 188 '@stylistic/new-parens': ['error', 'always'], 189 '@stylistic/newline-per-chained-call': ['error', { ignoreChainWithDepth: 2 }], 190 '@stylistic/no-extra-parens': ['error', 'all'], 191 '@stylistic/no-mixed-spaces-and-tabs': 'error', 192 '@stylistic/no-multi-spaces': 'error', 193 '@stylistic/no-multiple-empty-lines': ['error', { max: 2, maxEOF: 1 }], 194 '@stylistic/no-tabs': 'error', 195 '@stylistic/no-trailing-spaces': ['error', { skipBlankLines: false, ignoreComments: false }], 196 '@stylistic/no-whitespace-before-property': 'error', 197 '@stylistic/nonblock-statement-body-position': ['error', 'beside'], 198 '@stylistic/object-curly-newline': ['error', { consistent: true }], 199 '@stylistic/object-curly-spacing': ['error', 'always'], 200 '@stylistic/operator-linebreak': ['error', 'after'], 201 // disable due to conflict with required rule 'lines-around-comment' 202 '@stylistic/padded-blocks': 'off', 203 '@stylistic/quotes': ['error', 'single'], 204 '@stylistic/rest-spread-spacing': ['error', 'never'], 205 '@stylistic/semi': ['error', 'always'], 206 '@stylistic/semi-spacing': ['error', { before: false, after: true }], 207 '@stylistic/semi-style': ['error', 'last'], 208 '@stylistic/space-before-blocks': ['error', 'always'], 209 '@stylistic/space-before-function-paren': ['error', 'never'], 210 '@stylistic/space-in-parens': ['error', 'never'], 211 '@stylistic/space-infix-ops': ['error'], 212 '@stylistic/space-unary-ops': ['error', { words: true, nonwords: false, overrides: {} }], 213 '@stylistic/switch-colon-spacing': ['error', { after: true, before: false }], 214 '@stylistic/template-curly-spacing': ['error', 'never'], 215 '@stylistic/template-tag-spacing': ['error', 'never'], 216 'unicode-bom': ['error', 'never'], 217 '@stylistic/wrap-iife': ['error', 'outside'], 218 '@stylistic/wrap-regex': 'error', 219 '@stylistic/yield-star-spacing': ['error', { before: true, after: false }], 220 221 // typescript 222 '@typescript-eslint/explicit-function-return-type': 'error', 223 '@typescript-eslint/adjacent-overload-signatures': 'error', 224 '@typescript-eslint/consistent-type-exports': 'error', 225 '@typescript-eslint/await-thenable': 'error', 226 '@typescript-eslint/no-dynamic-delete': 'error', 227 '@typescript-eslint/no-this-alias': 'error', 228 '@typescript-eslint/explicit-member-accessibility': [ 229 'error', 230 { 231 accessibility: 'no-public' 232 } 233 ], 234 '@typescript-eslint/method-signature-style': 'error', 235 '@typescript-eslint/no-confusing-non-null-assertion': 'error', 236 '@typescript-eslint/no-confusing-void-expression': 'error', 237 // FIXME(knazarov) 238 // need to do something about this 239 '@typescript-eslint/no-explicit-any': 'warn', 240 // Produce too many warning caused by 'any' usage 241 // "@typescript-eslint/no-unsafe-member-access": "warn", 242 // "@typescript-eslint/no-unsafe-assignment": "warn", 243 '@typescript-eslint/no-unsafe-call': 'warn', 244 '@typescript-eslint/no-unsafe-argument': 'warn', 245 '@typescript-eslint/no-unsafe-return': 'warn', 246 'no-unsafe-finally': 'error', 247 '@typescript-eslint/no-extra-non-null-assertion': 'error', 248 '@typescript-eslint/no-meaningless-void-operator': 'error', 249 '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error', 250 // FIXME(knazarov) 251 // disabled due to many cases, where typescript deduces non-undefined value, but we can receive one from the api 252 '@typescript-eslint/no-unnecessary-condition': 'off', 253 '@typescript-eslint/no-unnecessary-type-assertion': 'error', 254 '@typescript-eslint/prefer-as-const': 'error', 255 '@typescript-eslint/prefer-optional-chain': 'error', 256 '@typescript-eslint/prefer-readonly': 'error', 257 '@typescript-eslint/consistent-type-imports': 'error', 258 // FIXME(knazarov) 259 // need to change metadata in cookbook accordingly. so do it later 260 '@typescript-eslint/naming-convention': [ 261 'off', 262 { 263 selector: 'default', 264 format: ['camelCase'] 265 }, 266 { 267 selector: 'enumMember', 268 format: ['UPPER_CASE'] 269 }, 270 { 271 selector: 'variable', 272 format: ['camelCase', 'UPPER_CASE'] 273 }, 274 { 275 selector: 'typeLike', 276 format: ['PascalCase'] 277 }, 278 { 279 selector: 'memberLike', 280 format: ['camelCase'] 281 } 282 ] 283 } 284 } 285); 286