diff --git a/.eslintrc.js b/.eslintrc.js index 84843c4265..70736ee317 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -80,15 +80,19 @@ const config = { 'react', '@typescript-eslint', 'simple-import-sort', + 'sonarjs', 'import', 'unused-imports', 'unicorn', ], rules: { + 'array-callback-return': 'error', 'no-undef': 'off', 'no-empty': 'off', 'no-func-assign': 'off', 'no-cond-assign': 'off', + 'no-constant-binary-expression': 'error', + 'no-constructor-return': 'error', 'react/prop-types': 'off', '@typescript-eslint/consistent-type-imports': 'error', '@typescript-eslint/no-non-null-assertion': 'error', @@ -138,6 +142,21 @@ const config = { ignore: ['^\\[[a-zA-Z0-9-_]+\\]\\.tsx$'], }, ], + 'sonarjs/no-all-duplicated-branches': 'error', + 'sonarjs/no-element-overwrite': 'error', + 'sonarjs/no-empty-collection': 'error', + 'sonarjs/no-extra-arguments': 'error', + 'sonarjs/no-identical-conditions': 'error', + 'sonarjs/no-identical-expressions': 'error', + 'sonarjs/no-ignored-return': 'error', + 'sonarjs/no-one-iteration-loop': 'error', + 'sonarjs/no-use-of-empty-return-value': 'error', + 'sonarjs/non-existent-operator': 'error', + 'sonarjs/no-collapsible-if': 'error', + 'sonarjs/no-same-line-conditional': 'error', + 'sonarjs/no-duplicated-branches': 'error', + 'sonarjs/no-collection-size-mischeck': 'error', + 'sonarjs/no-useless-catch': 'error', }, overrides: [ { diff --git a/apps/web/src/components/page-detail-editor.tsx b/apps/web/src/components/page-detail-editor.tsx index 4d39c456d2..b37f761b6c 100644 --- a/apps/web/src/components/page-detail-editor.tsx +++ b/apps/web/src/components/page-detail-editor.tsx @@ -109,7 +109,7 @@ const EditorWrapper = memo(function EditorWrapper({ ); const disposes = uiDecorators.map(ui => ui(editor)); return () => { - disposes.map(fn => fn()); + disposes.forEach(fn => fn()); dispose(); }; }, diff --git a/apps/web/src/components/workspace-header.tsx b/apps/web/src/components/workspace-header.tsx index 660e4a4614..952e3b36cd 100644 --- a/apps/web/src/components/workspace-header.tsx +++ b/apps/web/src/components/workspace-header.tsx @@ -80,15 +80,10 @@ export function WorkspaceHeader({ {t['Workspace Settings']()} ); - } else if (currentEntry.subPath === WorkspaceSubPath.SHARED) { - return ( - - ); - } else if (currentEntry.subPath === WorkspaceSubPath.TRASH) { + } else if ( + currentEntry.subPath === WorkspaceSubPath.SHARED || + currentEntry.subPath === WorkspaceSubPath.TRASH + ) { return ( { return helper.deleteWorkspace(workspaceId); }, [currentWorkspace, helper]); const onTransformWorkspace = useOnTransformWorkspace(); - if (!router.isReady) { - return ; - } else if (currentWorkspace === null) { - return ; - } else if (settingPanelValues.indexOf(currentTab as SettingPanel) === -1) { + if ( + !router.isReady || + currentWorkspace === null || + settingPanelValues.indexOf(currentTab as SettingPanel) === -1 + ) { return ; } const { SettingsDetail, Header } = getUIAdapter(currentWorkspace.flavour); diff --git a/apps/web/src/pages/workspace/[workspaceId]/trash.tsx b/apps/web/src/pages/workspace/[workspaceId]/trash.tsx index f1d472af7b..7a1391dc5d 100644 --- a/apps/web/src/pages/workspace/[workspaceId]/trash.tsx +++ b/apps/web/src/pages/workspace/[workspaceId]/trash.tsx @@ -31,9 +31,7 @@ const TrashPage: NextPageWithLayout = () => { }, [currentWorkspace, jumpToPage] ); - if (!router.isReady) { - return ; - } else if (currentWorkspace === null) { + if (!router.isReady || currentWorkspace === null) { return ; } // todo(himself65): refactor to plugin diff --git a/package.json b/package.json index 81adc61ad5..0f65d8fdd0 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-simple-import-sort": "^10.0.0", + "eslint-plugin-sonarjs": "^0.19.0", "eslint-plugin-unicorn": "^47.0.0", "eslint-plugin-unused-imports": "^2.0.0", "fake-indexeddb": "4.0.1", diff --git a/packages/workspace/src/affine/login.ts b/packages/workspace/src/affine/login.ts index 9b85c1efc3..fddb6cde4d 100644 --- a/packages/workspace/src/affine/login.ts +++ b/packages/workspace/src/affine/login.ts @@ -207,10 +207,12 @@ export function createAffineAuth(prefix = '/') { }), }).then(r => r.json()) as Promise; } catch (error) { - if (error instanceof Error && 'code' in error) { - if (error.code === 'auth/popup-closed-by-user') { - return null; - } + if ( + error instanceof Error && + 'code' in error && + error.code === 'auth/popup-closed-by-user' + ) { + return null; } logger.error('Failed to sign in', error); } diff --git a/yarn.lock b/yarn.lock index add4ab6e56..9299f6da85 100644 --- a/yarn.lock +++ b/yarn.lock @@ -296,6 +296,7 @@ __metadata: eslint-plugin-react: ^7.32.2 eslint-plugin-react-hooks: ^4.6.0 eslint-plugin-simple-import-sort: ^10.0.0 + eslint-plugin-sonarjs: ^0.19.0 eslint-plugin-unicorn: ^47.0.0 eslint-plugin-unused-imports: ^2.0.0 fake-indexeddb: 4.0.1 @@ -15275,6 +15276,15 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-sonarjs@npm:^0.19.0": + version: 0.19.0 + resolution: "eslint-plugin-sonarjs@npm:0.19.0" + peerDependencies: + eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: 893640583f62ce55584c6ddd481aa0fd6fa15fe0fffc32ac92b17f3fadde8eaf32414183bb80b612455212e9bb14400236398af6279ca04e8992f008e011926c + languageName: node + linkType: hard + "eslint-plugin-unicorn@npm:^47.0.0": version: 47.0.0 resolution: "eslint-plugin-unicorn@npm:47.0.0"