diff --git a/CHANGELOG.md b/CHANGELOG.md
index 24cc3c0de..cb03809f2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [#113](https://github.com/green-code-initiative/ecoCode/issues/113) new PYTHON rule : Use unoptimized vector images
- [#127](https://github.com/green-code-initiative/ecoCode/issues/127) Add Python rule EC404: Usage of generator comprehension instead of list comprehension in for loop declaration
+- [#192](https://github.com/green-code-initiative/ecoCode/pull/192) Add Python rule EC203: Detect unoptimized file formats
### Changed
diff --git a/RULES.md b/RULES.md
index dbbc7871e..1837f959c 100644
--- a/RULES.md
+++ b/RULES.md
@@ -48,3 +48,4 @@ Some are applicable for different technologies.
| EC5 | Usage of preparedStatement instead of Statement | SQL will only commit the query once, whereas if you used only one statement, it would commit the query every time and thus induce unnecessary calculations by the CPU and therefore superfluous energy consumption. | | β
| π« | π« | π« | π« |
| EC27 | Usage of system.arraycopy to copy arrays | Programs spend most of the time in loops. These can be resource consuming, especially when they integrate heavy processing (IO access). Moreover, the size of the data and processing inside the loops will not allow full use of hardware mechanisms such as the cache or compiler optimization mechanisms. | | β
| π« | π« | π« | π« |
| EC404 | Avoid list comprehension in iterations | Use generator comprehension instead of list comprehension in for loop declaration | | π« | π« | π« | β
| π« |
+| EC203 | Detect unoptimized file formats | When it is possible, to use svg format image over other image format | | π | π | π | β
| π |
diff --git a/java-plugin/src/main/java/fr/greencodeinitiative/java/RulesList.java b/java-plugin/src/main/java/fr/greencodeinitiative/java/RulesList.java
index d6a5cdbf4..8f2a47c47 100644
--- a/java-plugin/src/main/java/fr/greencodeinitiative/java/RulesList.java
+++ b/java-plugin/src/main/java/fr/greencodeinitiative/java/RulesList.java
@@ -24,25 +24,7 @@
import java.util.Collections;
import java.util.List;
-import fr.greencodeinitiative.java.checks.ArrayCopyCheck;
-import fr.greencodeinitiative.java.checks.AvoidConcatenateStringsInLoop;
-import fr.greencodeinitiative.java.checks.AvoidFullSQLRequest;
-import fr.greencodeinitiative.java.checks.AvoidGettingSizeCollectionInLoop;
-import fr.greencodeinitiative.java.checks.AvoidMultipleIfElseStatement;
-import fr.greencodeinitiative.java.checks.AvoidRegexPatternNotStatic;
-import fr.greencodeinitiative.java.checks.AvoidSQLRequestInLoop;
-import fr.greencodeinitiative.java.checks.AvoidSetConstantInBatchUpdate;
-import fr.greencodeinitiative.java.checks.AvoidSpringRepositoryCallInLoopCheck;
-import fr.greencodeinitiative.java.checks.AvoidStatementForDMLQueries;
-import fr.greencodeinitiative.java.checks.AvoidUsageOfStaticCollections;
-import fr.greencodeinitiative.java.checks.AvoidUsingGlobalVariablesCheck;
-import fr.greencodeinitiative.java.checks.FreeResourcesOfAutoCloseableInterface;
-import fr.greencodeinitiative.java.checks.IncrementCheck;
-import fr.greencodeinitiative.java.checks.InitializeBufferWithAppropriateSize;
-import fr.greencodeinitiative.java.checks.NoFunctionCallWhenDeclaringForLoop;
-import fr.greencodeinitiative.java.checks.OptimizeReadFileExceptions;
-import fr.greencodeinitiative.java.checks.UnnecessarilyAssignValuesToVariables;
-import fr.greencodeinitiative.java.checks.UseCorrectForLoop;
+import fr.greencodeinitiative.java.checks.*;
import org.sonar.plugins.java.api.JavaCheck;
public final class RulesList {
diff --git a/python-plugin/src/main/java/fr/greencodeinitiative/python/PythonRuleRepository.java b/python-plugin/src/main/java/fr/greencodeinitiative/python/PythonRuleRepository.java
index ff96bd13d..484cae93f 100644
--- a/python-plugin/src/main/java/fr/greencodeinitiative/python/PythonRuleRepository.java
+++ b/python-plugin/src/main/java/fr/greencodeinitiative/python/PythonRuleRepository.java
@@ -91,7 +91,8 @@ public List If possible, the utilisation of svg image format (or <svg/> html tag) is recommended over other image format. Because SVGs are generally smaller than other image format, theyβre less taxing on your server despite needing to render on load. When to use SVG :
+
+
+
Some advantages of using SVG : +
+ ... + img_jpg = "image.jpg" + ... ++
+ ... + img_svg = "image.svg" + ... ++ +
+ public void foo() { + ... + image_format = testImage("image.jpg") + ... + } ++
+ public void foo() { + ... + image_format = testImage("image.svg") + ... + } ++ +
+ public void foo() { + ... + return '<html><img src="xx/xx/image.bmp"></html>' + ... + } ++
+ public void foo() { + ... + return '<html><img src="xx/xx/image.svg"></html>' + ... + } + + public void foo2() { + ... + return ('<html><svg width="100" height="100">' + + '<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />' + + '</svg></html>') + ... + } +diff --git a/python-plugin/src/test/java/fr/greencodeinitiative/python/PythonRuleRepositoryTest.java b/python-plugin/src/test/java/fr/greencodeinitiative/python/PythonRuleRepositoryTest.java index 3562dc92d..0c734cbfa 100644 --- a/python-plugin/src/test/java/fr/greencodeinitiative/python/PythonRuleRepositoryTest.java +++ b/python-plugin/src/test/java/fr/greencodeinitiative/python/PythonRuleRepositoryTest.java @@ -44,8 +44,8 @@ public void init() { public void test() { assertThat(pythonRuleRepository.repositoryKey()).isEqualTo(PythonRuleRepository.REPOSITORY_KEY); assertThat(context.repositories()).hasSize(1).extracting("key").containsExactly(pythonRuleRepository.repositoryKey()); - assertThat(context.repositories().get(0).rules()).hasSize(8); - assertThat(pythonRuleRepository.checkClasses()).hasSize(8); + assertThat(context.repositories().get(0).rules()).hasSize(9); + assertThat(pythonRuleRepository.checkClasses()).hasSize(9); } diff --git a/python-plugin/src/test/java/fr/greencodeinitiative/python/checks/DetectUnoptimizedImageFormatTest.java b/python-plugin/src/test/java/fr/greencodeinitiative/python/checks/DetectUnoptimizedImageFormatTest.java new file mode 100644 index 000000000..7c735f59f --- /dev/null +++ b/python-plugin/src/test/java/fr/greencodeinitiative/python/checks/DetectUnoptimizedImageFormatTest.java @@ -0,0 +1,13 @@ +package fr.greencodeinitiative.python.checks; + +import org.junit.Test; +import org.sonar.python.checks.utils.PythonCheckVerifier; + +public class DetectUnoptimizedImageFormatTest { + + @Test + public void test() { + PythonCheckVerifier.verify("src/test/resources/checks/detectUnoptimizedImageFormat.py", new DetectUnoptimizedImageFormat()); + PythonCheckVerifier.verifyNoIssue("src/test/resources/checks/detectUnoptimizedImageFormatCompliant.py", new DetectUnoptimizedImageFormat()); + } +} diff --git a/python-plugin/src/test/resources/checks/avoidFullSQLRequest.py b/python-plugin/src/test/resources/checks/avoidFullSQLRequest.py index 217cb6c9a..66c6adb4c 100644 --- a/python-plugin/src/test/resources/checks/avoidFullSQLRequest.py +++ b/python-plugin/src/test/resources/checks/avoidFullSQLRequest.py @@ -8,5 +8,3 @@ def displayMessage(argument1): requestCompiliant = ' SeLeCt user FrOm myTable' displayMessage(requestNonCompiliant) displayMessage(requestCompiliant) - - diff --git a/python-plugin/src/test/resources/checks/avoidGettersAndSetters.py b/python-plugin/src/test/resources/checks/avoidGettersAndSetters.py index fd72053ad..538e79a79 100644 --- a/python-plugin/src/test/resources/checks/avoidGettersAndSetters.py +++ b/python-plugin/src/test/resources/checks/avoidGettersAndSetters.py @@ -23,4 +23,4 @@ def is_major(self): return self.age >= 18 def get_weight(self): # Noncompliant {{Avoid creating getter and setter methods in classes}} - return self.weight \ No newline at end of file + return self.weight diff --git a/python-plugin/src/test/resources/checks/avoidTryCatchFinallyCheck.py b/python-plugin/src/test/resources/checks/avoidTryCatchFinallyCheck.py index 1e24bb491..cbd081e0e 100644 --- a/python-plugin/src/test/resources/checks/avoidTryCatchFinallyCheck.py +++ b/python-plugin/src/test/resources/checks/avoidTryCatchFinallyCheck.py @@ -26,4 +26,4 @@ def boo(): if os.path.isfile(path): fh = open(path, 'r') print(fh.read()) - fh.close \ No newline at end of file + fh.close diff --git a/python-plugin/src/test/resources/checks/detectUnoptimizedImageFormat.py b/python-plugin/src/test/resources/checks/detectUnoptimizedImageFormat.py new file mode 100644 index 000000000..37ddac218 --- /dev/null +++ b/python-plugin/src/test/resources/checks/detectUnoptimizedImageFormat.py @@ -0,0 +1,36 @@ + +def testImage(image) : + return "path/to/" + image + + +def testImageFormat2() : + + img_bmp = "test/image.bmp" # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + img_ico = "image.ico" # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + img_tiff = "test/path/to/image.tiff" # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + img_webp = "test/path/to/" + "image.webp" # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + img_jpg = "image.jpg" # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + img_jpeg = "image.jpeg" # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + img_jfif = "image.jfif" # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + img_pjpeg = "image.pjpeg" # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + img_pjp = "image.pjp" # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + img_gif = "image.gif" # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + img_avif = "image.avif" # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + img_apng = "image.apng" # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + + image_format = testImage("image.jpg") # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + + return ('' # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + + '' # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + + '' # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + + '' # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + + '' # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + + '' # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + + '' # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + + '' # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + + '' # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + + '' # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + + '' # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + + '' # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + + '' # Noncompliant {{If possible, the utilisation of svg image format (or html tag) is recommended over other image format.}} + + '' ) diff --git a/python-plugin/src/test/resources/checks/detectUnoptimizedImageFormatCompliant.py b/python-plugin/src/test/resources/checks/detectUnoptimizedImageFormatCompliant.py new file mode 100644 index 000000000..205f125e7 --- /dev/null +++ b/python-plugin/src/test/resources/checks/detectUnoptimizedImageFormatCompliant.py @@ -0,0 +1,17 @@ + +def testImage(image) : + return "path/to/" + image + + +def testImageFormat2() : + + img_svg = "test/image.svg" # Compliant + + image_format = testImage("image.svg") # Compliant + + image_svg_html = ('') + + return ('' # Compliant + + '' ) diff --git a/python-plugin/src/test/resources/checks/noFunctionCallWhenDeclaringForLoop.py b/python-plugin/src/test/resources/checks/noFunctionCallWhenDeclaringForLoop.py index a3755d3e3..97cb01e63 100644 --- a/python-plugin/src/test/resources/checks/noFunctionCallWhenDeclaringForLoop.py +++ b/python-plugin/src/test/resources/checks/noFunctionCallWhenDeclaringForLoop.py @@ -6,6 +6,4 @@ def my_function(): my_function() pass - - -my_function() \ No newline at end of file +my_function()