From 353cc9dedc65086a8d98d3d27e7cff6b746da033 Mon Sep 17 00:00:00 2001 From: silverwind Date: Thu, 21 Jul 2022 05:52:20 +0200 Subject: [PATCH 1/3] Add eslint-plugin-sonarjs We had this plugin before but it was removed as it became outdated, now it was updated again, so it's compatible again. --- .eslintrc.yaml | 33 +++++++++++++++++++++++++++++++ package-lock.json | 20 +++++++++++++++++++ package.json | 1 + web_src/js/features/codeeditor.js | 18 ++++++++--------- web_src/js/features/stopwatch.js | 4 ++-- web_src/js/utils.js | 2 +- 6 files changed, 66 insertions(+), 12 deletions(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 90bb3c9c5eba..3324a1256ba8 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -12,6 +12,7 @@ plugins: - eslint-plugin-unicorn - eslint-plugin-import - eslint-plugin-jquery + - eslint-plugin-sonarjs env: es2022: true @@ -369,6 +370,38 @@ rules: semi-spacing: [2, {before: false, after: true}] semi-style: [2, last] semi: [2, always, {omitLastInOneLineBlock: true}] + sonarjs/cognitive-complexity: [0] + sonarjs/elseif-without-else: [0] + sonarjs/max-switch-cases: [0] + sonarjs/no-all-duplicated-branches: [2] + sonarjs/no-collapsible-if: [0] + sonarjs/no-collection-size-mischeck: [2] + sonarjs/no-duplicate-string: [0] + sonarjs/no-duplicated-branches: [0] + sonarjs/no-element-overwrite: [2] + sonarjs/no-empty-collection: [2] + sonarjs/no-extra-arguments: [0] + sonarjs/no-gratuitous-expressions: [2] + sonarjs/no-identical-conditions: [2] + sonarjs/no-identical-expressions: [0] + sonarjs/no-identical-functions: [0] + sonarjs/no-ignored-return: [2] + sonarjs/no-inverted-boolean-check: [2] + sonarjs/no-nested-switch: [0] + sonarjs/no-nested-template-literals: [0] + sonarjs/no-one-iteration-loop: [2] + sonarjs/no-redundant-boolean: [2] + sonarjs/no-redundant-jump: [0] + sonarjs/no-same-line-conditional: [2] + sonarjs/no-small-switch: [0] + sonarjs/no-unused-collection: [2] + sonarjs/no-use-of-empty-return-value: [2] + sonarjs/no-useless-catch: [0] + sonarjs/non-existent-operator: [2] + sonarjs/prefer-immediate-return: [0] + sonarjs/prefer-object-literal: [2] + sonarjs/prefer-single-boolean-return: [0] + sonarjs/prefer-while: [2] sort-imports: [0] sort-keys: [0] sort-vars: [0] diff --git a/package-lock.json b/package-lock.json index d2aa3dbe1b2e..cfd2a6ad2a01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,6 +50,7 @@ "eslint": "8.20.0", "eslint-plugin-import": "2.26.0", "eslint-plugin-jquery": "1.5.1", + "eslint-plugin-sonarjs": "0.13.0", "eslint-plugin-unicorn": "43.0.2", "eslint-plugin-vue": "9.2.0", "jest": "28.1.3", @@ -5492,6 +5493,18 @@ "eslint": ">=5.4.0" } }, + "node_modules/eslint-plugin-sonarjs": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.13.0.tgz", + "integrity": "sha512-t3m7ta0EspzDxSOZh3cEOJIJVZgN/TlJYaBGnQlK6W/PZNbWep8q4RQskkJkA7/zwNpX0BaoEOSUUrqaADVoqA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/eslint-plugin-unicorn": { "version": "43.0.2", "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-43.0.2.tgz", @@ -16787,6 +16800,13 @@ "dev": true, "requires": {} }, + "eslint-plugin-sonarjs": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.13.0.tgz", + "integrity": "sha512-t3m7ta0EspzDxSOZh3cEOJIJVZgN/TlJYaBGnQlK6W/PZNbWep8q4RQskkJkA7/zwNpX0BaoEOSUUrqaADVoqA==", + "dev": true, + "requires": {} + }, "eslint-plugin-unicorn": { "version": "43.0.2", "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-43.0.2.tgz", diff --git a/package.json b/package.json index c1ecd163432a..f4752aeec95f 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "eslint": "8.20.0", "eslint-plugin-import": "2.26.0", "eslint-plugin-jquery": "1.5.1", + "eslint-plugin-sonarjs": "0.13.0", "eslint-plugin-unicorn": "43.0.2", "eslint-plugin-vue": "9.2.0", "jest": "28.1.3", diff --git a/web_src/js/features/codeeditor.js b/web_src/js/features/codeeditor.js index a22043c9d482..d8df1209c166 100644 --- a/web_src/js/features/codeeditor.js +++ b/web_src/js/features/codeeditor.js @@ -164,13 +164,13 @@ export async function createCodeEditor(textarea, filenameInput, previewFileModes function getEditorConfigOptions(ec) { if (!isObject(ec)) return {}; - const opts = {}; - opts.detectIndentation = !('indent_style' in ec) || !('indent_size' in ec); - if ('indent_size' in ec) opts.indentSize = Number(ec.indent_size); - if ('tab_width' in ec) opts.tabSize = Number(ec.tab_width) || opts.indentSize; - if ('max_line_length' in ec) opts.rulers = [Number(ec.max_line_length)]; - opts.trimAutoWhitespace = ec.trim_trailing_whitespace === true; - opts.insertSpaces = ec.indent_style === 'space'; - opts.useTabStops = ec.indent_style === 'tab'; - return opts; + return { + detectIndentation: !('indent_style' in ec) || !('indent_size' in ec), + trimAutoWhitespace: ec.trim_trailing_whitespace === true, + insertSpaces: ec.indent_style === 'space', + useTabStops: ec.indent_style === 'tab', + ...('indent_size' in ec && {indentSize: Number(ec.indent_size)}), + ...('tab_width' in ec && {tabSize: Number(ec.tab_width) || Number(ec.indent_size)}), + ...('max_line_length' in ec && {rulers: [Number(ec.max_line_length)]}), + }; } diff --git a/web_src/js/features/stopwatch.js b/web_src/js/features/stopwatch.js index c47ba221241b..5990f86d709a 100644 --- a/web_src/js/features/stopwatch.js +++ b/web_src/js/features/stopwatch.js @@ -140,7 +140,7 @@ function updateStopwatchData(data) { $('.stopwatch-cancel').attr('action', `${issueUrl}/times/stopwatch/cancel`); $('.stopwatch-issue').text(`${repo_owner_name}/${repo_name}#${issue_index}`); $('.stopwatch-time').text(prettyMilliseconds(seconds * 1000)); - updateStopwatchTime(seconds); + updateTimeInterval = updateStopwatchTime(seconds); btnEl.removeClass('hidden'); } @@ -152,7 +152,7 @@ function updateStopwatchTime(seconds) { if (!Number.isFinite(secs)) return; const start = Date.now(); - updateTimeInterval = setInterval(() => { + return setInterval(() => { const delta = Date.now() - start; const dur = prettyMilliseconds(secs * 1000 + delta, {compact: true}); $('.stopwatch-time').text(dur); diff --git a/web_src/js/utils.js b/web_src/js/utils.js index f01f2d3b2244..e9cd39032df8 100644 --- a/web_src/js/utils.js +++ b/web_src/js/utils.js @@ -64,7 +64,7 @@ export function parseIssueHref(href) { export function strSubMatch(full, sub) { const res = ['']; let i = 0, j = 0; - for (; i < sub.length && j < full.length;) { + while (i < sub.length && j < full.length) { while (j < full.length) { if (sub[i] === full[j]) { if (res.length % 2 !== 0) res.push(''); From ed818674e5889ce812f1089904bdbcad858f1737 Mon Sep 17 00:00:00 2001 From: silverwind Date: Thu, 21 Jul 2022 07:48:27 +0200 Subject: [PATCH 2/3] Update web_src/js/features/stopwatch.js --- web_src/js/features/stopwatch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_src/js/features/stopwatch.js b/web_src/js/features/stopwatch.js index 5990f86d709a..d63da4155af2 100644 --- a/web_src/js/features/stopwatch.js +++ b/web_src/js/features/stopwatch.js @@ -149,7 +149,7 @@ function updateStopwatchData(data) { function updateStopwatchTime(seconds) { const secs = parseInt(seconds); - if (!Number.isFinite(secs)) return; + if (!Number.isFinite(secs)) return null; const start = Date.now(); return setInterval(() => { From 0de22398dcf42d115aa8fbe011f219349433ed6e Mon Sep 17 00:00:00 2001 From: silverwind Date: Thu, 21 Jul 2022 18:59:51 +0200 Subject: [PATCH 3/3] revert and disable sonarjs/prefer-object-literal rule --- .eslintrc.yaml | 2 +- web_src/js/features/codeeditor.js | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 3324a1256ba8..86f886b4b4d5 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -399,7 +399,7 @@ rules: sonarjs/no-useless-catch: [0] sonarjs/non-existent-operator: [2] sonarjs/prefer-immediate-return: [0] - sonarjs/prefer-object-literal: [2] + sonarjs/prefer-object-literal: [0] sonarjs/prefer-single-boolean-return: [0] sonarjs/prefer-while: [2] sort-imports: [0] diff --git a/web_src/js/features/codeeditor.js b/web_src/js/features/codeeditor.js index d8df1209c166..a22043c9d482 100644 --- a/web_src/js/features/codeeditor.js +++ b/web_src/js/features/codeeditor.js @@ -164,13 +164,13 @@ export async function createCodeEditor(textarea, filenameInput, previewFileModes function getEditorConfigOptions(ec) { if (!isObject(ec)) return {}; - return { - detectIndentation: !('indent_style' in ec) || !('indent_size' in ec), - trimAutoWhitespace: ec.trim_trailing_whitespace === true, - insertSpaces: ec.indent_style === 'space', - useTabStops: ec.indent_style === 'tab', - ...('indent_size' in ec && {indentSize: Number(ec.indent_size)}), - ...('tab_width' in ec && {tabSize: Number(ec.tab_width) || Number(ec.indent_size)}), - ...('max_line_length' in ec && {rulers: [Number(ec.max_line_length)]}), - }; + const opts = {}; + opts.detectIndentation = !('indent_style' in ec) || !('indent_size' in ec); + if ('indent_size' in ec) opts.indentSize = Number(ec.indent_size); + if ('tab_width' in ec) opts.tabSize = Number(ec.tab_width) || opts.indentSize; + if ('max_line_length' in ec) opts.rulers = [Number(ec.max_line_length)]; + opts.trimAutoWhitespace = ec.trim_trailing_whitespace === true; + opts.insertSpaces = ec.indent_style === 'space'; + opts.useTabStops = ec.indent_style === 'tab'; + return opts; }