diff --git a/ecocode-rules-specifications/README.md b/ecocode-rules-specifications/README.md
new file mode 100644
index 000000000..1ee24ba52
--- /dev/null
+++ b/ecocode-rules-specifications/README.md
@@ -0,0 +1,15 @@
+# ecoCode rules specification repository
+
+## Description
+
+This project contains the specifications of the ecoCode rules.
+
+All the existing rules can be found in the [rules folder](src/main/rules).
+
+## Description language
+
+The description of the rules uses the ASCIIDOC format (with [Markdown compatibility](https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/#markdown-compatibility)) in order to allow the inclusion of other pages (this feature is not available in standard with Markdown).
+
+See:
+* [AsciiDoc Syntax Quick Reference](https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/)
+* [Compare AsciiDoc to Markdown](https://docs.asciidoctor.org/asciidoc/latest/asciidoc-vs-markdown/)
diff --git a/ecocode-rules-specifications/pom.xml b/ecocode-rules-specifications/pom.xml
new file mode 100644
index 000000000..6dee12f0d
--- /dev/null
+++ b/ecocode-rules-specifications/pom.xml
@@ -0,0 +1,238 @@
+
+
+ 4.0.0
+
+
+ io.ecocode
+ ecocode-parent
+ 1.3.1-SNAPSHOT
+
+
+ ecocode-rules-specifications
+
+ ecoCode Rules Specifications repository
+ Repository that contains the specifications of every static-analysis rules available in ecoCode plugins.
+ https://github.com/green-code-initiative/ecoCode/tree/main/ecocode-rules-specifications
+
+
+
+ org.sonarsource.sonarqube
+ sonar-plugin-api
+ provided
+
+
+ org.sonarsource.analyzer-commons
+ sonar-analyzer-commons
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+
+ prepare-agent
+
+ prepare-agent
+
+
+
+ report
+
+ report
+
+
+
+
+
+
+ org.asciidoctor
+ asciidoctor-maven-plugin
+ 2.2.4
+
+
+ convert-to-html
+ generate-resources
+
+ process-asciidoc
+
+
+ ${project.basedir}/src/main/rules
+ ${project.build.directory}/rules
+
+ coderay
+ style
+
+ true
+ false
+ true
+
+
+ ERROR
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ 3.1.0
+
+
+ process-resources
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-assembly-plugin
+ 3.6.0
+
+
+ assembly-java
+ prepare-package
+
+ single
+
+
+
+ ${project.basedir}/src/main/assembly/java.xml
+
+
+
+
+ assembly-php
+ prepare-package
+
+ single
+
+
+
+ ${project.basedir}/src/main/assembly/php.xml
+
+
+
+
+ assembly-python
+ prepare-package
+
+ single
+
+
+
+ ${project.basedir}/src/main/assembly/python.xml
+
+
+
+
+ assembly-js
+ prepare-package
+
+ single
+
+
+
+ ${project.basedir}/src/main/assembly/js.xml
+
+
+
+
+ assembly-ts
+ prepare-package
+
+ single
+
+
+
+ ${project.basedir}/src/main/assembly/ts.xml
+
+
+
+
+
+ true
+
+
+
+
+
diff --git a/ecocode-rules-specifications/src/main/assembly/java.xml b/ecocode-rules-specifications/src/main/assembly/java.xml
new file mode 100644
index 000000000..dc9d8bd3c
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/assembly/java.xml
@@ -0,0 +1,18 @@
+
+ java
+
+ jar
+
+ false
+
+
+ ${project.build.outputDirectory}
+
+ io/ecocode/rules/java/*.*
+
+
+
+
+
diff --git a/ecocode-rules-specifications/src/main/assembly/js.xml b/ecocode-rules-specifications/src/main/assembly/js.xml
new file mode 100644
index 000000000..d5d72ca1e
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/assembly/js.xml
@@ -0,0 +1,18 @@
+
+ js
+
+ jar
+
+ false
+
+
+ ${project.build.outputDirectory}
+
+ io/ecocode/rules/js/*.*
+
+
+
+
+
diff --git a/ecocode-rules-specifications/src/main/assembly/php.xml b/ecocode-rules-specifications/src/main/assembly/php.xml
new file mode 100644
index 000000000..83eb07521
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/assembly/php.xml
@@ -0,0 +1,18 @@
+
+ php
+
+ jar
+
+ false
+
+
+ ${project.build.outputDirectory}
+
+ io/ecocode/rules/php/*.*
+
+
+
+
+
diff --git a/ecocode-rules-specifications/src/main/assembly/python.xml b/ecocode-rules-specifications/src/main/assembly/python.xml
new file mode 100644
index 000000000..7c294fd24
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/assembly/python.xml
@@ -0,0 +1,18 @@
+
+ python
+
+ jar
+
+ false
+
+
+ ${project.build.outputDirectory}
+
+ io/ecocode/rules/python/*.*
+
+
+
+
+
diff --git a/ecocode-rules-specifications/src/main/assembly/ts.xml b/ecocode-rules-specifications/src/main/assembly/ts.xml
new file mode 100644
index 000000000..ec0100661
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/assembly/ts.xml
@@ -0,0 +1,18 @@
+
+ ts
+
+ jar
+
+ false
+
+
+ ${project.build.outputDirectory}
+
+ io/ecocode/rules/ts/*.*
+
+
+
+
+
diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC1.json b/ecocode-rules-specifications/src/main/rules/EC1/EC1.json
similarity index 100%
rename from java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC1.json
rename to ecocode-rules-specifications/src/main/rules/EC1/EC1.json
diff --git a/ecocode-rules-specifications/src/main/rules/EC1/java/EC1.asciidoc b/ecocode-rules-specifications/src/main/rules/EC1/java/EC1.asciidoc
new file mode 100644
index 000000000..91ae3f7f0
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC1/java/EC1.asciidoc
@@ -0,0 +1,23 @@
+The use of Spring repository in a loop induces unnecessary calculations by the CPU and therefore superfluous energy consumption.
+
+## Noncompliant Code Example
+
+```java
+private final List ids = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+
+List employees = new ArrayList<>();
+
+for (Integer id: ids) {
+ Optional employee = employeeRepository.findById(id); // Noncompliant
+ if (employee.isPresent()) {
+ employees.add(employee.get());
+ }
+}
+```
+
+## Compliant Solution
+
+```java
+private final List ids = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+List employees = employeeRepository.findAllById(ids);
+```
diff --git a/ecocode-rules-specifications/src/main/rules/EC10/EC10.json b/ecocode-rules-specifications/src/main/rules/EC10/EC10.json
new file mode 100644
index 000000000..ec7fbffd9
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC10/EC10.json
@@ -0,0 +1,14 @@
+{
+ "title": "Avoid using unoptimized vector images",
+ "type": "CODE_SMELL",
+ "status": "ready",
+ "remediation": {
+ "func": "Constant\/Issue",
+ "constantCost": "60min"
+ },
+ "tags": [
+ "eco-design",
+ "ecocode"
+ ],
+ "defaultSeverity": "Minor"
+}
diff --git a/ecocode-rules-specifications/src/main/rules/EC10/python/EC10.asciidoc b/ecocode-rules-specifications/src/main/rules/EC10/python/EC10.asciidoc
new file mode 100644
index 000000000..cf2483171
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC10/python/EC10.asciidoc
@@ -0,0 +1,39 @@
+SVG images generated by common drawing softwares contains unnecessary data: calc layer, metadata, namespaces and comments.
+
+## Noncompliant Code Example
+
+```xml
+
+
+```
+
+## Compliant Solution
+
+```xml
+
+```
diff --git a/ecocode-rules-specifications/src/main/rules/EC11/EC11.json b/ecocode-rules-specifications/src/main/rules/EC11/EC11.json
new file mode 100644
index 000000000..878a34665
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC11/EC11.json
@@ -0,0 +1,19 @@
+{
+ "title": "Disallow multiple access of same DOM element.",
+ "type": "CODE_SMELL",
+ "status": "ready",
+ "remediation": {
+ "func": "Constant\/Issue",
+ "constantCost": "5min"
+ },
+ "tags": [
+ "eco-design",
+ "performance",
+ "ecocode"
+ ],
+ "defaultSeverity": "Major",
+ "compatibleLanguages": [
+ "JAVASCRIPT",
+ "TYPESCRIPT"
+ ]
+}
diff --git a/ecocode-rules-specifications/src/main/rules/EC11/js/EC11.asciidoc b/ecocode-rules-specifications/src/main/rules/EC11/js/EC11.asciidoc
new file mode 100644
index 000000000..b5a2a8649
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC11/js/EC11.asciidoc
@@ -0,0 +1,20 @@
+## Rule details
+
+This rule aims to reduce DOM access assigning its object to variable when access multiple time. It saves CPU cycles.
+
+## Examples
+
+Examples of **incorrect** code for this rule:
+
+```js
+var el1 = document.getElementById("block1").test1;
+var el2 = document.getElementById("block1").test2;
+```
+
+Examples of **correct** code for this rule:
+
+```js
+var blockElement = document.getElementById("block1");
+var el1 = blockElement.test1;
+var el2 = blockElement.test2;
+```
diff --git a/ecocode-rules-specifications/src/main/rules/EC12/EC12.json b/ecocode-rules-specifications/src/main/rules/EC12/EC12.json
new file mode 100644
index 000000000..67c6010cf
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC12/EC12.json
@@ -0,0 +1,19 @@
+{
+ "title": "Disallow multiple style changes at once.",
+ "type": "CODE_SMELL",
+ "status": "ready",
+ "remediation": {
+ "func": "Constant\/Issue",
+ "constantCost": "10min"
+ },
+ "tags": [
+ "eco-design",
+ "performance",
+ "ecocode"
+ ],
+ "defaultSeverity": "Major",
+ "compatibleLanguages": [
+ "JAVASCRIPT",
+ "TYPESCRIPT"
+ ]
+}
diff --git a/ecocode-rules-specifications/src/main/rules/EC12/js/EC12.asciidoc b/ecocode-rules-specifications/src/main/rules/EC12/js/EC12.asciidoc
new file mode 100644
index 000000000..5bd836997
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC12/js/EC12.asciidoc
@@ -0,0 +1,33 @@
+## Rule Details
+
+This rule aims to disallow batching multiple style changes at once.
+
+To limit the number of repaint/reflow, it is advised to batch style modifications by adding a class containing all style changes that will generate a unique reflow.
+
+## Examples
+
+Examples of **non-compliant** code for this rule:
+
+```html
+
+```
+
+Examples of **compliant** code for this rule:
+
+```html
+
+
+
+```
diff --git a/ecocode-rules-specifications/src/main/rules/EC13/EC13.json b/ecocode-rules-specifications/src/main/rules/EC13/EC13.json
new file mode 100644
index 000000000..6ff60b4fa
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC13/EC13.json
@@ -0,0 +1,19 @@
+{
+ "title": "Prefer API collections with pagination.",
+ "type": "CODE_SMELL",
+ "status": "ready",
+ "remediation": {
+ "func": "Constant\/Issue",
+ "constantCost": "30min"
+ },
+ "tags": [
+ "eco-design",
+ "performance",
+ "ecocode"
+ ],
+ "defaultSeverity": "Minor",
+ "compatibleLanguages": [
+ "JAVASCRIPT",
+ "TYPESCRIPT"
+ ]
+}
diff --git a/ecocode-rules-specifications/src/main/rules/EC13/ts/EC13.asciidoc b/ecocode-rules-specifications/src/main/rules/EC13/ts/EC13.asciidoc
new file mode 100644
index 000000000..abc58bf6c
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC13/ts/EC13.asciidoc
@@ -0,0 +1,31 @@
+## Rule details
+
+This rule aims to reduce the size and thus the network weight of API returns that may contain many elements. This rule is built for the https://nestjs.com[NestJS framework] but can work with a controller `@Controller()` and a decorated method `@Get()`.
+
+## Examples
+
+Examples of **non-compliant** code for this rule:
+
+```typescript
+@Controller()
+class Test {
+ @Get()
+ public find(): Promise {}
+}
+```
+
+Examples of **compliant** code for this rule:
+
+```typescript
+interface Pagination {
+ items: string[];
+ currentPage: number;
+ totalPages: number;
+}
+
+@Controller()
+class Test {
+ @Get()
+ public find(): Promise {}
+}
+```
diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC2.json b/ecocode-rules-specifications/src/main/rules/EC2/EC2.json
similarity index 100%
rename from java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC2.json
rename to ecocode-rules-specifications/src/main/rules/EC2/EC2.json
diff --git a/ecocode-rules-specifications/src/main/rules/EC2/java/EC2.asciidoc b/ecocode-rules-specifications/src/main/rules/EC2/java/EC2.asciidoc
new file mode 100644
index 000000000..0e56f2845
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC2/java/EC2.asciidoc
@@ -0,0 +1,32 @@
+If we are using too many conditional `if` – `else` statements it will impact performance since JVM will have to compare the conditions. We can think of using a switch statement instead of multiple `if` – `else` if possible. `switch` statement has a performance advantage over `if` – `else`.
+
+## Non-compliant Code Example
+
+```java
+int index = 1;
+int nb = 2;
+
+if (nb > index) {
+ nb = nb + index;
+} else {
+ nb = nb - 1;
+}
+if (nb != index + 1) {
+ nb = nb + index;
+} else {
+ nb = nb - 1;
+}
+```
+
+## Compliant Code Example
+
+```java
+int index = 1;
+int nb = 2;
+
+if (nb > index) {
+ nb = nb + index;
+} else {
+ nb = nb - 1;
+}
+```
diff --git a/ecocode-rules-specifications/src/main/rules/EC203/EC203.json b/ecocode-rules-specifications/src/main/rules/EC203/EC203.json
new file mode 100644
index 000000000..3f46aefd8
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC203/EC203.json
@@ -0,0 +1,16 @@
+{
+ "title": "Detect unoptimized image format",
+ "type": "CODE_SMELL",
+ "status": "ready",
+ "remediation": {
+ "func": "Constant\/Issue",
+ "constantCost": "60min"
+ },
+ "tags": [
+ "performance",
+ "user-experience",
+ "eco-design",
+ "ecocode"
+ ],
+ "defaultSeverity": "Minor"
+}
diff --git a/ecocode-rules-specifications/src/main/rules/EC203/python/EC203.asciidoc b/ecocode-rules-specifications/src/main/rules/EC203/python/EC203.asciidoc
new file mode 100644
index 000000000..85d38acb6
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC203/python/EC203.asciidoc
@@ -0,0 +1,78 @@
+If possible, the utilisation of svg image format (or `` 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 :
+
+- Your image is used for decorative website graphics, logos, icons, graphs and diagrams, and other simple images.
+- You image require animation.
+- You image need to be responsive and scale without lack of quality.
+
+Some advantages of using SVG:
+
+- SVGs are scalable and will render pixel-perfect at any resolution whereas JPEGs, PNGs and GIFs will not.
+- SVGs are vector images and therefore are usually much smaller in file-size than bitmap-based images.
+- SVGs can be embedded into the HTML which means they can be cached, edited directly using CSS and indexed for greater accessibility.
+- SVGs can be animated directly or by using CSS or JavaScript making it easy for web designers to add interactivity to a site.
+
+## Noncompliant Code Example
+
+```
+img_jpg = "image.jpg"
+```
+
+## Compliant Solution
+
+```
+img_svg = "image.svg"
+```
+
+## Noncompliant Code Example
+
+```
+public void foo() {
+ // ...
+ image_format = testImage("image.jpg")
+ // ...
+}
+```
+
+## Compliant Solution
+
+```
+public void foo() {
+ // ...
+ image_format = testImage("image.svg")
+ // ...
+}
+```
+
+## Noncompliant Code Example
+
+```
+public void foo() {
+ // ...
+ return ''
+ // ...
+}
+```
+
+## Compliant Solution
+
+```
+public void foo() {
+ // ...
+ return ''
+ // ...
+}
+```
+
+Or
+
+```
+ public void foo() {
+ // ...
+ return ('')
+ // ...
+}
+```
diff --git a/ecocode-rules-specifications/src/main/rules/EC22/EC22.json b/ecocode-rules-specifications/src/main/rules/EC22/EC22.json
new file mode 100644
index 000000000..9d3ed8c36
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC22/EC22.json
@@ -0,0 +1,15 @@
+{
+ "title": "Use of methods for basic operations",
+ "type": "CODE_SMELL",
+ "status": "ready",
+ "remediation": {
+ "func": "Constant\/Issue",
+ "constantCost": "5min"
+ },
+ "tags": [
+ "eco-design",
+ "performance",
+ "ecocode"
+ ],
+ "defaultSeverity": "Minor"
+}
diff --git a/ecocode-rules-specifications/src/main/rules/EC22/php/EC22.asciidoc b/ecocode-rules-specifications/src/main/rules/EC22/php/EC22.asciidoc
new file mode 100644
index 000000000..c42338993
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC22/php/EC22.asciidoc
@@ -0,0 +1,13 @@
+Use of methods for basic operations
+
+## Noncompliant Code Example
+
+```php
+$min = min($a, $b); // Noncompliant
+```
+
+## Compliant Solution
+
+```php
+$min = $a < $b ? $a : $b;
+```
diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC27.json b/ecocode-rules-specifications/src/main/rules/EC27/EC27.json
similarity index 100%
rename from java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC27.json
rename to ecocode-rules-specifications/src/main/rules/EC27/EC27.json
diff --git a/ecocode-rules-specifications/src/main/rules/EC27/java/EC27.asciidoc b/ecocode-rules-specifications/src/main/rules/EC27/java/EC27.asciidoc
new file mode 100644
index 000000000..455e0a137
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC27/java/EC27.asciidoc
@@ -0,0 +1,28 @@
+Using `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.
+
+For example, an array copy is potentially a non-performance source if it is poorly designed. Indeed, the use of a single copy loop can be twice as consuming as dedicated methods.
+Loops must be optimized to reduce processing time and make full use of hardware and processor mechanisms and optimizations.
+In the case of table copying (table), use the native `System.arraycopy`.
+We can also use `copyOf` or `clone` that are slightly less efficient.
+The looping method will be outlawed.
+
+## Noncompliant Code Example
+
+```java
+int len = array.length;
+boolean[] copy = new boolean[array.length];
+for (int i = 0; i < len; i++) {
+ copy[i] = array[i]; // Noncompliant
+}
+return copy;
+```
+
+## Compliant Solution
+
+```java
+int[] copy = new int[array.length];
+System.arraycopy(array, 0, copy, 0, array.length);
+return copy;
+```
diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC28.json b/ecocode-rules-specifications/src/main/rules/EC28/EC28.json
similarity index 100%
rename from java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC28.json
rename to ecocode-rules-specifications/src/main/rules/EC28/EC28.json
diff --git a/ecocode-rules-specifications/src/main/rules/EC28/java/EC28.asciidoc b/ecocode-rules-specifications/src/main/rules/EC28/java/EC28.asciidoc
new file mode 100644
index 000000000..841ee9f8c
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC28/java/EC28.asciidoc
@@ -0,0 +1,30 @@
+Optimize read file exception
+
+## Noncompliant Code Example
+
+```java
+public void readPreferences(String filename) {
+ //...
+ InputStream in = null;
+ try {
+ in = new FileInputStream(filename);
+ } catch (FileNotFoundException e) {
+ logger.log(e);
+ }
+ in.read(...);
+ //...
+}
+```
+
+## Compliant Solution
+
+```java
+public void readPreferences(String filename) throws IllegalArgumentException, FileNotFoundException, IOException {
+ if (filename == null) {
+ throw new IllegalArgumentException ("filename is null");
+ }
+ //...
+ InputStream in = new FileInputStream(filename);
+ //...
+}
+```
diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC3.json b/ecocode-rules-specifications/src/main/rules/EC3/EC3.json
similarity index 93%
rename from java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC3.json
rename to ecocode-rules-specifications/src/main/rules/EC3/EC3.json
index f511c1c2a..33916b15e 100644
--- a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC3.json
+++ b/ecocode-rules-specifications/src/main/rules/EC3/EC3.json
@@ -7,6 +7,7 @@
"constantCost": "5min"
},
"tags": [
+ "bad-practice",
"eco-design",
"performance",
"ecocode"
diff --git a/ecocode-rules-specifications/src/main/rules/EC3/java/EC3.asciidoc b/ecocode-rules-specifications/src/main/rules/EC3/java/EC3.asciidoc
new file mode 100644
index 000000000..49fcb223e
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC3/java/EC3.asciidoc
@@ -0,0 +1,22 @@
+When iterating over any collection, fetch the size of the collection in advance to avoid fetching it on each iteration, this saves CPU cycles, and therefore consumes less power. The example provided below illustrates what should be avoided.
+
+## Noncompliant Code Example
+
+```java
+List objList = getData();
+
+for (int i = 0; i < objList.size(); i++) { // Noncompliant
+ // execute code
+}
+```
+
+## Compliant Solution
+
+```java
+List objList = getData();
+
+int size = objList.size();
+for (int i = 0; i < size; i++) {
+ // execute code
+}
+```
diff --git a/ecocode-rules-specifications/src/main/rules/EC3/php/EC3.asciidoc b/ecocode-rules-specifications/src/main/rules/EC3/php/EC3.asciidoc
new file mode 100644
index 000000000..9c4d5bb81
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC3/php/EC3.asciidoc
@@ -0,0 +1,96 @@
+When iterating over any collection, fetch the size of the collection in advance to avoid fetching it on each iteration, this saves CPU cycles, and therefore consumes less power.
+
+NB : note that we are using the `count()` method to get the size of an array but it would work the same with the `sizeof()` and `iterator_count()` methods.
+
+## Noncompliant Code Example
+
+```php
+$array = array('orange', 'banana', 'apple', 'carrot', 'collard', 'pea');
+
+// FOR STATEMENTS / Right operand
+for ($i = 0; $i < count($array); ++$i) {
+ var_dump($array[$i]);
+}
+
+// FOR STATEMENTS / Left operand
+for ($i = 0; count($array) > $i; ++$i) {
+ var_dump($array[$i]);
+}
+
+// WHILE STATEMENTS / Right operand
+$i = 0;
+while($i < count($array)) {
+ var_dump($array[$i]);
+ ++$i;
+}
+
+// WHILE STATEMENTS / Left operand
+$i = 0;
+while(count($array) > $i) {
+ var_dump($array[$i]);
+ ++$i;
+}
+
+// DO WHILE STATEMENTS / Right operand
+$i = 0;
+do {
+ var_dump($array[$i]);
+ ++$i;
+} while ($i < count($array));
+
+// DO WHILE STATEMENTS / Left operand
+$i = 0;
+do {
+ var_dump($array[$i]);
+ ++$i;
+} while (count($array) > $i);
+```
+
+## Compliant Solution
+
+```php
+$array = array('orange', 'banana', 'apple', 'carrot', 'collard', 'pea');
+// FOR STATEMENTS / Right operand
+$size = sizeof($array);
+for ($i = 0; $i < $size; ++$i) {
+ var_dump($array[$i]);
+}
+
+// FOR STATEMENTS / Left operand
+$size = sizeof($array);
+for ($i = 0; $size > $i; ++$i) {
+ var_dump($array[$i]);
+}
+
+// WHILE STATEMENTS / Right operand
+$i = 0;
+$size = count($array);
+while($i < $size) {
+ var_dump($array[$i]);
+ ++$i;
+}
+
+// WHILE STATEMENTS / Left operand
+$i = 0;
+$size = count($array);
+while($size > $i) {
+ var_dump($array[$i]);
+ ++$i;
+}
+
+// DO WHILE STATEMENTS / Right operand
+$i = 0;
+$size = count($array);
+do {
+ var_dump($array[$i]);
+ ++$i;
+} while ($i < $size);
+
+// DO WHILE STATEMENTS / Left operand
+$i = 0;
+$size = count($array);
+do {
+ var_dump($array[$i]);
+ ++$i;
+} while ($size > $i);
+```
diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC32.json b/ecocode-rules-specifications/src/main/rules/EC32/EC32.json
similarity index 100%
rename from java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC32.json
rename to ecocode-rules-specifications/src/main/rules/EC32/EC32.json
diff --git a/ecocode-rules-specifications/src/main/rules/EC32/java/EC32.asciidoc b/ecocode-rules-specifications/src/main/rules/EC32/java/EC32.asciidoc
new file mode 100644
index 000000000..00c2ac907
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC32/java/EC32.asciidoc
@@ -0,0 +1,21 @@
+If you know in advance how many characters would be appended, initialize builder/buffer with the appropriate size.
+They will thus never have to be resized.
+This saves CPU cycles and therefore consumes less energy.
+
+## Noncompliant Code Example
+
+```java
+StringBuilder sb = new StringBuilder(); // Noncompliant
+for (int i = 0; i < 100; i++) {
+ sb.append(...);
+}
+```
+
+## Compliant Solution
+
+```java
+StringBuilder sb = new StringBuilder(100);
+for (int i = 0; i < 100; i++) {
+ sb.append(...);
+}
+```
diff --git a/ecocode-rules-specifications/src/main/rules/EC34/EC34.json b/ecocode-rules-specifications/src/main/rules/EC34/EC34.json
new file mode 100644
index 000000000..00bc65320
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC34/EC34.json
@@ -0,0 +1,15 @@
+{
+ "title": "Avoid using try-catch statement",
+ "type": "CODE_SMELL",
+ "status": "ready",
+ "remediation": {
+ "func": "Constant\/Issue",
+ "constantCost": "5min"
+ },
+ "tags": [
+ "eco-design",
+ "performance",
+ "ecocode"
+ ],
+ "defaultSeverity": "Minor"
+}
diff --git a/ecocode-rules-specifications/src/main/rules/EC34/php/1GB.etsdiff.csv b/ecocode-rules-specifications/src/main/rules/EC34/php/1GB.etsdiff.csv
new file mode 100644
index 000000000..5b56c3789
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC34/php/1GB.etsdiff.csv
@@ -0,0 +1,3 @@
+Energy (J),515.855638,516.9188409999999
+Transfer (B),1579453,1579457
+Storage (B),637549804,637549804
diff --git a/ecocode-rules-specifications/src/main/rules/EC34/php/EC34.asciidoc b/ecocode-rules-specifications/src/main/rules/EC34/php/EC34.asciidoc
new file mode 100644
index 000000000..f7b2ab71d
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC34/php/EC34.asciidoc
@@ -0,0 +1,45 @@
+Inside complex code parts (for exemple multiple loops, complex data constructions...), avoid using try...catch...finally.
+
+When an exception is thrown, a variable (the exception itself) is created in a catch block and it's destruction consumes unnecessary CPU cycles and RAM. Prefer using logical tests in this cases.
+
+## Noncompliant Code Example
+
+```php
+try
+{
+ $picture = PDF_open_image_file($PDF, "jpeg", $imgFile, "", 0); // This is the original statement, this works on PHP4
+}
+catch(Exception $ex)
+{
+ $msg = "Error opening $imgFile for Product $row['Identifier']";
+ throw new Exception($msg);
+}
+```
+
+## Compliant Solution
+
+```php
+//try
+if (file_exists($imgFile)) {
+ $picture = PDF_open_image_file($PDF, "jpeg", $imgFile, "", 0);
+}
+
+//catch
+if (!$picture) {
+ $msg = "Error opening $imgFile for Product $row['Identifier']";
+ print $msg;
+}
+```
+
+include::../../etsdiff-methodology.asciidoc[]
+
+## Case for a 1GB database:
+
+image::https://live.staticflickr.com/65535/52622382871_f19da08db4_o.png[ETSdiff percent comparison]
+
+[format=csv,cols="1h,1,1"]
+|===
+Source of impacts,Compliant,Non-compliant
+
+include::1GB.etsdiff.csv[]
+|===
diff --git a/ecocode-rules-specifications/src/main/rules/EC34/python/EC34.asciidoc b/ecocode-rules-specifications/src/main/rules/EC34/python/EC34.asciidoc
new file mode 100644
index 000000000..14b3c3c5b
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC34/python/EC34.asciidoc
@@ -0,0 +1,25 @@
+Inside complex code parts (for example multiple loops, complex data constructions...), avoid using try...catch...finally.
+
+When an exception is thrown, a variable (the exception itself) is created in a catch block, and it's destruction consumes unnecessary CPU cycles and RAM. Prefer using logical tests in this cases.
+
+## Noncompliant Code Example
+
+```python
+try:
+ f = open(path)
+ print(fh.read())
+except:
+ print('No such file '+path
+finally:
+ f.close()
+```
+
+## Compliant Solution
+
+```python
+if os.path.isfile(path):
+ fh = open(path, 'r')
+ print(fh.read())
+ fh.close
+```
+
diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC4.json b/ecocode-rules-specifications/src/main/rules/EC4/EC4.json
similarity index 100%
rename from java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC4.json
rename to ecocode-rules-specifications/src/main/rules/EC4/EC4.json
diff --git a/ecocode-rules-specifications/src/main/rules/EC4/java/EC4.asciidoc b/ecocode-rules-specifications/src/main/rules/EC4/java/EC4.asciidoc
new file mode 100644
index 000000000..f8763b4ed
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC4/java/EC4.asciidoc
@@ -0,0 +1,37 @@
+Prefer local variables as parameters
+
+When calling a global variable, the interpretation engine must check that it exists in all the scopes, that it has a value, etc. Passing global variables as arguments gives them the status of local variables inside the function, thus saving computing time (CPU cycles).
+
+## CASE 1 (Avoid as possible)
+
+You are back on the service code. You see that the `func1()` uses `globalVariabl1`. Okay, but whats its value by now ? How does it change ? Who mutates the `globalVariabl1` before it comes to this function ? What have been the sequence of all these mutations ? You would have no idea. It will be quite difficult to figure all this out.
+
+## CASE 2 (Recommended)
+
+You are back to you code, and see that the `func0()` fetches something and then passes it to `func1(param1)` as a parameter. You clearly know what the data is, how does it gets here.
+
+## Noncompliant Code Example
+
+```java
+var aGlobal = new String('Hello');
+
+function globalLength(){
+ length = aGlobal.length;
+ console.log(length);
+}
+
+globalLength();
+```
+
+## Compliant Solution
+
+```java
+var aGlobal = new String('Hello');
+
+function someVarLength(str){
+ length = str.length;
+ console.log(length);
+}
+
+somVarLength(aGlobal);
+```
diff --git a/ecocode-rules-specifications/src/main/rules/EC4/php/EC4.asciidoc b/ecocode-rules-specifications/src/main/rules/EC4/php/EC4.asciidoc
new file mode 100644
index 000000000..94021a9e6
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC4/php/EC4.asciidoc
@@ -0,0 +1,29 @@
+Prefer local variables as parameters
+
+When calling a global variable, the interpretation engine must check that it exists in all the scopes, that it has a value, etc. Passing global variables as arguments gives them the status of local variables inside the function, thus saving computing time (CPU cycles).
+
+## Noncompliant Code Example
+
+```php
+var aGlobal = new String('Hello');
+
+function globalLength(){
+ length = aGlobal.length;
+ console.log(length);
+}
+
+globalLength();
+```
+
+## Compliant Solution
+
+```php
+var aGlobal = new String('Hello');
+
+function someVarLength(str){
+ length = str.length;
+ console.log(length);
+}
+
+somVarLength(aGlobal);
+```
diff --git a/python-plugin/src/main/resources/fr/greencodeinitiative/l10n/python/rules/python/EC4.html b/ecocode-rules-specifications/src/main/rules/EC4/python/EC4.asciidoc
similarity index 55%
rename from python-plugin/src/main/resources/fr/greencodeinitiative/l10n/python/rules/python/EC4.html
rename to ecocode-rules-specifications/src/main/rules/EC4/python/EC4.asciidoc
index c92e7e5be..b777840a9 100644
--- a/python-plugin/src/main/resources/fr/greencodeinitiative/l10n/python/rules/python/EC4.html
+++ b/ecocode-rules-specifications/src/main/rules/EC4/python/EC4.asciidoc
@@ -1,20 +1,24 @@
-
When function calls global variables, a lot a CPU cycles is consumed.
-
Noncompliant Code Example
-
+When function calls global variables, a lot a CPU cycles is consumed.
+
+## Noncompliant Code Example
+
+```python
global_var = 'foo'
def print_global_var_details():
print(len(global_var)) # Noncompliant
print('Global var : ', global_var) # Noncompliant
print('Global var : ' + global_var) # Noncompliant
print_global_var_details()
-
+```
diff --git a/ecocode-rules-specifications/src/main/rules/EC404/EC404.json b/ecocode-rules-specifications/src/main/rules/EC404/EC404.json
new file mode 100644
index 000000000..c04d919d3
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC404/EC404.json
@@ -0,0 +1,15 @@
+{
+ "title": "Use generator comprehension instead of list comprehension in for loop declaration",
+ "type": "CODE_SMELL",
+ "status": "ready",
+ "remediation": {
+ "func": "Constant\/Issue",
+ "constantCost": "15min"
+ },
+ "tags": [
+ "performance",
+ "eco-design",
+ "ecocode"
+ ],
+ "defaultSeverity": "Minor"
+}
diff --git a/ecocode-rules-specifications/src/main/rules/EC404/python/EC404.asciidoc b/ecocode-rules-specifications/src/main/rules/EC404/python/EC404.asciidoc
new file mode 100644
index 000000000..4a0738f9f
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC404/python/EC404.asciidoc
@@ -0,0 +1,20 @@
+Use generator comprehension instead of list comprehension in for loop declaration.
+
+Python generators resemble lazy lists from other programming languages: when iterated over, they compute their values on the fly. They lack some list behaviors (indexing, len method, ...) but are memory-efficient, as they do not store each of their values in memory, unlike lists. Thus, when declared in a for-loop declaration, list comprehensions can be safely replaced with generator comprehensions.
+
+For more details on list comprehensions vs generator comprehensions, see https://docs.python.org/3/howto/functional.html#generator-expressions-and-list-comprehensions[Python documentation].
+
+## Noncompliant Code Example
+
+```python
+for var in [var2 for var2 in range(100)]:
+ ...
+
+```
+
+## Compliant Solution
+
+```python
+for var in (var2 for var2 in range(100)):
+ ...
+```
diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC5.json b/ecocode-rules-specifications/src/main/rules/EC5/EC5.json
similarity index 100%
rename from java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC5.json
rename to ecocode-rules-specifications/src/main/rules/EC5/EC5.json
diff --git a/ecocode-rules-specifications/src/main/rules/EC5/java/EC5.asciidoc b/ecocode-rules-specifications/src/main/rules/EC5/java/EC5.asciidoc
new file mode 100644
index 000000000..229a3503d
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC5/java/EC5.asciidoc
@@ -0,0 +1,22 @@
+Use `PreparedStatement` instead of `Statement`, because 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.
+
+## Noncompliant Code Example
+
+```java
+public void select() {
+ Statement statement = connection.createStatement();
+ statement.executeUpdate("INSERT INTO persons(id, name) VALUES(2, 'John DOE')"); // Noncompliant
+}
+```
+
+## Compliant Solution
+
+```java
+public void select() {
+ PreparedStatement statement = connection.prepareStatement(INSERT INTO persons(id, name) VALUES(?, ?));
+
+ statement.setInt(1, 2);
+ statement.setString(2, "John DOE");
+ statement.executeQuery();
+}
+```
diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC53.json b/ecocode-rules-specifications/src/main/rules/EC53/EC53.json
similarity index 100%
rename from java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC53.json
rename to ecocode-rules-specifications/src/main/rules/EC53/EC53.json
diff --git a/ecocode-rules-specifications/src/main/rules/EC53/java/EC53.asciidoc b/ecocode-rules-specifications/src/main/rules/EC53/java/EC53.asciidoc
new file mode 100644
index 000000000..924efda63
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC53/java/EC53.asciidoc
@@ -0,0 +1,21 @@
+Using List instead of Arrays with Foreach save CPU cycles calculations and RAM consumption.
+
+## Noncompliant Code Example
+
+```java
+private final Integer[] intArray = new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+
+for (Integer i : intArray) {
+ // ...
+}
+```
+
+## Compliant Solution
+
+```java
+private final List intList = Arrays.asList(new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
+
+for (Integer i : intList) {
+ // ...
+}
+```
diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC63.json b/ecocode-rules-specifications/src/main/rules/EC63/EC63.json
similarity index 100%
rename from java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC63.json
rename to ecocode-rules-specifications/src/main/rules/EC63/EC63.json
diff --git a/ecocode-rules-specifications/src/main/rules/EC63/java/EC63.asciidoc b/ecocode-rules-specifications/src/main/rules/EC63/java/EC63.asciidoc
new file mode 100644
index 000000000..9d3ca796d
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC63/java/EC63.asciidoc
@@ -0,0 +1,17 @@
+Do not unnecessarily assign values to variables. It increases the use of RAM memory.
+
+## Noncompliant Code Example
+
+```java
+String var1 = getValue();
+return var1;
+
+String var2 = "hello"
+var2 = "world" //Non compliant cause never assigned
+```
+
+## Compliant Solution
+
+```java
+return getValue();
+```
diff --git a/ecocode-rules-specifications/src/main/rules/EC66/EC66.json b/ecocode-rules-specifications/src/main/rules/EC66/EC66.json
new file mode 100644
index 000000000..034168254
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC66/EC66.json
@@ -0,0 +1,16 @@
+{
+ "title": "Avoid using double quote (\"), prefer using simple quote (')",
+ "type": "CODE_SMELL",
+ "status": "ready",
+ "remediation": {
+ "func": "Constant\/Issue",
+ "constantCost": "5min"
+ },
+ "tags": [
+ "bad-practice",
+ "eco-design",
+ "performance",
+ "ecocode"
+ ],
+ "defaultSeverity": "Minor"
+}
diff --git a/ecocode-rules-specifications/src/main/rules/EC66/php/1GB.etsdiff.csv b/ecocode-rules-specifications/src/main/rules/EC66/php/1GB.etsdiff.csv
new file mode 100644
index 000000000..4765a99fe
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC66/php/1GB.etsdiff.csv
@@ -0,0 +1,3 @@
+Energy (J),3.041966,1.2651545000000002
+Transfer (B),68520884,68588123
+Storage (B),637548795,637548795
diff --git a/ecocode-rules-specifications/src/main/rules/EC66/php/EC66.asciidoc b/ecocode-rules-specifications/src/main/rules/EC66/php/EC66.asciidoc
new file mode 100644
index 000000000..8af551481
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC66/php/EC66.asciidoc
@@ -0,0 +1,30 @@
+PHP allows declaring a string with simple or double quotes. Using double quotes allows developers to insert variables which will be substituted during execution. When the string has no variables, using single quotes prevents PHP from searching for non-existent variables. It will save CPU cycles consumption and RAM usage.
+
+## Noncompliant Code Example
+
+```php
+myFunction("name", "age", "IsStudent");
+ $lastName = "Hugo";
+ $concatenatedString = "$lastName is a student";
+```
+
+## Compliant Solution
+
+```php
+myFunction('name', 'age', 'IsStudent');
+ $lastName = 'Hugo';
+ $concatenatedString = $lastName . 'is a student';
+```
+
+include::../../etsdiff-methodology.asciidoc[]
+
+## Case for a 1GB database:
+
+image::https://live.staticflickr.com/65535/52621866212_de15608a41_o.png[ETSdiff percent comparison]
+
+[format=csv,cols="1h,1,1"]
+|===
+Source of impacts,Compliant,Non-compliant
+
+include::1GB.etsdiff.csv[]
+|===
diff --git a/ecocode-rules-specifications/src/main/rules/EC66/python/EC66.asciidoc b/ecocode-rules-specifications/src/main/rules/EC66/python/EC66.asciidoc
new file mode 100644
index 000000000..09e0eda41
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC66/python/EC66.asciidoc
@@ -0,0 +1,31 @@
+The shape using the quotation marks (") allows the developer to insert variables that will be substituted at run time.
+
+But if the string does not have a variable, use quotes (') instead.
+
+Thus, language will not look for variables to substitute, which will reduce the consumption of CPU cycles.
+
+## Noncompliant Code Example
+
+```python
+# in variables
+firstname = "Andrea" # Noncompliant {{Avoid using quotation mark ("), prefer using simple quote (')}}
+
+# in functions
+def my_function(name, age):
+ print(name + 'is' + age + ' yo.')
+
+my_function("Robert", 12) # Noncompliant {{Avoid using quotation mark ("), prefer using simple quote (')}}
+```
+
+## Compliant Solution
+
+```python
+# in variables
+firstname = 'Andrea'
+
+# in functions
+def my_function(name, age):
+ print(name + 'is' + age + ' yo.')
+
+my_function('Robert', 12)
+```
diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC67.json b/ecocode-rules-specifications/src/main/rules/EC67/EC67.json
similarity index 100%
rename from java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC67.json
rename to ecocode-rules-specifications/src/main/rules/EC67/EC67.json
diff --git a/ecocode-rules-specifications/src/main/rules/EC67/java/EC67.asciidoc b/ecocode-rules-specifications/src/main/rules/EC67/java/EC67.asciidoc
new file mode 100644
index 000000000..a0c7b961a
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC67/java/EC67.asciidoc
@@ -0,0 +1,13 @@
+The form `$i++` creates a temporary variable whereas `++$i` does not. It save CPU cycles.
+
+## Noncompliant Code Example
+
+```java
+i++ // Noncompliant
+```
+
+## Compliant Solution
+
+```java
+++i
+```
diff --git a/ecocode-rules-specifications/src/main/rules/EC67/php/1GB.etsdiff.csv b/ecocode-rules-specifications/src/main/rules/EC67/php/1GB.etsdiff.csv
new file mode 100644
index 000000000..c79e54fc0
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC67/php/1GB.etsdiff.csv
@@ -0,0 +1,3 @@
+Energy (J),1.8163645000000002,0.2613885000000001
+Transfer (B),11265758,11290494
+Storage (B),637548673,637548673
diff --git a/ecocode-rules-specifications/src/main/rules/EC67/php/EC67.asciidoc b/ecocode-rules-specifications/src/main/rules/EC67/php/EC67.asciidoc
new file mode 100644
index 000000000..9a025ea99
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC67/php/EC67.asciidoc
@@ -0,0 +1,26 @@
+The form `$i++` creates a temporary variable whereas `++$i` does not. It save CPU cycles.
+
+## Noncompliant Code Example
+
+```php
+$i++
+```
+
+## Compliant Solution
+
+```php
+++$i
+```
+
+include::../../etsdiff-methodology.asciidoc[]
+
+## Case for a 1GB database:
+
+image::https://live.staticflickr.com/65535/52622379586_f84c767111_o.png[ETSdiff percent comparison]
+
+[format=csv,cols="1h,1,1"]
+|===
+Source of impacts,Compliant,Non-compliant
+
+include::1GB.etsdiff.csv[]
+|===
diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC69.json b/ecocode-rules-specifications/src/main/rules/EC69/EC69.json
similarity index 100%
rename from java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC69.json
rename to ecocode-rules-specifications/src/main/rules/EC69/EC69.json
diff --git a/ecocode-rules-specifications/src/main/rules/EC69/java/EC69.asciidoc b/ecocode-rules-specifications/src/main/rules/EC69/java/EC69.asciidoc
new file mode 100644
index 000000000..e32cd94db
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC69/java/EC69.asciidoc
@@ -0,0 +1,24 @@
+Do not call a function when declaring a for-type loop in order to avoid function calls each iterations. It saves CPU cycles.
+
+## Noncompliant Code Example
+
+```java
+public void foo() {
+ for (int i = 0; i < getMyValue(); i++) { // Noncompliant
+ System.out.println(i);
+ boolean b = getMyValue() > 6;
+ }
+}
+```
+
+## Compliant Solution
+
+```java
+public void foo() {
+ int myValue = getMyValue();
+ for (int i = 0; i < myValue; i++) {
+ System.out.println(i);
+ boolean b = getMyValue() > 6;
+ }
+}
+```
diff --git a/ecocode-rules-specifications/src/main/rules/EC69/php/1GB.etsdiff.csv b/ecocode-rules-specifications/src/main/rules/EC69/php/1GB.etsdiff.csv
new file mode 100644
index 000000000..227f4def5
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC69/php/1GB.etsdiff.csv
@@ -0,0 +1,3 @@
+Energy (J),144.635057,144.58341249999998
+Transfer (B),50000,50004
+Storage (B),637549590,637549590
diff --git a/ecocode-rules-specifications/src/main/rules/EC69/php/EC69.asciidoc b/ecocode-rules-specifications/src/main/rules/EC69/php/EC69.asciidoc
new file mode 100644
index 000000000..0da3cde83
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC69/php/EC69.asciidoc
@@ -0,0 +1,38 @@
+Do not call a function when declaring a for-type loop in order to avoid function calls each iteration. It saves CPU cycles.
+
+## Noncompliant Code Example
+
+```php
+for ($i = 0; $i <= foo(); $i++) { // Noncompliant
+ // ......
+}
+```
+
+## Compliant Solution
+
+```php
+$maxI = foo();
+for ($i = 0; $i <= $maxI; $i++) {
+ .....
+}
+
+ OR
+
+for ($i = 0, $maxI = foo(); $i <= $maxI; $i++) {
+ .....
+}
+}
+```
+
+include::../../etsdiff-methodology.asciidoc[]
+
+## Case for a 1GB database:
+
+image::https://live.staticflickr.com/65535/52622634654_bf3c3d9ba8_o.png[ETSdiff percent comparison]
+
+[format=csv,cols="1h,1,1"]
+|===
+Source of impacts,Compliant,Non-compliant
+
+include::1GB.etsdiff.csv[]
+|===
diff --git a/ecocode-rules-specifications/src/main/rules/EC69/python/EC69.asciidoc b/ecocode-rules-specifications/src/main/rules/EC69/python/EC69.asciidoc
new file mode 100644
index 000000000..3d73ce30a
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC69/python/EC69.asciidoc
@@ -0,0 +1,17 @@
+Do not call a function when declaring a for-type loop in order to avoid function calls each iteration. It saves CPU cycles.
+
+## Noncompliant Code Example
+
+```python
+for i in my_function(): # Noncompliant
+ ......
+```
+
+## Compliant Solution
+
+```python
+limit = my_function()
+for i in limit:
+ ......
+```
+
diff --git a/ecocode-rules-specifications/src/main/rules/EC7/EC7.json b/ecocode-rules-specifications/src/main/rules/EC7/EC7.json
new file mode 100644
index 000000000..46c194d56
--- /dev/null
+++ b/ecocode-rules-specifications/src/main/rules/EC7/EC7.json
@@ -0,0 +1,15 @@
+{
+ "title": "Avoid creating getter and setter methods in classes",
+ "type": "CODE_SMELL",
+ "status": "ready",
+ "remediation": {
+ "func": "Constant\/Issue",
+ "constantCost": "5min"
+ },
+ "tags": [
+ "eco-design",
+ "performance",
+ "ecocode"
+ ],
+ "defaultSeverity": "Minor"
+}
diff --git a/python-plugin/src/main/resources/fr/greencodeinitiative/l10n/python/rules/python/EC7.html b/ecocode-rules-specifications/src/main/rules/EC7/python/EC7.asciidoc
similarity index 74%
rename from python-plugin/src/main/resources/fr/greencodeinitiative/l10n/python/rules/python/EC7.html
rename to ecocode-rules-specifications/src/main/rules/EC7/python/EC7.asciidoc
index dba3dd847..4ca4240e5 100644
--- a/python-plugin/src/main/resources/fr/greencodeinitiative/l10n/python/rules/python/EC7.html
+++ b/ecocode-rules-specifications/src/main/rules/EC7/python/EC7.asciidoc
@@ -1,6 +1,8 @@
-
Avoid using getters and setters in a class, as they increase unnecessary RAM memory usage.
-
Noncompliant Code Example
-
+Avoid using getters and setters in a class, as they increase unnecessary RAM memory usage.
+
+## Noncompliant Code Example
+
+```python
class Client():
def __init__(self, age):
@@ -15,10 +17,11 @@
If we are using too many conditional if-else statements it will impact performance since JVM will have to compare the conditions. We can think of using a switch statement instead of multiple if-else if possible. Switch statement has a performance advantage over if – else.
-
-
Non-compliant Code Example
-
- int index = 1;
- int nb = 2;
-
- if (nb > index) {
- nb = nb + index;
- } else {
- nb = nb - 1;
- }
- if (nb != index + 1) {
- nb = nb + index;
- } else {
- nb = nb - 1;
- }
-
-
-
-
Compliant Code Example
-
- int index = 1;
- int nb = 2;
-
- if (nb > index) {
- nb = nb + index;
- } else {
- nb = nb - 1;
- }
-
- 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.
- For example, an array copy is potentially a non-performance source if it is poorly designed. Indeed, the use of a single copy loop can be twice as consuming as dedicated methods.
- Loops must be optimized to reduce processing time and make full use of hardware and processor mechanisms and optimizations.
- In the case of table copying (table), the native System.arraycopy.
- We can also use copyOf or clone that are slightly less efficient.
- The looping method will be outlawed.
-
-
Noncompliant Code Example
-
- int len = array.length;
- boolean[] copy = new boolean[array.length];
- for (int i = 0; i < len; i++) {
- copy[i] = array[i]; // Noncompliant
- }
- return copy;
-
When iterating over any collection, fetch the size of the collection in advance to avoid fetching it on each iteration, this saves CPU cycles, and therefore consumes less power. The example provided below illustrates what should be avoided.
-
Noncompliant Code Example
-
- List<String> objList = getData();
-
- for (int i = 0; i < objList.size(); i++) { // Noncompliant
- // execute code
- }
-
-
-
Compliant Solution
-
- List<String> objList = getData();
-
- int size = objList.size();
- for (int i = 0; i < size; i++) {
- // execute code
- }
-
- If you know in advance how many characters would be appended, initialize builder/buffer with the appropriate size.
- They will thus never have to be resized.
- This saves CPU cycles and therefore consumes less energy.
-
-
Noncompliant Code Example
-
- StringBuilder sb = new StringBuilder(); // Noncompliant
- for (int i = 0; i < 100; i++) {
- sb.append(...);
- }
-
-
Compliant Solution
-
- StringBuilder sb = new StringBuilder(100);
- for (int i = 0; i < 100; i++) {
- sb.append(...);
- }
-
When calling a global variable, the interpretation engine must check that it exists in all the scopes, that it has a value, etc. Passing global variables as arguments gives them the status of local variables inside the function, thus saving computing time (CPU cycles).
-
-
-CASE 1 (Avoid as possible):
-You are back on the service code. You see that the func1() uses globalVariabl1. Okay, but whats its value by now ? How does it change ? Who mutates the globalVariabl1 before it comes to this function ? What have been the sequence of all these mutations ? You would have no idea. It will be quite difficult to figure all this out.
-
-CASE 2 (Recommended):
-You are back to you code, and see that the func0() fetches something and then passes it to func1(param1) as a parameter. You clearly know what the data is, how does it gets here.
-
-
Noncompliant Code Example
-
- var aGlobal = new String('Hello');
-
- function globalLength(){
- length = aGlobal.length;
- console.log(length);
- }
-
- globalLength();
-
-
Compliant Solution
-
- var aGlobal = new String('Hello');
-
- function someVarLength(str){
- length = str.length;
- console.log(length);
- }
-
- somVarLength(aGlobal);
-
\ No newline at end of file
diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC5.html b/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC5.html
deleted file mode 100644
index 3fd5bb834..000000000
--- a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC5.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
Use PreparedStatement instead of Statement, because 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.
- Don't concatenate Strings in loop. User StringBuilder instead.
- Strings are immutable so each time you concatenate a String, a new String is created. This is a waste of memory and CPU.
-
-
-
Noncompliant Code Example
-
-
- public String concatenateStrings(String[] strings) {
- String result = "";
-
- for (String string : strings) {
- result += string; // Noncompliant
- }
- return result;
- }
-
- public String concatenateStrings2() {
- String result = "";
-
- for (int i = 0; i < 1000; ++i) {
- result += "another"; // Noncompliant
- }
- return result;
- }
-
-
-
-
Compliant Solution
-
-
- public String concatenateStrings(String[] strings) {
- StringBuilder result = new StringBuilder();
-
- for (String string : strings) {
- result.append(string);
- }
- return result.toString();
- }
-
-
- Avoid usage of static collections.
- If you want to use static collections make them final and create for example a singleton if needed containing the collections.
- The static fields are more complicated for the Garbage Collector to manage and can lead to memory leaks.
-
-
-
Noncompliant Code Example
-
-
- /**
- * Not compliant
- */
- public class AvoidUsageOfStaticCollections {
- public static final List<> LIST = new ArrayList<>();
- public static final Set<> SET = new HashSet<>();
- public static final Map<> MAP = new HashMap<>();
- }
-
-
-
-
Compliant Solution
-
-
- /**
- * Compliant
- */
- public class GoodUsageOfStaticCollections {
- public static volatile GoodUsageOfStaticCollections INSTANCE = new GoodUsageOfStaticCollections();
-
- public final List<> LIST = new ArrayList<>();
- public final Set<> SET = new HashSet<>();
- public final Map<> MAP = new HashMap<>();
-
- private GoodUsageOfStaticCollections() {
- }
- }
-
-
\ No newline at end of file
diff --git a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC77.html b/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC77.html
deleted file mode 100644
index f0aed4f4f..000000000
--- a/java-plugin/src/main/resources/fr/greencodeinitiative/l10n/java/rules/java/EC77.html
+++ /dev/null
@@ -1,67 +0,0 @@
-
- Avoid using Pattern.compile() in a non-static context.
- This operation requires a significant amount of computational power, Using a single match saves CPU cycles and RAM consumption.
-
-
-
Noncompliant Code Example
-
-
- public class AvoidRegexPatternNotStatic {
-
- public boolean foo() {
- final Pattern pattern = Pattern.compile("foo"); // Noncompliant
- return pattern.matcher("foo").find();
- }
-
- }
-
-
-
-
Compliant Solution N°1
-
-
- public class ValidRegexPattern {
-
- private static final Pattern pattern = Pattern.compile("foo"); // Compliant
-
- public boolean foo() {
- return pattern.matcher("foo").find();
- }
-
- }
-
-
-
-
Compliant Solution N°2
-
-
- public class ValidRegexPattern2 {
-
- private final Pattern pattern = Pattern.compile("foo"); // Compliant
-
- public boolean foo() {
- return pattern.matcher("foo").find();
- }
-
- }
-
-
-
-
Compliant Solution N°3
-
-
- public class ValidRegexPattern3 {
-
- private final Pattern pattern;
-
- public ValidRegexPattern3() {
- pattern = Pattern.compile("foo"); // Compliant
- }
-
- public boolean foo() {
- return pattern.matcher("foo").find();
- }
-
- }
-
-
When iterating over any collection, fetch the size of the collection in advance to avoid fetching it on each iteration, this saves CPU cycles, and therefore consumes less power.
-
NB : note that we are using the count() method to get the size of an array but it would work the same with the sizeof() and iterator_count() methods
-
-
Noncompliant Code Examples
-
- $array = array('orange', 'banana', 'apple', 'carrot', 'collard', 'pea');
-
- // FOR STATEMENTS / Right operand
- for ($i = 0; $i < count($array); ++$i) {
- var_dump($array[$i]);
- }
-
- // FOR STATEMENTS / Left operand
- for ($i = 0; count($array) > $i; ++$i) {
- var_dump($array[$i]);
- }
-
- // WHILE STATEMENTS / Right operand
- $i = 0;
- while($i < count($array)) {
- var_dump($array[$i]);
- ++$i;
- }
-
- // WHILE STATEMENTS / Left operand
- $i = 0;
- while(count($array) > $i) {
- var_dump($array[$i]);
- ++$i;
- }
-
- // DO WHILE STATEMENTS / Right operand
- $i = 0;
- do {
- var_dump($array[$i]);
- ++$i;
- } while ($i < count($array));
-
- // DO WHILE STATEMENTS / Left operand
- $i = 0;
- do {
- var_dump($array[$i]);
- ++$i;
- } while (count($array) > $i);
-
-
-
Compliant Solution
-
- $array = array('orange', 'banana', 'apple', 'carrot', 'collard', 'pea');
- // FOR STATEMENTS / Right operand
- $size = sizeof($array);
- for ($i = 0; $i < $size; ++$i) {
- var_dump($array[$i]);
- }
-
- // FOR STATEMENTS / Left operand
- $size = sizeof($array);
- for ($i = 0; $size > $i; ++$i) {
- var_dump($array[$i]);
- }
-
- // WHILE STATEMENTS / Right operand
- $i = 0;
- $size = count($array);
- while($i < $size) {
- var_dump($array[$i]);
- ++$i;
- }
-
- // WHILE STATEMENTS / Left operand
- $i = 0;
- $size = count($array);
- while($size > $i) {
- var_dump($array[$i]);
- ++$i;
- }
-
- // DO WHILE STATEMENTS / Right operand
- $i = 0;
- $size = count($array);
- do {
- var_dump($array[$i]);
- ++$i;
- } while ($i < $size);
-
- // DO WHILE STATEMENTS / Left operand
- $i = 0;
- $size = count($array);
- do {
- var_dump($array[$i]);
- ++$i;
- } while ($size > $i);
-
Inside complex code parts (for exemple multiple loops, complex data constructions...), avoid using try...catch...finally.
-
When an exception is thrown, a variable (the exception itself) is created in a catch block and it's destruction consumes unnecessary CPU cycles and RAM. Prefer using logical tests in this cases.
-
Noncompliant Code Example
-
-try
-{
- $picture = PDF_open_image_file($PDF, "jpeg", $imgFile, "", 0); // This is the original statement, this works on PHP4
-}
-catch(Exception $ex)
-{
- $msg = "Error opening $imgFile for Product $row['Identifier']";
- throw new Exception($msg);
-}
-
-
The three sources of impacts of a code identified are:
-- Energy (measured in joules)
- - Transfer (measured in Bytes)
- - Storage (measured in Bytes)
- The control of these 3 impacts allows to lengthen the life of the terminals as well as reduce their energy consumption.
- The ETSdiff tool allows measuring a differential on these three values and in a given context (database and fixed measurement environment).
- The results generated by ETSdiff must help define the interest of the rule reported by Sonarqube in the context of the code analyzed.
-
-
When calling a global variable, the interpretation engine must check that it exists in all the scopes, that it has a value, etc. Passing global variables as arguments gives them the status of local variables inside the function, thus saving computing time (CPU cycles).
-
-
Noncompliant Code Example
-
- var aGlobal = new String('Hello');
-
- function globalLength(){
- length = aGlobal.length;
- console.log(length);
- }
-
- globalLength();
-
-
Compliant Solution
-
- var aGlobal = new String('Hello');
-
- function someVarLength(str){
- length = str.length;
- console.log(length);
- }
-
- somVarLength(aGlobal);
-
\ No newline at end of file
diff --git a/php-plugin/src/main/resources/fr/greencodeinitiative/l10n/php/rules/custom/EC66.html b/php-plugin/src/main/resources/fr/greencodeinitiative/l10n/php/rules/custom/EC66.html
deleted file mode 100644
index 233604feb..000000000
--- a/php-plugin/src/main/resources/fr/greencodeinitiative/l10n/php/rules/custom/EC66.html
+++ /dev/null
@@ -1,94 +0,0 @@
-
PHP allows declaring a string with simple or double quotes. Using double quotes allows developers to insert variables which will be substituted during execution. When the string has no variables, using single quotes prevents PHP from searching for non-existent variables. It will save CPU cycles consumption and RAM usage.
-
Noncompliant Code Example
-
-myFunction("name", "age", "IsStudent");
- $lastName = "Hugo";
- $concatenatedString = "$lastName is a student";
-
The three sources of impacts of a code identified are:
-- Energy (measured in joules)
- - Transfer (measured in Bytes)
- - Storage (measured in Bytes)
- The control of these 3 impacts allows to lengthen the life of the terminals as well as reduce their energy consumption.
- The ETSdiff tool allows measuring a differential on these three values and in a given context (database and fixed measurement environment).
- The results generated by ETSdiff must help define the interest of the rule reported by Sonarqube in the context of the code analyzed.
-
-
The form $i++ creates a temporary variable whereas ++$i does not. It save CPU cycles.
-
Noncompliant Code Example
-
-$i++
-
-
Compliant Solution
-
++$i
-
The three sources of impacts of a code identified are:
-- Energy (measured in joules)
- - Transfer (measured in Bytes)
- - Storage (measured in Bytes)
- The control of these 3 impacts allows to lengthen the life of the terminals as well as reduce their energy consumption.
- The ETSdiff tool allows measuring a differential on these three values and in a given context (database and fixed measurement environment).
- The results generated by ETSdiff must help define the interest of the rule reported by Sonarqube in the context of the code analyzed.
-
-
Case for a 1GB database:
-
-
Total:
-
-
-
-
-
-
-
Compliant
-
-
-
-
-
Non-compliant
-
-
-
-
-
-
-
Energy
-
-
-
-
-
1.8163645000000002
-
-
-
-
-
0.2613885000000001
-
-
-
-
-
-
-
Transfer
-
-
-
-
-
11265758
-
-
-
-
-
11290494
-
-
-
-
-
-
-
Storage
-
-
-
-
-
637548673
-
-
-
-
-
637548673
-
-
-
-
-
\ No newline at end of file
diff --git a/php-plugin/src/main/resources/fr/greencodeinitiative/l10n/php/rules/custom/EC69.html b/php-plugin/src/main/resources/fr/greencodeinitiative/l10n/php/rules/custom/EC69.html
deleted file mode 100644
index c71d96a37..000000000
--- a/php-plugin/src/main/resources/fr/greencodeinitiative/l10n/php/rules/custom/EC69.html
+++ /dev/null
@@ -1,104 +0,0 @@
-
Do not call a function when declaring a for-type loop in order to avoid function calls each iteration. It saves CPU cycles.
The three sources of impacts of a code identified are:
-- Energy (measured in joules)
- - Transfer (measured in Bytes)
- - Storage (measured in Bytes)
- The control of these 3 impacts allows to lengthen the life of the terminals as well as reduce their energy consumption.
- The ETSdiff tool allows measuring a differential on these three values and in a given context (database and fixed measurement environment).
- The results generated by ETSdiff must help define the interest of the rule reported by Sonarqube in the context of the code analyzed.
-
-
-
Executing SQL queries in loop induced unnecessary network transfert, calculation by the cpu and RAM usage.
-
Noncompliant Code Example
-
- public function foo() {
- ...
- $baseQuery = "SELECT name FROM users where id = ";
-
- for ($i = 0; $i < 20; ++$i) {
-
- $query = $baseQuery . $i;
- $connection = mysql_connect($dbhost, $dbuser, $dbpass) or die("Unable to Connect to '$dbhost'");
- mysql_select_db($dbname) or die("Could not open the db '$dbname'");
- $result = mysql_query($this->Query);// Noncompliant
-
- // iterate through the result
- ...
- mysql_close($connection);
- }
- ...
- }
-
-
-
Compliant Solution
-
-
- public function foo() {
- ...
- $query = "SELECT name FROM users where id in (";
-
- for ($i = 0; $i < 20; ++$i) {
- $query .= ',' . $i;
- }
- $query .= ')';
-
- $connection = mysql_connect($dbhost, $dbuser, $dbpass) or die("Unable to Connect to '$dbhost'");
- mysql_select_db($dbname) or die("Could not open the db '$dbname'");
- $result = mysql_query($this->Query); // compliant
-
- // iterate through the result
- ...
- mysql_close($connection);
- }
-
-
-
-
The three sources of impacts of a code identified are:
- - Energy (measured in joules)
- - Transfer (measured in Bytes)
- - Storage (measured in Bytes)
- The control of these 3 impacts allows to lengthen the life of the terminals as well as reduce their energy consumption.
- The ETSdiff tool allows measuring a differential on these three values and in a given context (database and fixed measurement environment).
- The results generated by ETSdiff must help define the interest of the rule reported by Sonarqube in the context of the code analyzed.
-
-
-
Case for a 1GB database:
-
-
Total:
-
-
-
-
-
-
-
Compliant
-
-
-
-
-
Non-compliant
-
-
-
-
-
-
-
Energy
-
-
-
-
-
73.907586
-
-
-
-
-
82.15627099999998
-
-
-
-
-
-
-
Transfer
-
-
-
-
-
49526
-
-
-
-
-
221836
-
-
-
-
-
-
-
Storage
-
-
-
-
-
637549572
-
-
-
-
-
637549572
-
-
-
-
-
-
-
Case for a 2GB database:
-
-
Total:
-
-
-
-
-
-
-
Compliant
-
-
-
-
-
Non-compliant
-
-
-
-
-
-
-
Energy
-
-
-
-
-
159.4871645
-
-
-
-
-
169.746055
-
-
-
-
-
-
-
Transfer
-
-
-
-
-
50385
-
-
-
-
-
228225
-
-
-
-
-
-
-
Storage
-
-
-
-
-
1178614788
-
-
-
-
-
1178614788
-
-
-
-
-
-
-
Case for a 4GB database:
-
-
Total:
-
-
-
-
-
-
-
Compliant
-
-
-
-
-
Non-compliant
-
-
-
-
-
-
-
Energy
-
-
-
-
-
395.7629349999999
-
-
-
-
-
404.37447649999996
-
-
-
-
-
-
-
Transfer
-
-
-
-
-
51597
-
-
-
-
-
238884
-
-
-
-
-
-
-
Storage
-
-
-
-
-
2357214212
-
-
-
-
-
2357214212
-
-
-
-
-
-
-
Case for a 8GB database:
-
-
Total:
-
-
-
-
-
-
-
Compliant
-
-
-
-
-
Non-compliant
-
-
-
-
-
-
-
Energy
-
-
-
-
-
992.128585
-
-
-
-
-
1005.4625534999999
-
-
-
-
-
-
-
Transfer
-
-
-
-
-
52189
-
-
-
-
-
249499
-
-
-
-
-
-
-
Storage
-
-
-
-
-
4685052932
-
-
-
-
-
4685052932
-
-
-
-
-
\ No newline at end of file
diff --git a/php-plugin/src/main/resources/fr/greencodeinitiative/l10n/php/rules/custom/EC74.html b/php-plugin/src/main/resources/fr/greencodeinitiative/l10n/php/rules/custom/EC74.html
deleted file mode 100644
index de53be78e..000000000
--- a/php-plugin/src/main/resources/fr/greencodeinitiative/l10n/php/rules/custom/EC74.html
+++ /dev/null
@@ -1,101 +0,0 @@
-
Database servers have to resolve schema fields when using asterisk symbol (*). Knowing and using the schema saves CPU cycles and network transfer.
-
Noncompliant Code Example
-
- public function foo() {
- ...
- $baseQuery = "SELECT * FROM users"; // Noncompliant
-
- ...
- }
-
-
Compliant Solution
-
- public function foo() {
- ...
- $baseQuery = "SELECT id,name, address FROM users ";
- ...
- }
-
-
The three sources of impacts of a code identified are:
-- Energy (measured in joules)
- - Transfer (measured in Bytes)
- - Storage (measured in Bytes)
- The control of these 3 impacts allows to lengthen the life of the terminals as well as reduce their energy consumption.
- The ETSdiff tool allows measuring a differential on these three values and in a given context (database and fixed measurement environment).
- The results generated by ETSdiff must help define the interest of the rule reported by Sonarqube in the context of the code analyzed.
-
-
-
Case for a 1GB database:
-
-
-
Total:
-
-
-
-
-
-
-
Compliant
-
-
-
-
-
Non-compliant
-
-
-
-
-
-
-
Energy
-
-
-
-
-
0.040610499999999994
-
-
-
-
-
0.065223
-
-
-
-
-
-
-
Transfer
-
-
-
-
-
779232
-
-
-
-
-
2697937
-
-
-
-
-
-
-
Storage
-
-
-
-
-
637548827
-
-
-
-
-
637548827
-
-
-
-
-
diff --git a/php-plugin/src/test/java/fr/greencodeinitiative/php/PhpPluginTest.java b/php-plugin/src/test/java/fr/greencodeinitiative/php/PhpPluginTest.java
index 33736bc4c..9139c7c4e 100644
--- a/php-plugin/src/test/java/fr/greencodeinitiative/php/PhpPluginTest.java
+++ b/php-plugin/src/test/java/fr/greencodeinitiative/php/PhpPluginTest.java
@@ -16,20 +16,26 @@
*/
package fr.greencodeinitiative.php;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.sonar.api.Plugin;
import org.sonar.api.SonarRuntime;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
-public class PhpPluginTest {
+class PhpPluginTest {
+ private Plugin.Context context;
- @Test
- public void test() {
+ @BeforeEach
+ void init() {
SonarRuntime sonarRuntime = mock(SonarRuntime.class);
- Plugin.Context context = new Plugin.Context(sonarRuntime);
+ context = new Plugin.Context(sonarRuntime);
new PHPPlugin().define(context);
+ }
+
+ @Test
+ void test() {
assertThat(context.getExtensions()).hasSize(1);
}
diff --git a/php-plugin/src/test/java/fr/greencodeinitiative/php/PhpRuleRepositoryTest.java b/php-plugin/src/test/java/fr/greencodeinitiative/php/PhpRuleRepositoryTest.java
index 70ef4cae8..32495c4e1 100644
--- a/php-plugin/src/test/java/fr/greencodeinitiative/php/PhpRuleRepositoryTest.java
+++ b/php-plugin/src/test/java/fr/greencodeinitiative/php/PhpRuleRepositoryTest.java
@@ -16,42 +16,88 @@
*/
package fr.greencodeinitiative.php;
-import static org.assertj.core.api.Assertions.assertThat;
import org.assertj.core.api.SoftAssertions;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.sonar.api.SonarRuntime;
import org.sonar.api.server.rule.RulesDefinition;
+import org.sonar.api.utils.Version;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+class PhpRuleRepositoryTest {
-public class PhpRuleRepositoryTest {
+ private RulesDefinition.Repository repository;
- private PhpRuleRepository phpRuleRepository;
- private RulesDefinition.Context context;
+ @BeforeEach
+ void init() {
+ // TODO: Remove this check after Git repo split
+ /*
+ On an IDE (like IntelliJ), if the developer runs the unit tests without building/generating the Maven goals on the
+ "ecocode-rules-specifications" module before, the unit tests will not see the generated HTML descriptions (from ASCIIDOC files).
+ The developer must therefore configure his IDE to build the `ecocode-rules-specifications` module before launching the Tests.
+
+ When the `php-plugin` submodule is in a specific Git repository, `ecocode-rules-specifications` will be fetched from a classic
+ external Maven dependency. There will therefore no longer be any need to perform this specific configuration.
+ */
+ if (PhpRuleRepository.class.getResource("/io/ecocode/rules/php/EC4.json") == null) {
+ String message = "'ecocode-rules-specification' resources corrupted. Please check build of 'ecocode-rules-specification' module";
+ if (System.getProperties().keySet().stream().anyMatch(k -> k.toString().startsWith("idea."))) {
+ message += "\n\nOn 'IntelliJ IDEA':" +
+ "\n1. go to settings :" +
+ "\n > Build, Execution, Deployment > Build Tools > Maven > Runner" +
+ "\n2. check option:" +
+ "\n > Delegate IDE build/run actions to Maven" +
+ "\n3. Click on menu: " +
+ "\n > Build > Build Project"
+ ;
+ }
+ fail(message);
+ }
+
+ final SonarRuntime sonarRuntime = mock(SonarRuntime.class);
+ doReturn(Version.create(0, 0)).when(sonarRuntime).getApiVersion();
+ PhpRuleRepository rulesDefinition = new PhpRuleRepository(sonarRuntime);
+ RulesDefinition.Context context = new RulesDefinition.Context();
+ rulesDefinition.define(context);
+ repository = context.repository(rulesDefinition.repositoryKey());
+ }
- @Before
- public void init() {
- phpRuleRepository = new PhpRuleRepository();
- context = new RulesDefinition.Context();
- phpRuleRepository.define(context);
+ @Test
+ @DisplayName("Test repository metadata")
+ void testMetadata() {
+ assertThat(repository.name()).isEqualTo("ecoCode");
+ assertThat(repository.language()).isEqualTo("php");
+ assertThat(repository.key()).isEqualTo("ecocode-php");
}
@Test
- public void test() {
- assertThat(phpRuleRepository.repositoryKey()).isEqualTo(PhpRuleRepository.REPOSITORY_KEY);
- assertThat(context.repositories()).hasSize(1).extracting("key").containsExactly(phpRuleRepository.repositoryKey());
- assertThat(context.repositories().get(0).rules()).hasSize(9);
- assertThat(phpRuleRepository.checkClasses()).hasSize(9);
+ void testRegistredRules() {
+ assertThat(repository.rules()).hasSize(9);
}
- /**
- * Check all rule keys must be prefixed by 'EC'
- */
- @Test()
- public void testRuleKeyPrefix() {
- RulesDefinition.Repository repository = context.repository(PhpRuleRepository.REPOSITORY_KEY);
+ @Test
+ @DisplayName("All rule keys must be prefixed by 'EC'")
+ void testRuleKeyPrefix() {
SoftAssertions assertions = new SoftAssertions();
repository.rules().forEach(
rule -> assertions.assertThat(rule.key()).startsWith("EC")
);
assertions.assertAll();
}
+
+ @Test
+ void testAllRuleParametersHaveDescription() {
+ SoftAssertions assertions = new SoftAssertions();
+ repository.rules().stream()
+ .flatMap(rule -> rule.params().stream())
+ .forEach(param -> assertions.assertThat(param.description())
+ .as("description for " + param.key())
+ .isNotEmpty());
+ assertions.assertAll();
+ }
}
diff --git a/pom.xml b/pom.xml
index 7b1750006..0a13b79b0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,6 +23,7 @@
+ ecocode-rules-specificationspython-pluginjava-pluginjavascript-plugin
diff --git a/python-plugin/pom.xml b/python-plugin/pom.xml
index 3447d148a..b2a7d6e60 100644
--- a/python-plugin/pom.xml
+++ b/python-plugin/pom.xml
@@ -16,16 +16,24 @@
https://github.com/green-code-initiative/ecoCode/tree/main/python-plugin
+
+ ${project.groupId}
+ ecocode-rules-specifications
+ ${project.version}
+ python
+ org.sonarsource.pythonsonar-python-pluginsonar-plugin
+ providedorg.sonarsource.sonarqubesonar-plugin-api
+ provided
@@ -63,6 +71,11 @@
${java.version}
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ org.apache.maven.pluginsmaven-dependency-plugin
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 2718b28f0..23ff4f51e 100644
--- a/python-plugin/src/main/java/fr/greencodeinitiative/python/PythonRuleRepository.java
+++ b/python-plugin/src/main/java/fr/greencodeinitiative/python/PythonRuleRepository.java
@@ -17,58 +17,32 @@
package fr.greencodeinitiative.python;
import fr.greencodeinitiative.python.checks.*;
-import org.sonar.api.rules.RuleType;
+import org.sonar.api.SonarRuntime;
import org.sonar.api.server.rule.RulesDefinition;
-import org.sonar.api.server.rule.RulesDefinitionAnnotationLoader;
import org.sonar.plugins.python.api.PythonCustomRuleRepository;
+import org.sonarsource.analyzer.commons.RuleMetadataLoader;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
public class PythonRuleRepository implements RulesDefinition, PythonCustomRuleRepository {
public static final String LANGUAGE = "py";
public static final String NAME = "ecoCode";
- public static final String RESOURCE_BASE_PATH = "/fr/greencodeinitiative/l10n/python/rules/python/";
+ public static final String RESOURCE_BASE_PATH = "io/ecocode/rules/python";
public static final String REPOSITORY_KEY = "ecocode-python";
- @Override
- public void define(Context context) {
- NewRepository repository = context.createRepository(repositoryKey(), LANGUAGE).setName(NAME);
-
- new RulesDefinitionAnnotationLoader().load(repository, checkClasses().toArray(new Class[] {}));
-
- // technical debt
- Map remediationCosts = new HashMap<>();
- remediationCosts.put(AvoidSQLRequestInLoop.RULE_KEY, "10min");
- remediationCosts.put(AvoidFullSQLRequest.RULE_KEY, "20min");
- repository.rules().forEach(rule -> {
- rule.setType(RuleType.CODE_SMELL);
- String debt = remediationCosts.get(rule.key());
-
- // TODO DDC : create support to use org.apache.commons.lang.StringUtils
-// if (StringUtils.isBlank(debt)) {
- if (debt == null || debt.trim().equals("")) {
- // default debt to 5min for issue correction
- rule.setDebtRemediationFunction(
- rule.debtRemediationFunctions().constantPerIssue("5min"));
- } else {
- rule.setDebtRemediationFunction(
- rule.debtRemediationFunctions().constantPerIssue(debt));
- }
- });
+ private final SonarRuntime sonarRuntime;
- // HTML description
- repository.rules().forEach(rule ->
- rule.setHtmlDescription(loadResource(RESOURCE_BASE_PATH + rule.key() + ".html")));
+ public PythonRuleRepository(SonarRuntime sonarRuntime) {
+ this.sonarRuntime = sonarRuntime;
+ }
+ @Override
+ public void define(Context context) {
+ NewRepository repository = context.createRepository(REPOSITORY_KEY, LANGUAGE).setName(NAME);
+ RuleMetadataLoader ruleMetadataLoader = new RuleMetadataLoader(RESOURCE_BASE_PATH, sonarRuntime);
+ ruleMetadataLoader.addRulesByAnnotatedClass(repository, (List) checkClasses());
repository.done();
}
@@ -92,21 +66,4 @@ public List checkClasses() {
DetectUnoptimizedImageFormat.class
);
}
-
- private String loadResource(String path) {
- URL resource = getClass().getResource(path);
- if (resource == null) {
- throw new IllegalStateException("Resource not found: " + path);
- }
- ByteArrayOutputStream result = new ByteArrayOutputStream();
- try (InputStream in = resource.openStream()) {
- byte[] buffer = new byte[1024];
- for (int len = in.read(buffer); len != -1; len = in.read(buffer)) {
- result.write(buffer, 0, len);
- }
- return new String(result.toByteArray(), StandardCharsets.UTF_8);
- } catch (IOException e) {
- throw new IllegalStateException("Failed to read resource: " + path, e);
- }
- }
}
diff --git a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidDoubleQuoteCheck.java b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidDoubleQuoteCheck.java
index 033c468d1..e6b191289 100644
--- a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidDoubleQuoteCheck.java
+++ b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidDoubleQuoteCheck.java
@@ -1,20 +1,13 @@
package fr.greencodeinitiative.python.checks;
-import org.sonar.check.Priority;
import org.sonar.check.Rule;
import org.sonar.plugins.python.api.PythonSubscriptionCheck;
import org.sonar.plugins.python.api.SubscriptionContext;
import org.sonar.plugins.python.api.tree.StringLiteral;
import org.sonar.plugins.python.api.tree.Tree;
-@Rule(
- key = AvoidDoubleQuoteCheck.RULE_KEY,
- name = AvoidDoubleQuoteCheck.MESSAGE_RULE,
- description = AvoidDoubleQuoteCheck.MESSAGE_RULE,
- priority = Priority.MINOR,
- tags = {"eco-design", "ecocode", "bad-practice"})
+@Rule(key = "EC66")
public class AvoidDoubleQuoteCheck extends PythonSubscriptionCheck {
- public static final String RULE_KEY = "EC66";
public static final String MESSAGE_RULE = "Avoid using quotation mark (\"), prefer using simple quote (')";
@Override
public void initialize(Context context) {
diff --git a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidFullSQLRequest.java b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidFullSQLRequest.java
index 77c5f43be..8c6d4eedf 100644
--- a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidFullSQLRequest.java
+++ b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidFullSQLRequest.java
@@ -7,7 +7,6 @@
import java.util.Map;
import java.util.regex.Pattern;
-import org.sonar.check.Priority;
import org.sonar.check.Rule;
import org.sonar.plugins.python.api.PythonSubscriptionCheck;
import org.sonar.plugins.python.api.SubscriptionContext;
@@ -16,17 +15,10 @@
import org.sonar.plugins.python.api.tree.Tree;
import org.sonarsource.analyzer.commons.annotations.DeprecatedRuleKey;
-@Rule(
- key = AvoidFullSQLRequest.RULE_KEY,
- name = AvoidFullSQLRequest.MESSAGERULE,
- description = AvoidFullSQLRequest.MESSAGERULE,
- priority = Priority.MINOR,
- tags = {"sql", "performance", "eco-design", "ecocode"})
+@Rule(key = "EC74")
@DeprecatedRuleKey(repositoryKey = "gci-python", ruleKey = "S74")
public class AvoidFullSQLRequest extends PythonSubscriptionCheck {
- public static final String RULE_KEY = "EC74";
-
protected static final String MESSAGERULE = "Don't use the query SELECT * FROM";
// TODO DDC : create support to add in deployment th dependency com.google.re2j:re2j
diff --git a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidGettersAndSetters.java b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidGettersAndSetters.java
index fc1dddca4..beb063de7 100644
--- a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidGettersAndSetters.java
+++ b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidGettersAndSetters.java
@@ -3,7 +3,6 @@
import java.util.List;
import java.util.stream.Collectors;
-import org.sonar.check.Priority;
import org.sonar.check.Rule;
import org.sonar.plugins.python.api.PythonSubscriptionCheck;
import org.sonar.plugins.python.api.SubscriptionContext;
@@ -18,16 +17,10 @@
import org.sonar.plugins.python.api.tree.Tree;
import org.sonarsource.analyzer.commons.annotations.DeprecatedRuleKey;
-@Rule(
- key = AvoidGettersAndSetters.RULE_KEY,
- name = AvoidGettersAndSetters.DESCRIPTION,
- description = AvoidGettersAndSetters.DESCRIPTION,
- priority = Priority.MINOR,
- tags = {"convention", "eco-design", "ecocode"})
+@Rule(key = "EC7")
@DeprecatedRuleKey(repositoryKey = "gci-python", ruleKey = "D7")
public class AvoidGettersAndSetters extends PythonSubscriptionCheck {
- public static final String RULE_KEY = "EC7";
public static final String DESCRIPTION = "Avoid creating getter and setter methods in classes";
@Override
diff --git a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidGlobalVariableInFunctionCheck.java b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidGlobalVariableInFunctionCheck.java
index ab4302bbd..82bc46b74 100644
--- a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidGlobalVariableInFunctionCheck.java
+++ b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidGlobalVariableInFunctionCheck.java
@@ -5,7 +5,6 @@
import java.util.List;
import java.util.Map;
-import org.sonar.check.Priority;
import org.sonar.check.Rule;
import org.sonar.plugins.python.api.PythonSubscriptionCheck;
import org.sonar.plugins.python.api.SubscriptionCheck;
@@ -62,16 +61,10 @@
import org.sonar.plugins.python.api.tree.YieldStatement;
import org.sonarsource.analyzer.commons.annotations.DeprecatedRuleKey;
-@Rule(
- key = AvoidGlobalVariableInFunctionCheck.RULE_KEY,
- name = "Do not call global variables directly inside functions",
- description = AvoidGlobalVariableInFunctionCheck.DESCRIPTION,
- priority = Priority.MINOR,
- tags = {"performance", "eco-design", "ecocode"})
+@Rule(key = "EC4")
@DeprecatedRuleKey(repositoryKey = "gci-python", ruleKey = "D4")
public class AvoidGlobalVariableInFunctionCheck extends PythonSubscriptionCheck {
- public static final String RULE_KEY = "EC4";
public static final String DESCRIPTION = "Use local variable (function/class scope) instead of global variable (application scope)";
private List globalVariables;
diff --git a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidListComprehensionInIterations.java b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidListComprehensionInIterations.java
index 5cb64346d..917d053c9 100644
--- a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidListComprehensionInIterations.java
+++ b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidListComprehensionInIterations.java
@@ -1,6 +1,5 @@
package fr.greencodeinitiative.python.checks;
-import org.sonar.check.Priority;
import org.sonar.check.Rule;
import org.sonar.plugins.python.api.PythonSubscriptionCheck;
import org.sonar.plugins.python.api.SubscriptionContext;
@@ -18,15 +17,9 @@
import static org.sonar.plugins.python.api.tree.Tree.Kind.LIST_COMPREHENSION;
import static org.sonar.plugins.python.api.tree.Tree.Kind.REGULAR_ARGUMENT;
-@Rule(
- key = AvoidListComprehensionInIterations.RULE_KEY,
- name = AvoidListComprehensionInIterations.DESCRIPTION,
- description = AvoidListComprehensionInIterations.DESCRIPTION,
- priority = Priority.MINOR,
- tags = {"eco-design", "ecocode", "performance"})
+@Rule(key = "EC404")
public class AvoidListComprehensionInIterations extends PythonSubscriptionCheck {
- public static final String RULE_KEY = "EC404";
public static final String DESCRIPTION = "Use generator comprehension instead of list comprehension in for loop declaration";
@Override
diff --git a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidSQLRequestInLoop.java b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidSQLRequestInLoop.java
index 7a7c1187e..a2bb20786 100644
--- a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidSQLRequestInLoop.java
+++ b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidSQLRequestInLoop.java
@@ -6,7 +6,6 @@
import java.util.Objects;
import java.util.Set;
-import org.sonar.check.Priority;
import org.sonar.check.Rule;
import org.sonar.plugins.python.api.PythonSubscriptionCheck;
import org.sonar.plugins.python.api.SubscriptionContext;
@@ -20,17 +19,10 @@
import org.sonar.plugins.python.api.tree.Tree;
import org.sonarsource.analyzer.commons.annotations.DeprecatedRuleKey;
-@Rule(
- key = AvoidSQLRequestInLoop.RULE_KEY,
- name = "Avoid SQL request in loop",
- description = AvoidSQLRequestInLoop.MESSAGE_RULE,
- priority = Priority.MINOR,
- tags = {"sql", "performance", "eco-design", "ecocode"})
+@Rule(key = "EC72")
@DeprecatedRuleKey(repositoryKey = "gci-python", ruleKey = "S72")
public class AvoidSQLRequestInLoop extends PythonSubscriptionCheck {
- public static final String RULE_KEY = "EC72";
-
// TODO: Handle ORM lib
private static final List SQL_LIBS = Arrays.asList("cx_Oracle", "mysql.connector", "psycopg2", "pymssql", "pyodbc", "sqlite3");
diff --git a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidTryCatchFinallyCheck.java b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidTryCatchFinallyCheck.java
index 43ae16492..be801c44d 100644
--- a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidTryCatchFinallyCheck.java
+++ b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidTryCatchFinallyCheck.java
@@ -1,6 +1,5 @@
package fr.greencodeinitiative.python.checks;
-import org.sonar.check.Priority;
import org.sonar.check.Rule;
import org.sonar.plugins.python.api.PythonSubscriptionCheck;
import org.sonar.plugins.python.api.SubscriptionContext;
@@ -8,16 +7,10 @@
import org.sonar.plugins.python.api.tree.TryStatement;
import org.sonarsource.analyzer.commons.annotations.DeprecatedRuleKey;
-@Rule(
- key = AvoidTryCatchFinallyCheck.RULE_KEY,
- name = "Avoid using try-catch statement",
- description = AvoidTryCatchFinallyCheck.DESCRIPTION,
- priority = Priority.MINOR,
- tags = {"error-handling", "performance", "eco-design", "ecocode"})
+@Rule(key = "EC34")
@DeprecatedRuleKey(repositoryKey = "gci-python", ruleKey = "S34")
public class AvoidTryCatchFinallyCheck extends PythonSubscriptionCheck {
- public static final String RULE_KEY = "EC34";
public static final String DESCRIPTION = "Avoid the use of try-catch";
@Override
diff --git a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidUnoptimizedVectorImagesCheck.java b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidUnoptimizedVectorImagesCheck.java
index 5819eeec0..f3a9c3686 100644
--- a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidUnoptimizedVectorImagesCheck.java
+++ b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/AvoidUnoptimizedVectorImagesCheck.java
@@ -3,21 +3,14 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.sonar.check.Priority;
import org.sonar.check.Rule;
import org.sonar.plugins.python.api.PythonSubscriptionCheck;
import org.sonar.plugins.python.api.SubscriptionContext;
import org.sonar.plugins.python.api.tree.*;
-@Rule(
- key = AvoidUnoptimizedVectorImagesCheck.RULE_KEY,
- name = AvoidUnoptimizedVectorImagesCheck.DESCRIPTION,
- description = AvoidUnoptimizedVectorImagesCheck.DESCRIPTION,
- priority = Priority.MINOR,
- tags = {"eco-design", "ecocode"})
+@Rule(key = "EC10")
public class AvoidUnoptimizedVectorImagesCheck extends PythonSubscriptionCheck {
- public static final String RULE_KEY = "EC10";
public static final String DESCRIPTION = "Avoid using unoptimized vector images";
private static final Pattern LAYERS_PATTERN = Pattern.compile("");
diff --git a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/DetectUnoptimizedImageFormat.java b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/DetectUnoptimizedImageFormat.java
index 5cd3c48c7..a69599aed 100644
--- a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/DetectUnoptimizedImageFormat.java
+++ b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/DetectUnoptimizedImageFormat.java
@@ -1,6 +1,5 @@
package fr.greencodeinitiative.python.checks;
-import org.sonar.check.Priority;
import org.sonar.check.Rule;
import org.sonar.plugins.python.api.PythonSubscriptionCheck;
import org.sonar.plugins.python.api.SubscriptionContext;
@@ -10,12 +9,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-@Rule(
- key = DetectUnoptimizedImageFormat.RULE_KEY,
- name = DetectUnoptimizedImageFormat.MESSAGERULE,
- description = DetectUnoptimizedImageFormat.MESSAGEERROR,
- priority = Priority.MINOR,
- tags = {"eco-design", "ecocode", "performance", "user-experience"})
+@Rule(key = "EC203")
public class DetectUnoptimizedImageFormat extends PythonSubscriptionCheck {
protected static final String RULE_KEY = "EC203";
diff --git a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/NoFunctionCallWhenDeclaringForLoop.java b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/NoFunctionCallWhenDeclaringForLoop.java
index 5c7e09f05..b0bf30286 100644
--- a/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/NoFunctionCallWhenDeclaringForLoop.java
+++ b/python-plugin/src/main/java/fr/greencodeinitiative/python/checks/NoFunctionCallWhenDeclaringForLoop.java
@@ -1,22 +1,15 @@
package fr.greencodeinitiative.python.checks;
-import org.sonar.check.Priority;
import org.sonar.check.Rule;
import org.sonar.plugins.python.api.PythonSubscriptionCheck;
import org.sonar.plugins.python.api.tree.CallExpression;
import org.sonar.plugins.python.api.tree.Tree;
import org.sonarsource.analyzer.commons.annotations.DeprecatedRuleKey;
-@Rule(
- key = NoFunctionCallWhenDeclaringForLoop.RULE_KEY,
- name = NoFunctionCallWhenDeclaringForLoop.DESCRIPTION,
- description = NoFunctionCallWhenDeclaringForLoop.DESCRIPTION,
- priority = Priority.MINOR,
- tags = {"performance", "eco-design", "ecocode"})
+@Rule(key = "EC69")
@DeprecatedRuleKey(repositoryKey = "gci-python", ruleKey = "S69")
public class NoFunctionCallWhenDeclaringForLoop extends PythonSubscriptionCheck {
- public static final String RULE_KEY = "EC69";
public static final String DESCRIPTION = "Do not call a function when declaring a for-type loop";
@Override
diff --git a/python-plugin/src/main/resources/fr/greencodeinitiative/l10n/python/rules/python/EC10.html b/python-plugin/src/main/resources/fr/greencodeinitiative/l10n/python/rules/python/EC10.html
deleted file mode 100644
index 131ab21f8..000000000
--- a/python-plugin/src/main/resources/fr/greencodeinitiative/l10n/python/rules/python/EC10.html
+++ /dev/null
@@ -1,47 +0,0 @@
-
SVG images generated by common drawing softwares contains unnecessary data: calc layer, metadata, namespaces and comments.
Inside complex code parts (for example multiple loops, complex data constructions...), avoid using try...catch...finally.
-
When an exception is thrown, a variable (the exception itself) is created in a catch block, and it's destruction consumes unnecessary CPU cycles and RAM. Prefer using logical tests in this cases.
-
-
Noncompliant Code Example
-
-try:
- f = open(path)
- print(fh.read())
-except:
- print('No such file '+path
-finally:
- f.close()
-
-
Use generator comprehension instead of list comprehension in for loop declaration.
-
Python generators resemble lazy lists from other programming languages: when iterated over, they compute their values on the fly. They lack some list behaviors (indexing, len method, ...) but are memory-efficient, as they do not store each of their values in memory, unlike lists. Thus, when declared in a for-loop declaration, list comprehensions can be safely replaced with generator comprehensions.
-
For more details on list comprehensions vs generator comprehensions, see Python documentation.
-
Noncompliant Code Example
-
-for var in [var2 for var2 in range(100)]:
- ...
-
-
Compliant Solution
-
-for var in (var2 for var2 in range(100)):
- ...
-
- The shape using the quotation marks (") allows the developer to insert variables that will be substituted at run time.
- But if the string does not have a variable, use quotes (') instead.
- Thus, language will not look for variables to substitute, which will reduce the consumption of CPU cycles.
-
-
Noncompliant Code Example
-
- # in variables
- firstname = "Andrea" # Noncompliant {{Avoid using quotation mark ("), prefer using simple quote (')}}
-
- # in functions
- def my_function(name, age):
- print(name + 'is' + age + ' yo.')
-
- my_function("Robert", 12) # Noncompliant {{Avoid using quotation mark ("), prefer using simple quote (')}}
-
Executing SQL queries in loop induced unnecessary calculation by the cpu, RAM usage and network transfer.
-
Noncompliant Code Example
-
- def foo():
- ...
- results = []
- for id in range(20):
- results.append(cursor.execute("SELECT name FROM users where id = ?", (id)).fetchone()) # Noncompliant {{Avoid performing SQL queries within a loop}}
- ...
-
-
Compliant Solution
-
-
- def foo():
- ...
- ids = range(20)
- results = cursor.execute("SELECT name FROM users where id IN ({0})".format(', '.join("?" * len(ids))), ids).fetchmany() # Compliant
- ...
- }
-
-