diff --git a/.vscode/settings.json b/.vscode/settings.json index ec1aeb55e2ddc..3485628ed613e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,6 +4,9 @@ // When opening a file, `editor.tabSize` and `editor.insertSpaces` will NOT be detected based on the file contents. "editor.detectIndentation": false, "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, // When enabled, will trim trailing whitespace when you save a file. "files.trimTrailingWhitespace": true, "files.insertFinalNewline": true, @@ -45,6 +48,7 @@ }, "editor.rulers": [120], "eslint.workingDirectories": [{ "mode": "auto" }], // infer working directory based on .eslintrc/package.json location + "eslint.codeActionsOnSave.mode": "problems", "files.associations": { "**/package.json.hbs": "json", "**/*.json.hbs": "jsonc" diff --git a/change/@fluentui-eslint-plugin-e6e0684b-1ee7-4695-a151-9f716d78ab67.json b/change/@fluentui-eslint-plugin-e6e0684b-1ee7-4695-a151-9f716d78ab67.json new file mode 100644 index 0000000000000..cdb8acc2abc2f --- /dev/null +++ b/change/@fluentui-eslint-plugin-e6e0684b-1ee7-4695-a151-9f716d78ab67.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "enable autofixable import rules", + "packageName": "@fluentui/eslint-plugin", + "email": "martinhochel@microsoft.com", + "dependentChangeType": "none" +} diff --git a/packages/eslint-plugin/src/configs/react.js b/packages/eslint-plugin/src/configs/react.js index a8e0890b78d02..5d5368279598a 100644 --- a/packages/eslint-plugin/src/configs/react.js +++ b/packages/eslint-plugin/src/configs/react.js @@ -68,31 +68,11 @@ const config = { '**/*.scss.ts', ], rules: { - '@rnx-kit/no-export-all': ['error', { expand: 'external-only' }], - '@fluentui/no-global-react': 'error', - '@fluentui/max-len': [ - 'error', - { - ignorePatterns: [ - 'require(<.*?>)?\\(', - 'https?:\\/\\/', - '^(import|export) ', - '^\\s+( ({ @@ -115,14 +97,6 @@ const config = { message: `"${name}" refers to a DOM global. Did you mean to reference a local value instead?`, })), ], - '@fluentui/ban-imports': [ - 'error', - { - path: 'react', - names: ['useLayoutEffect'], - message: '`useLayoutEffect` causes a warning in SSR. Use `useIsomorphicLayoutEffect`', - }, - ], 'no-restricted-properties': [ 'error', { object: 'describe', property: 'only', message: 'describe.only should only be used during test development' }, @@ -138,53 +112,6 @@ const config = { 'prefer-const': 'error', 'prefer-arrow-callback': 'error', // tslint: no-function-expression radix: ['error', 'always'], - 'react/jsx-key': 'error', - 'react/jsx-no-bind': [ - 'error', - { - allowArrowFunctions: false, // tslint: jsx-no-lambda - allowFunctions: false, - allowBind: false, - ignoreDOMComponents: true, - ignoreRefs: true, - }, - ], - 'react/no-string-refs': 'error', - 'react/self-closing-comp': 'error', - 'react-hooks/exhaustive-deps': [ - 'error', - { - additionalHooks: 'useIsomorphicLayoutEffect', - }, - ], - 'react-hooks/rules-of-hooks': 'error', - - // airbnb or other config overrides (some temporary) - // TODO: determine which rules we want to enable, and make needed changes (separate PR) - 'arrow-body-style': 'off', - 'class-methods-use-this': 'off', - 'consistent-return': 'off', - 'default-case': 'off', - 'func-names': 'off', - 'global-require': 'off', - - 'jsx-a11y/alt-text': 'off', - 'jsx-a11y/anchor-is-valid': 'off', - 'jsx-a11y/aria-activedescendant-has-tabindex': 'off', - 'jsx-a11y/aria-role': 'off', - 'jsx-a11y/click-events-have-key-events': 'off', - 'jsx-a11y/control-has-associated-label': 'off', - 'jsx-a11y/role-has-required-aria-props': 'off', - 'jsx-a11y/interactive-supports-focus': 'off', - 'jsx-a11y/label-has-associated-control': 'off', - 'jsx-a11y/media-has-caption': 'off', - 'jsx-a11y/mouse-events-have-key-events': 'off', - 'jsx-a11y/no-interactive-element-to-noninteractive-role': 'off', - 'jsx-a11y/no-noninteractive-element-interactions': 'off', - 'jsx-a11y/no-noninteractive-tabindex': 'off', - 'jsx-a11y/no-redundant-roles': 'off', - 'jsx-a11y/no-static-element-interactions': 'off', - 'jsx-a11y/role-supports-aria-props': 'off', 'lines-between-class-members': 'off', 'max-classes-per-file': 'off', 'no-case-declarations': 'off', @@ -216,6 +143,93 @@ const config = { 'operator-assignment': 'off', 'prefer-destructuring': 'off', 'prefer-template': 'off', + // airbnb or other config overrides (some temporary) + // TODO: determine which rules we want to enable, and make needed changes (separate PR) + 'arrow-body-style': 'off', + 'class-methods-use-this': 'off', + 'consistent-return': 'off', + 'default-case': 'off', + 'func-names': 'off', + 'global-require': 'off', + 'spaced-comment': 'off', + // airbnb options ban for-of which is unnecessary for TS and modern node (https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/rules/style.js#L334) + // but this is a very powerful rule we may want to use in other ways + 'no-restricted-syntax': 'off', + // permanently disable because we disagree with these rules + 'no-await-in-loop': 'off', // contrary to rule docs, awaited things often are NOT parallelizable + // permanently disable due to performance issues (using custom rule `@fluentui/max-len` instead) + 'max-len': 'off', + // permanently disable due to perf problems and limited benefit + // see here for perf testing (note that you must run eslint directly) + // https://eslint.org/docs/developer-guide/working-with-rules#per-rule-performance + 'no-empty-character-class': 'off', + + /** + * + * `@typescript-eslint`plugin eslint rules + * @see https://github.com/typescript-eslint/typescript-eslint/tree/main/packages/eslint-plugin + */ + // tslint: function-name, variable-name + ...configHelpers.getNamingConventionRule(false), + '@typescript-eslint/no-empty-function': 'error', + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/prefer-namespace-keyword': 'error', + + /** + * + * `@rnx-kit` eslint rules + * @see https://github.com/microsoft/rnx-kit/tree/main/packages/eslint-plugin + */ + '@rnx-kit/no-export-all': ['error', { expand: 'external-only' }], + + /** + * + * `@fluentui` eslint rules / This package + * @see https://www.npmjs.com/package/@fluentui/eslint-plugin + */ + '@fluentui/ban-imports': [ + 'error', + { + path: 'react', + names: ['useLayoutEffect'], + message: '`useLayoutEffect` causes a warning in SSR. Use `useIsomorphicLayoutEffect`', + }, + ], + '@fluentui/no-global-react': 'error', + '@fluentui/max-len': [ + 'error', + { + ignorePatterns: [ + 'require(<.*?>)?\\(', + 'https?:\\/\\/', + '^(import|export) ', + '^\\s+(