")) {
+ if (isImpactMethodCalled) {
+ this.recordIssue(id.getStart().getStartIndex(), DEFAULT_ISSUE_MESSAGE);
+ }
+ isUIKitImported = false;
+ isFeedbackGeneratorInstantiated = false;
+ isImpactMethodCalled = false;
+ }
+ }
+}
+
diff --git a/swift-lang/src/main/java/io/ecocode/ios/swift/checks/sobriety/LocationLeakCheck.java b/swift-lang/src/main/java/io/ecocode/ios/swift/checks/sobriety/LocationLeakCheck.java
index 9d2243a..6cf1e83 100644
--- a/swift-lang/src/main/java/io/ecocode/ios/swift/checks/sobriety/LocationLeakCheck.java
+++ b/swift-lang/src/main/java/io/ecocode/ios/swift/checks/sobriety/LocationLeakCheck.java
@@ -34,7 +34,6 @@ public class LocationLeakCheck extends SwiftRuleCheck {
@Override
public void apply(ParseTree tree) {
-
if (tree instanceof Swift5Parser.ExpressionContext && (tree.getText().contains(".startUpdatingLocation()"))) {
firstCallExist = true;
id = (Swift5Parser.ExpressionContext) tree;
diff --git a/swift-lang/src/main/resources/ecocode_swift_profile.json b/swift-lang/src/main/resources/ecocode_swift_profile.json
index ef3480d..4464de3 100644
--- a/swift-lang/src/main/resources/ecocode_swift_profile.json
+++ b/swift-lang/src/main/resources/ecocode_swift_profile.json
@@ -11,6 +11,7 @@
"EC520",
"EC522",
"EC524",
+ "EC528",
"EC530",
"EC533",
"EC534",
diff --git a/swift-lang/src/main/resources/io/ecocode/rules/swift/EC528.html b/swift-lang/src/main/resources/io/ecocode/rules/swift/EC528.html
new file mode 100644
index 0000000..ad329b6
--- /dev/null
+++ b/swift-lang/src/main/resources/io/ecocode/rules/swift/EC528.html
@@ -0,0 +1,14 @@
+
+ Shaking or vibrating an iOS device is possible using UIFeedbackGenerator.
+ Behind this effect stands a specific hardware component, the Taptic Engine, which consumes power.
+ As a consequence, its usage should be carefully considered, especially if its added value is not clear.
+
Noncompliant Code Example
+
+
+ import UIKit
+
+ func triggerVibration() {
+ let generator = UIImpactFeedbackGenerator(style: .heavy)
+ generator.impactOccurred()
+ }
+
\ No newline at end of file
diff --git a/swift-lang/src/main/resources/io/ecocode/rules/swift/EC528.json b/swift-lang/src/main/resources/io/ecocode/rules/swift/EC528.json
new file mode 100644
index 0000000..d527290
--- /dev/null
+++ b/swift-lang/src/main/resources/io/ecocode/rules/swift/EC528.json
@@ -0,0 +1,18 @@
+{
+ "key": "EC528",
+ "title": "Sobriety: Vibration Free",
+ "defaultSeverity": "Major",
+ "description": "Avoid using the device vibrator to use less energy.",
+ "status": "ready",
+ "remediation": {
+ "func": "Constant/Issue",
+ "constantCost": "5min"
+ },
+ "tags": [
+ "ecocode",
+ "environment",
+ "sobriety",
+ "eco-design"
+ ],
+ "type": "CODE_SMELL"
+}
\ No newline at end of file
diff --git a/swift-lang/src/test/java/io/ecocode/ios/swift/EcoCodeSwiftRulesDefinitionTest.java b/swift-lang/src/test/java/io/ecocode/ios/swift/EcoCodeSwiftRulesDefinitionTest.java
index 8e3f299..89cea99 100644
--- a/swift-lang/src/test/java/io/ecocode/ios/swift/EcoCodeSwiftRulesDefinitionTest.java
+++ b/swift-lang/src/test/java/io/ecocode/ios/swift/EcoCodeSwiftRulesDefinitionTest.java
@@ -55,7 +55,7 @@ public void testMetadata() {
@Test
public void testRegisteredRules() {
- assertThat(repository.rules()).hasSize(14);
+ assertThat(repository.rules()).hasSize(15);
}
@Test
diff --git a/swift-lang/src/test/java/io/ecocode/ios/swift/checks/sobriety/FeedbackGeneratorUsageCheckTest.java b/swift-lang/src/test/java/io/ecocode/ios/swift/checks/sobriety/FeedbackGeneratorUsageCheckTest.java
new file mode 100644
index 0000000..bd0e70b
--- /dev/null
+++ b/swift-lang/src/test/java/io/ecocode/ios/swift/checks/sobriety/FeedbackGeneratorUsageCheckTest.java
@@ -0,0 +1,57 @@
+/*
+ * ecoCode iOS plugin - Help the earth, adopt this green plugin for your applications
+ * Copyright © 2023 green-code-initiative (https://www.ecocode.io/)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package io.ecocode.ios.swift.checks.sobriety;
+
+import io.ecocode.ios.swift.checks.CheckTestHelper;
+import org.assertj.core.api.ObjectAssert;
+import org.junit.Test;
+import org.sonar.api.batch.fs.TextPointer;
+import org.sonar.api.batch.fs.TextRange;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
+import org.sonar.api.batch.sensor.issue.Issue;
+import org.sonar.api.batch.sensor.issue.IssueLocation;
+import org.sonar.api.rule.RuleKey;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FeedbackGeneratorUsageCheckTest {
+
+ private static final String TEST_CASE_FEEDBACK_GENERATOR_USE = "checks/sobriety/FeedbackGeneratorUsageCheck_abusive_use_trigger.swift";
+ private static final String TEST_CASE_COMPLIANT = "checks/sobriety/FeedbackGeneratorUsage_compliant_no_trigger.swift";
+ @Test
+ public void feedbackGeneratorUsageCheck_usage_trigger(){
+ SensorContextTester context = CheckTestHelper.analyzeTestFile(TEST_CASE_FEEDBACK_GENERATOR_USE);
+ ObjectAssert issue = assertThat(context.allIssues()).hasSize(1)
+ .first();
+ issue.extracting(Issue::ruleKey).extracting(RuleKey::rule).isEqualTo("EC528");
+ issue.extracting(Issue::ruleKey).extracting(RuleKey::repository)
+ .isEqualTo("ecoCode-swift");
+ issue.extracting(Issue::primaryLocation)
+ .extracting(IssueLocation::textRange)
+ .extracting(TextRange::start)
+ .extracting(TextPointer::line)
+ .isEqualTo(5);
+ }
+
+ @Test
+ public void locationLeakCheck_compliant_no_trigger(){
+ SensorContextTester context = CheckTestHelper.analyzeTestFile(TEST_CASE_COMPLIANT);
+ assertThat(context.allIssues()).isEmpty();
+ }
+}
diff --git a/swift-lang/src/test/resources/checks/sobriety/FeedbackGeneratorUsageCheck_abusive_use_trigger.swift b/swift-lang/src/test/resources/checks/sobriety/FeedbackGeneratorUsageCheck_abusive_use_trigger.swift
new file mode 100644
index 0000000..e05a04d
--- /dev/null
+++ b/swift-lang/src/test/resources/checks/sobriety/FeedbackGeneratorUsageCheck_abusive_use_trigger.swift
@@ -0,0 +1,6 @@
+import UIKit
+
+func triggerVibration() {
+ let generator = UIImpactFeedbackGenerator(style: .heavy)
+ generator.impactOccurred()
+}
\ No newline at end of file
diff --git a/swift-lang/src/test/resources/checks/sobriety/FeedbackGeneratorUsage_compliant_no_trigger.swift b/swift-lang/src/test/resources/checks/sobriety/FeedbackGeneratorUsage_compliant_no_trigger.swift
new file mode 100644
index 0000000..2e54bf5
--- /dev/null
+++ b/swift-lang/src/test/resources/checks/sobriety/FeedbackGeneratorUsage_compliant_no_trigger.swift
@@ -0,0 +1,5 @@
+import UIKit
+
+func hello() {
+ print("Hello, world!")
+}
\ No newline at end of file