diff --git a/CHANGELOG.md b/CHANGELOG.md index a407930..133b3dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Update Docker Compose configuration file to V2 +- [#44](https://github.com/green-code-initiative/ecoCode-javascript/pull/44) Implement the rule EC523 for React Native + +### Deleted + +- [#44](https://github.com/green-code-initiative/ecoCode-javascript/pull/44) Merge the rule EC8 with EC523 ## [1.5.0] - 2024-03-13 diff --git a/eslint-plugin/docs/rules/avoid-high-accuracy-geolocation.md b/eslint-plugin/docs/rules/avoid-high-accuracy-geolocation.md index fea7b49..49e4072 100644 --- a/eslint-plugin/docs/rules/avoid-high-accuracy-geolocation.md +++ b/eslint-plugin/docs/rules/avoid-high-accuracy-geolocation.md @@ -15,6 +15,7 @@ usage. If the application or service does not critically require pinpoint accuracy, opting for a less accurate geolocation can help minimize the strain on the device's CPU. +## Web ```js var options = { enableHighAccuracy: true, timeout: 5000, maximumAge: 0 }; // Non-compliant navigator.geolocation.getCurrentPosition( @@ -40,6 +41,21 @@ navigator.geolocation.getCurrentPosition( ); ``` +## React Native +In this example, we ask the user to turn on high accuracy location mode which enables network provider that uses Google Play services to improve location accuracy and location-based services: +```js +import * as Location from 'expo-location'; + +Location.enableNetworkProviderAsync(); // Non-compliant +``` + +Prefer to ask the user to turn on lower-accuracy geolocation to conserve resources: +```js +import * as Location from 'expo-location'; + +Location.requestPermissionsAsync(); // Compliant +``` + ## Resources ### Documentation diff --git a/eslint-plugin/lib/rules/avoid-high-accuracy-geolocation.js b/eslint-plugin/lib/rules/avoid-high-accuracy-geolocation.js index 3f70b2d..341fe59 100644 --- a/eslint-plugin/lib/rules/avoid-high-accuracy-geolocation.js +++ b/eslint-plugin/lib/rules/avoid-high-accuracy-geolocation.js @@ -18,6 +18,10 @@ "use strict"; +const geolocationLibrariesMethods = { + "expo-location": ["enableNetworkProviderAsync"], +}; + /** @type {import("eslint").Rule.RuleModule} */ module.exports = { meta: { @@ -33,15 +37,41 @@ module.exports = { schema: [], }, create: function (context) { + const librariesFoundInImports = []; + return { + ImportDeclaration(node) { + const currentLibrary = node.source.value; + + if (geolocationLibrariesMethods[currentLibrary]) { + librariesFoundInImports.push(currentLibrary); + } + }, + MemberExpression(node) { + if (librariesFoundInImports.length === 0) { + return; + } + + if ( + librariesFoundInImports.some((library) => + geolocationLibrariesMethods[library].includes(node.property.name), + ) + ) { + reportAvoidUsingAccurateGeolocation(context, node); + } + }, Property(node) { if ( node?.key.name === "enableHighAccuracy" && node?.value.value === true ) { - context.report({ node, messageId: "AvoidUsingAccurateGeolocation" }); + reportAvoidUsingAccurateGeolocation(context, node); } }, }; }, }; + +function reportAvoidUsingAccurateGeolocation(context, node) { + context.report({ node, messageId: "AvoidUsingAccurateGeolocation" }); +} diff --git a/eslint-plugin/tests/lib/rules/avoid-high-accuracy-geolocation.js b/eslint-plugin/tests/lib/rules/avoid-high-accuracy-geolocation.js index 09e0077..a08b154 100644 --- a/eslint-plugin/tests/lib/rules/avoid-high-accuracy-geolocation.js +++ b/eslint-plugin/tests/lib/rules/avoid-high-accuracy-geolocation.js @@ -29,11 +29,20 @@ const RuleTester = require("eslint").RuleTester; // Tests //------------------------------------------------------------------------------ -const ruleTester = new RuleTester(); -const expectedError = { +const ruleTester = new RuleTester({ + parserOptions: { + ecmaVersion: 6, + sourceType: "module", + }, +}); +const expectedErrorOnProperty = { messageId: "AvoidUsingAccurateGeolocation", type: "Property", }; +const expectedErrorOnMemberExpression = { + messageId: "AvoidUsingAccurateGeolocation", + type: "MemberExpression", +}; ruleTester.run("avoid-high-accuracy-geolocation", rule, { valid: [ @@ -60,6 +69,15 @@ ruleTester.run("avoid-high-accuracy-geolocation", rule, { ` navigator.geolocation.getCurrentPosition(success, error, {enableHighAccuracy: false}); `, + + ` + import axios from 'axios'; + `, + ` + import * as Location from 'expo-location'; + + Location.requestPermissionsAsync(); + `, ], invalid: [ @@ -77,13 +95,21 @@ ruleTester.run("avoid-high-accuracy-geolocation", rule, { navigator.geolocation.getCurrentPosition(success, error, options); `, - errors: [expectedError], + errors: [expectedErrorOnProperty], }, { code: ` navigator.geolocation.getCurrentPosition(success, error, {enableHighAccuracy: true}); `, - errors: [expectedError], + errors: [expectedErrorOnProperty], + }, + { + code: ` + import * as Location from 'expo-location'; + + Location.enableNetworkProviderAsync(); + `, + errors: [expectedErrorOnMemberExpression], }, ], }); diff --git a/sonar-plugin/pom.xml b/sonar-plugin/pom.xml index 676913f..9dc55de 100644 --- a/sonar-plugin/pom.xml +++ b/sonar-plugin/pom.xml @@ -49,7 +49,7 @@ ${encoding} ${encoding} - 1.5.0 + 1.6.0 9.4.0.54424 9.13.0.20537 1.23.0.740 diff --git a/sonar-plugin/src/main/java/io/ecocode/javascript/checks/AvoidHighAccuracyGeolocation.java b/sonar-plugin/src/main/java/io/ecocode/javascript/checks/AvoidHighAccuracyGeolocation.java index ef76f24..1ae7485 100644 --- a/sonar-plugin/src/main/java/io/ecocode/javascript/checks/AvoidHighAccuracyGeolocation.java +++ b/sonar-plugin/src/main/java/io/ecocode/javascript/checks/AvoidHighAccuracyGeolocation.java @@ -21,13 +21,15 @@ import org.sonar.plugins.javascript.api.EslintBasedCheck; import org.sonar.plugins.javascript.api.JavaScriptRule; import org.sonar.plugins.javascript.api.TypeScriptRule; +import org.sonarsource.analyzer.commons.annotations.DeprecatedRuleKey; @JavaScriptRule @TypeScriptRule @Rule(key = AvoidHighAccuracyGeolocation.RULE_KEY) +@DeprecatedRuleKey(repositoryKey = "ecocode-javascript", ruleKey = "EC8") public class AvoidHighAccuracyGeolocation implements EslintBasedCheck { - public static final String RULE_KEY = "EC8"; + public static final String RULE_KEY = "EC523"; @Override public String eslintKey() { diff --git a/sonar-plugin/src/main/resources/io/ecocode/profiles/ecocode_javascript_profile.json b/sonar-plugin/src/main/resources/io/ecocode/profiles/ecocode_javascript_profile.json index 2e3da99..81e71c1 100644 --- a/sonar-plugin/src/main/resources/io/ecocode/profiles/ecocode_javascript_profile.json +++ b/sonar-plugin/src/main/resources/io/ecocode/profiles/ecocode_javascript_profile.json @@ -1,7 +1,6 @@ { "name": "ecoCode", "ruleKeys": [ - "EC8", "EC9", "EC11", "EC12", @@ -9,6 +8,7 @@ "EC25", "EC26", "EC29", - "EC30" + "EC30", + "EC523" ] }