From 1bab09e42a205cb0da1f57aac0425bc592c0e538 Mon Sep 17 00:00:00 2001 From: yassin-kammoun-sonarsource Date: Mon, 13 Nov 2023 14:18:02 +0100 Subject: [PATCH] Create rule S6846 (`jsx-a11y/no-access-key`): DOM elements should not use the `accesskey` property --- .../jsts/file-for-rules/javascript-S1451.json | 5 ++- .../jsts/file-for-rules/javascript-S3798.json | 5 ++- .../jsts/file-for-rules/javascript-S6747.json | 3 ++ .../jsts/file-for-rules/javascript-S6846.json | 5 +++ its/sources/jsts/custom/S6846.js | 3 ++ package-lock.json | 3 ++ .../sonar/javascript/checks/CheckList.java | 1 + .../javascript/checks/NoAccessKeyCheck.java | 36 +++++++++++++++++ .../javascript/rules/javascript/S6846.html | 40 +++++++++++++++++++ .../javascript/rules/javascript/S6846.json | 29 ++++++++++++++ .../rules/javascript/Sonar_way_profile.json | 3 +- 11 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6846.json create mode 100644 its/sources/jsts/custom/S6846.js create mode 100644 sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/NoAccessKeyCheck.java create mode 100644 sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6846.html create mode 100644 sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6846.json diff --git a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S1451.json b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S1451.json index ea89a44c7f9..afc35d91e74 100644 --- a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S1451.json +++ b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S1451.json @@ -192,11 +192,14 @@ 0 ], "file-for-rules:S6840.js": [ - 0 +0 ], "file-for-rules:S6843.js": [ 0 ], +"file-for-rules:S6846.js": [ +0 +], "file-for-rules:boundOrAssignedEvalOrArguments.js": [ 0 ] diff --git a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S3798.json b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S3798.json index 7551f330047..859827b469f 100644 --- a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S3798.json +++ b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S3798.json @@ -66,11 +66,14 @@ 2 ], "file-for-rules:S6840.js": [ - 1 +1 ], "file-for-rules:S6843.js": [ 1 ], +"file-for-rules:S6846.js": [ +1 +], "file-for-rules:boundOrAssignedEvalOrArguments.js": [ 2, 8 diff --git a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6747.json b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6747.json index 560b760fe93..7f17219c5eb 100644 --- a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6747.json +++ b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6747.json @@ -1,5 +1,8 @@ { "file-for-rules:S6840.js": [ 2 +], +"file-for-rules:S6846.js": [ +2 ] } diff --git a/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6846.json b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6846.json new file mode 100644 index 00000000000..233f0994ccf --- /dev/null +++ b/its/ruling/src/test/expected/jsts/file-for-rules/javascript-S6846.json @@ -0,0 +1,5 @@ +{ +"file-for-rules:S6846.js": [ +2 +] +} diff --git a/its/sources/jsts/custom/S6846.js b/its/sources/jsts/custom/S6846.js new file mode 100644 index 00000000000..69e27e3a91e --- /dev/null +++ b/its/sources/jsts/custom/S6846.js @@ -0,0 +1,3 @@ +function div() { + return
; +} diff --git a/package-lock.json b/package-lock.json index ef304280621..ed779fff14f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "htmlparser2", "jsx-ast-utils", "lodash.clone", + "minimatch", "module-alias", "postcss", "postcss-html", @@ -4153,6 +4154,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "inBundle": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -9332,6 +9334,7 @@ "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "inBundle": true, "dependencies": { "brace-expansion": "^2.0.1" }, diff --git a/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/CheckList.java b/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/CheckList.java index ebc4d2d81eb..476638c35f3 100644 --- a/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/CheckList.java +++ b/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/CheckList.java @@ -233,6 +233,7 @@ public static List> getAllChecks() { NestedControlFlowDepthCheck.class, NewCapCheck.class, NewOperatorMisuseCheck.class, + NoAccessKeyCheck.class, NoAccessStateInSetstateCheck.class, NoAccessorFieldMismatchCheck.class, NoAngularBypassSanitizationCheck.class, diff --git a/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/NoAccessKeyCheck.java b/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/NoAccessKeyCheck.java new file mode 100644 index 00000000000..677e9c09478 --- /dev/null +++ b/sonar-plugin/javascript-checks/src/main/java/org/sonar/javascript/checks/NoAccessKeyCheck.java @@ -0,0 +1,36 @@ +/** + * SonarQube JavaScript Plugin + * Copyright (C) 2011-2023 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.javascript.checks; + +import org.sonar.check.Rule; +import org.sonar.plugins.javascript.api.EslintBasedCheck; +import org.sonar.plugins.javascript.api.JavaScriptRule; +import org.sonar.plugins.javascript.api.TypeScriptRule; + +@JavaScriptRule +@TypeScriptRule +@Rule(key = "S6846") +public class NoAccessKeyCheck implements EslintBasedCheck { + + @Override + public String eslintKey() { + return "no-access-key"; + } +} diff --git a/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6846.html b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6846.html new file mode 100644 index 00000000000..220275f2ace --- /dev/null +++ b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6846.html @@ -0,0 +1,40 @@ +

Why is this an issue?

+

The accesskey attribute, despite its potential utility, is fraught with numerous issues that limit its effectiveness and +usability:

+
    +
  • Screen readers' implementation of accesskey largely depends on the browser used, as they rely on browsers for much of their + functionality. Some screen readers may repeatedly indicate the accesskey value each time the element is encountered, potentially + causing unnecessary repetition and noise for the user.
  • +
  • Conflicts between accesskey shortcuts and other keyboard shortcuts, such as those of browsers, operating systems, assistive + technologies, or browser extensions, are frequent. This overlap can lead to uncertainty and potentially trigger unintended actions, causing user + confusion.
  • +
  • While keyboard shortcuts are vital for screen reader functionality, conflicts can disable either the screen reader or accesskey + shortcuts. Typically, screen reader shortcuts take precedence, disabling the accesskey but preserving screen reader functionality. + However, this can cause confusion for users attempting to activate an accesskey.
  • +
  • No keystroke combinations can guarantee zero conflicts with all browsers, assistive technologies, or operating systems, particularly + considering foreign languages. For instance, an accesskey shortcut that works in an English browser may conflict in the same browser + set in another language due to different menu naming conventions.
  • +
  • While using numerals instead of letters for keyboard shortcuts could reduce conflicts, it’s not a foolproof solution. There’s no standard + correlation between numbers and web functions, which could lead to user confusion.
  • +
  • Unlike the Windows environment that highlights keyboard shortcuts in menus, web pages or applications lack a standardized method to notify + users about available accesskey shortcuts.
  • +
+

Given these concerns, it is generally recommended to avoid using `accesskey`s.

+
+function div() {
+    return <div accessKey="h" />;
+}
+
+

Do not use `accesskey`s at all.

+
+function div() {
+    return <div />;
+}
+
+

Resources

+

Documentation

+ + diff --git a/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6846.json b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6846.json new file mode 100644 index 00000000000..27edb4d35e3 --- /dev/null +++ b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/S6846.json @@ -0,0 +1,29 @@ +{ + "title": "DOM elements should not use the \"accesskey\" property", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + "accessibility", + "react" + ], + "defaultSeverity": "Major", + "ruleSpecification": "RSPEC-6846", + "sqKey": "S6846", + "scope": "All", + "quickfix": "infeasible", + "code": { + "impacts": { + "MAINTAINABILITY": "LOW", + "RELIABILITY": "MEDIUM" + }, + "attribute": "CONVENTIONAL" + }, + "compatibleLanguages": [ + "JAVASCRIPT", + "TYPESCRIPT" + ] +} diff --git a/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/Sonar_way_profile.json b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/Sonar_way_profile.json index eadc549bd45..248fb0dfc39 100644 --- a/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/Sonar_way_profile.json +++ b/sonar-plugin/javascript-checks/src/main/resources/org/sonar/l10n/javascript/rules/javascript/Sonar_way_profile.json @@ -310,6 +310,7 @@ "S6840", "S6841", "S6842", - "S6843" + "S6843", + "S6846" ] }