From b879bc1f1d583875cbfea88a06aa0bbeced115d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Thu, 24 Aug 2023 16:17:50 +0200 Subject: [PATCH 1/2] feat(rules): add Swift rules from ecocode-ios --- .../src/main/assembly/swift.xml | 18 +++++++++++++++++ .../src/main/rules/EC14/EC14.json | 20 +++++++++++++++++++ .../src/main/rules/EC14/swift/EC14.asciidoc | 15 ++++++++++++++ .../src/main/rules/EC15/EC15.json | 20 +++++++++++++++++++ .../src/main/rules/EC15/swift/EC15.asciidoc | 19 ++++++++++++++++++ .../src/main/rules/EC16/EC16.json | 20 +++++++++++++++++++ .../src/main/rules/EC16/swift/EC16.asciidoc | 14 +++++++++++++ .../src/main/rules/EC17/EC17.json | 20 +++++++++++++++++++ .../src/main/rules/EC17/swift/EC17.asciidoc | 13 ++++++++++++ .../src/main/rules/EC18/EC18.json | 20 +++++++++++++++++++ .../src/main/rules/EC18/swift/EC18.asciidoc | 12 +++++++++++ .../src/main/rules/EC19/EC19.json | 20 +++++++++++++++++++ .../src/main/rules/EC19/swift/EC19.asciidoc | 20 +++++++++++++++++++ .../src/main/rules/EC20/EC20.json | 20 +++++++++++++++++++ .../src/main/rules/EC20/swift/EC20.asciidoc | 17 ++++++++++++++++ .../src/main/rules/EC21/EC21.json | 20 +++++++++++++++++++ .../src/main/rules/EC21/swift/EC21.asciidoc | 9 +++++++++ .../src/main/rules/EC23/EC23.json | 20 +++++++++++++++++++ .../src/main/rules/EC23/swift/EC23.asciidoc | 14 +++++++++++++ 19 files changed, 331 insertions(+) create mode 100644 ecocode-rules-specifications/src/main/assembly/swift.xml create mode 100644 ecocode-rules-specifications/src/main/rules/EC14/EC14.json create mode 100644 ecocode-rules-specifications/src/main/rules/EC14/swift/EC14.asciidoc create mode 100644 ecocode-rules-specifications/src/main/rules/EC15/EC15.json create mode 100644 ecocode-rules-specifications/src/main/rules/EC15/swift/EC15.asciidoc create mode 100644 ecocode-rules-specifications/src/main/rules/EC16/EC16.json create mode 100644 ecocode-rules-specifications/src/main/rules/EC16/swift/EC16.asciidoc create mode 100644 ecocode-rules-specifications/src/main/rules/EC17/EC17.json create mode 100644 ecocode-rules-specifications/src/main/rules/EC17/swift/EC17.asciidoc create mode 100644 ecocode-rules-specifications/src/main/rules/EC18/EC18.json create mode 100644 ecocode-rules-specifications/src/main/rules/EC18/swift/EC18.asciidoc create mode 100644 ecocode-rules-specifications/src/main/rules/EC19/EC19.json create mode 100644 ecocode-rules-specifications/src/main/rules/EC19/swift/EC19.asciidoc create mode 100644 ecocode-rules-specifications/src/main/rules/EC20/EC20.json create mode 100644 ecocode-rules-specifications/src/main/rules/EC20/swift/EC20.asciidoc create mode 100644 ecocode-rules-specifications/src/main/rules/EC21/EC21.json create mode 100644 ecocode-rules-specifications/src/main/rules/EC21/swift/EC21.asciidoc create mode 100644 ecocode-rules-specifications/src/main/rules/EC23/EC23.json create mode 100644 ecocode-rules-specifications/src/main/rules/EC23/swift/EC23.asciidoc diff --git a/ecocode-rules-specifications/src/main/assembly/swift.xml b/ecocode-rules-specifications/src/main/assembly/swift.xml new file mode 100644 index 000000000..2ea8b63a9 --- /dev/null +++ b/ecocode-rules-specifications/src/main/assembly/swift.xml @@ -0,0 +1,18 @@ + + swift + + jar + + false + + + ${project.build.outputDirectory} + + io/ecocode/rules/swift/*.* + + + + + diff --git a/ecocode-rules-specifications/src/main/rules/EC14/EC14.json b/ecocode-rules-specifications/src/main/rules/EC14/EC14.json new file mode 100644 index 000000000..11b6e314d --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC14/EC14.json @@ -0,0 +1,20 @@ +{ + "title": "Do not disable idle timer, unless absolutely necessary.", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + "eco-design", + "environment", + "sobriety", + "ecocode" + ], + "defaultSeverity": "Major", + "compatibleLanguages": [ + "SWIFT" + ] + } + \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC14/swift/EC14.asciidoc b/ecocode-rules-specifications/src/main/rules/EC14/swift/EC14.asciidoc new file mode 100644 index 000000000..9a283f08d --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC14/swift/EC14.asciidoc @@ -0,0 +1,15 @@ +To avoid draining the battery, an iOS device that is left idle quickly falls asleep. +Hence, keeping the screen on should be avoided, unless it is absolutely necessary. If so, developers typically +disable the idle timer with `UIApplication.shared.isIdleTimerDisabled = true`. + +## Noncompliant Code Example + +```swift +UIApplication.shared.isIdleTimerDisabled = true // Noncompliant +``` + +## Compliant Solution + +```swift +UIApplication.shared.isIdleTimerDisabled = false +``` diff --git a/ecocode-rules-specifications/src/main/rules/EC15/EC15.json b/ecocode-rules-specifications/src/main/rules/EC15/EC15.json new file mode 100644 index 000000000..5c16b127b --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC15/EC15.json @@ -0,0 +1,20 @@ +{ + "title": "Setting a tolerance for timers will allow them to fire later than the scheduled fire date.", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "1min" + }, + "tags": [ + "eco-design", + "environment", + "idleness", + "ecocode" + ], + "defaultSeverity": "Major", + "compatibleLanguages": [ + "SWIFT" + ] + } + \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC15/swift/EC15.asciidoc b/ecocode-rules-specifications/src/main/rules/EC15/swift/EC15.asciidoc new file mode 100644 index 000000000..271ed1b2f --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC15/swift/EC15.asciidoc @@ -0,0 +1,19 @@ +Setting a tolerance for timers will allow them to fire later than the scheduled fire date. +The system will use this flexibility to shift the execution of timers by small amounts of time, +within their tolerances, increasing the ability to optimize power savings. +Your app can set the `Timer#tolerance` property to specify a tolerance for a timer. +Using this approach dramatically increases the amount of time that the processor spends idling +while users detect no change in system responsiveness. + +## Noncompliant Code Example + +```swift +let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in } // Noncompliant +``` + +## Compliant Solution + +```swift +let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in } +timer.tolerance = 0.5 +``` diff --git a/ecocode-rules-specifications/src/main/rules/EC16/EC16.json b/ecocode-rules-specifications/src/main/rules/EC16/EC16.json new file mode 100644 index 000000000..a51bee56a --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC16/EC16.json @@ -0,0 +1,20 @@ +{ + "title": "Monitoring power changes and customizing behavior depending on battery level is a good practice.", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "0min" + }, + "tags": [ + "eco-design", + "environment", + "power", + "ecocode" + ], + "defaultSeverity": "Info", + "compatibleLanguages": [ + "SWIFT" + ] + } + \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC16/swift/EC16.asciidoc b/ecocode-rules-specifications/src/main/rules/EC16/swift/EC16.asciidoc new file mode 100644 index 000000000..5b74d8331 --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC16/swift/EC16.asciidoc @@ -0,0 +1,14 @@ +It's always good that an app has different behavior when device is connected/disconnected to a power station, +or has different battery levels. Your app can query the `UIDevice#batteryLevel` and +`UIDevice#batteryState` properties at any time to determine the level of charge and +the state of the battery. Your app can also register to receive notifications when the battery level +or state changes, using `batteryLevelDidChangeNotification` and batteryStateDidChangeNotification`. + +## Compliant Code Example + +```swift +let level = UIDevice.current.batteryLevel +let state = UIDevice.current.batteryState +NotificationCenter.default.addObserver(forName: UIDevice.batteryLevelDidChangeNotification, object: nil, queue: nil) { _ in } +NotificationCenter.default.addObserver(forName: UIDevice.batteryStateDidChangeNotification, object: nil, queue: nil) { _ in } +``` \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC17/EC17.json b/ecocode-rules-specifications/src/main/rules/EC17/EC17.json new file mode 100644 index 000000000..2c853e895 --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC17/EC17.json @@ -0,0 +1,20 @@ +{ + "title": "Taking into account when the device is entering or exiting the power save mode is a good practice.", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "0min" + }, + "tags": [ + "eco-design", + "environment", + "power", + "ecocode" + ], + "defaultSeverity": "Info", + "compatibleLanguages": [ + "SWIFT" + ] + } + \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC17/swift/EC17.asciidoc b/ecocode-rules-specifications/src/main/rules/EC17/swift/EC17.asciidoc new file mode 100644 index 000000000..7facd238b --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC17/swift/EC17.asciidoc @@ -0,0 +1,13 @@ +Use device API to check if low power mode is enabled, and adapt resources usage accordingly. +For example, you can reduce frequency of data update if low power mode is enabled. +Your app can query the `ProcessInfo.processInfo.isLowPowerModeEnabled` property at any time +to determine whether Low Power Mode is active. Your app can also register to receive notifications +when the Low Power Mode state of a device changes, using `NSProcessInfoPowerStateDidChange`. + +## Compliant Code Example + +```swift +let isLowPowerModeEnabled = ProcessInfo.processInfo.isLowPowerModeEnabled +NotificationCenter.default.addObserver(forName: .NSProcessInfoPowerStateDidChange, object: nil, queue: nil) { _ in } +NotificationCenter.default.addObserver(forName: Notification.Name.NSProcessInfoPowerStateDidChange, object: nil, queue: nil) { _ in } +``` \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC18/EC18.json b/ecocode-rules-specifications/src/main/rules/EC18/EC18.json new file mode 100644 index 000000000..6dd70fdfa --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC18/EC18.json @@ -0,0 +1,20 @@ +{ + "title": "Do not disable location updates pause, unless absolutely necessary.", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + "eco-design", + "environment", + "sobriety", + "ecocode" + ], + "defaultSeverity": "Major", + "compatibleLanguages": [ + "SWIFT" + ] + } + \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC18/swift/EC18.asciidoc b/ecocode-rules-specifications/src/main/rules/EC18/swift/EC18.asciidoc new file mode 100644 index 000000000..c64bcc495 --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC18/swift/EC18.asciidoc @@ -0,0 +1,12 @@ +Allowing the system to pause location updates, at times when the location data is unlikely to change, can improve +battery life without sacrificing location data. This is the default behavior. For example, if the user stops for +food while using a navigation app, the location manager might pause updates for a period of time. It is possible +to disable this behavior, by setting the `CLLocationManager#pausesLocationUpdatesAutomatically` +property to `false`, but applications are strongly discouraged of doing it. + +## Noncompliant Code Example + +```swift +let manager = CLLocationManager() +manager.pausesLocationUpdatesAutomatically = false // Noncompliant +``` \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC19/EC19.json b/ecocode-rules-specifications/src/main/rules/EC19/EC19.json new file mode 100644 index 000000000..87dc5a2e6 --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC19/EC19.json @@ -0,0 +1,20 @@ +{ + "title": "Adapt location accuracy and type to applications needs.", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + "eco-design", + "environment", + "sobriety", + "ecocode" + ], + "defaultSeverity": "Major", + "compatibleLanguages": [ + "SWIFT" + ] + } + \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC19/swift/EC19.asciidoc b/ecocode-rules-specifications/src/main/rules/EC19/swift/EC19.asciidoc new file mode 100644 index 000000000..bc5553394 --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC19/swift/EC19.asciidoc @@ -0,0 +1,20 @@ +Location awareness is one of the most popular features used by apps. +By default standard location updates run with the best accuracy level, +but unless your app really needs to know the user’s position within a few meters, +this level of accuracy isn't needed. +Requesting higher accuracy than you need causes the system to power up additional hardware +and waste power for unnecessary precision. You can specify a degree of accuracy by setting +the `CLLocationManager#desiredAccuracy` property. +Also, setting the `CLLocationManager#activityType` property will let the system knows what type +of location activity your app is performing and helps it determine +the most appropriate time to perform location updates. +Finally, if your app just needs a quick fix on the user’s location, +it’s best to call the `CLLocationManager#requestLocation` method, +that will deliver a single location update. + +## Compliant Code Example + +```swift +let manager = CLLocationManager() +manager.desiredAccuracy = 2 +``` \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC20/EC20.json b/ecocode-rules-specifications/src/main/rules/EC20/EC20.json new file mode 100644 index 000000000..0f88fe059 --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC20/EC20.json @@ -0,0 +1,20 @@ +{ + "title": "Set appropriate motion sensor update rates for the application's needs.", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + "eco-design", + "environment", + "sobriety", + "ecocode" + ], + "defaultSeverity": "Major", + "compatibleLanguages": [ + "SWIFT" + ] + } + \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC20/swift/EC20.asciidoc b/ecocode-rules-specifications/src/main/rules/EC20/swift/EC20.asciidoc new file mode 100644 index 000000000..b0d4447a6 --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC20/swift/EC20.asciidoc @@ -0,0 +1,17 @@ +Using the Core Motion API, your app can receive continuous motion updates in the form of +accelerometer, gyroscope, and device motion (rotation, acceleration, and more) events. +Yet you don't often need these updates as soon as they are generated. +Before registering to receive these recurring motion updates, you can specify an interval +that meets your app’s needs, using `CMMotionManager#accelerometerUpdateInterval`, +`CMMotionManager#gyroUpdateInterval`, `CMMotionManager#deviceMotionUpdateInterval` and +`CMMotionManager#magnetometerUpdateInterval` properties. The larger the interval, +the fewer events are delivered to your app, improving battery life. + +## Compliant Code Example + +```swift +CMMotionManager.accelerometerUpdateInterval = 1000 +CMMotionManager.gyroUpdateInterval = 1000 +CMMotionManager.deviceMotionUpdateInterval = 1000 +CMMotionManager.magnetometerUpdateInterval = 1000 +``` \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC21/EC21.json b/ecocode-rules-specifications/src/main/rules/EC21/EC21.json new file mode 100644 index 000000000..a5d50a917 --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC21/EC21.json @@ -0,0 +1,20 @@ +{ + "title": "Do not force brightness in your code, unless absolutely necessary.", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + "eco-design", + "environment", + "sobriety", + "ecocode" + ], + "defaultSeverity": "Major", + "compatibleLanguages": [ + "SWIFT" + ] + } + \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC21/swift/EC21.asciidoc b/ecocode-rules-specifications/src/main/rules/EC21/swift/EC21.asciidoc new file mode 100644 index 000000000..2a809d5b7 --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC21/swift/EC21.asciidoc @@ -0,0 +1,9 @@ +To avoid draining the battery, an iOS device adapt its brightness to the environment. +Hence, keeping forcing the screen brightness on should be avoided, unless it is absolutely necessary. +If so, developers typically force the brightness to 1 with `UIScreen.main.brightness`. + +## Non-Compliant Code Example + +```swift +UIScreen.main.brightness = 0.3 +``` \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC23/EC23.json b/ecocode-rules-specifications/src/main/rules/EC23/EC23.json new file mode 100644 index 000000000..38256300c --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC23/EC23.json @@ -0,0 +1,20 @@ +{ + "title": "Turning on the torch mode programmatically must absolutely be avoided because the flashlight is one of the most energy-intensive component.", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + "eco-design", + "environment", + "sobriety", + "ecocode" + ], + "defaultSeverity": "Major", + "compatibleLanguages": [ + "SWIFT" + ] + } + \ No newline at end of file diff --git a/ecocode-rules-specifications/src/main/rules/EC23/swift/EC23.asciidoc b/ecocode-rules-specifications/src/main/rules/EC23/swift/EC23.asciidoc new file mode 100644 index 000000000..0cc3c0778 --- /dev/null +++ b/ecocode-rules-specifications/src/main/rules/EC23/swift/EC23.asciidoc @@ -0,0 +1,14 @@ +Turning on the torch mode programmatically using `AVCaptureDevice#torchMode` or `AVCaptureDevice#setTorchModeOn(level:)` +methods must absolutely be avoided because the flashlight is one of the most energy-intensive component. + +## Non-Compliant Code Example + +```swift +guard let videoDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else { return } +guard videoDevice.hasTorch else { return } + +videoDevice.lockForConfiguration() +videoDevice.torchMode = .on // non-compliant +videoDevice.setTorchModeOn(level: 1.0) // non-compliant +videoDevice.unlockForConfiguration() +``` \ No newline at end of file From dbf0e3e8f9a064079587da69a09273426c4dd3eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gae=CC=88l=20Foppolo?= Date: Thu, 9 Nov 2023 10:18:36 +0100 Subject: [PATCH 2/2] Add entry in CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2545fc5d5..301ac9f6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- [#224](https://github.com/green-code-initiative/ecoCode/issues/224) Add Swift rules from ecocode-ios - [ios#3](https://github.com/green-code-initiative/ecoCode-ios/issues/3) Move iOS rules into centralized rules repository - [android#67](https://github.com/green-code-initiative/ecoCode-android/issues/67) Move Android rules into centralized rules repository - [#216](https://github.com/green-code-initiative/ecoCode/issues/216) Upgrade rule EC2 for Java : Multiple if-else statement improvment