Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ensao-lint (Mohamed El kadiri) #28

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,11 @@ Implémenter les règles suivantes :
| LINT_REG_000 |BLOCKER|Les erreurs de syntaxe ne sont pas autorisées|
| LINT_REG_001 |MEDIUM |Les imports non utilisés sont à supprimer |
| LINT_REG_002 |HIGHEST|Les types java `(class, interface, annotation, enum)` commence par une majuscule, elles ne doivent pas avoir des sous-tirets `_` |
| LINT_REG_003 |HIGH|Les variables locales commencent par une minuscule |
| LINT_REG_004 |HIGH|Les attributs d'une classe commencent par une minuscule |
| LINT_REG_005 |MEDIUM|Les constantes d'une classe sont écrites en majuscule, avec des `_` comme séparateur|
| LINT_REG_006 |HIGHEST|Les expressions booléennes ne doivent avoir plus que `2` opérandes |
| LINT_REG_007 |LOW|Les éléments d'une énumeration sont en majuscule, avec des `_` comme séparateur|
| LINT_REG_008 |HIGHEST|Le corps d'une méthode ne doit pas dépasser `30` lignes|
| LINT_REG_009 |HIGH|Les instanciations anonymes sont à remplacer par des expressions `lambda`|
| LINT_REG_010 |MEDIUM|Les expressions `lambda` intuitives sont à remplacer par `method reference` |
| LINT_REG_011 |HIGHEST|Le nombre de méthodes ne doit pas dépasser `20` méthodes déclarées par classe|
| LINT_REG_012 |HIGHEST|Le nombre de paramètres d'une méthode/constructeur ne doit dépasser `2`|
| LINT_REG_013 |HIGHEST|Les attributs de classe doivent avoir une visibilité déclarée|
| LINT_REG_014 |LOW|Préférer l'utilisation d'une seule instruction de sortie `(return, throw)` dans les méthodes|
| LINT_REG_015|LOW|Ne pas catcher les exceptions sans les logger|
| LINT_REG_016|MEDIUM|Les variables non utilisées sont à supprimer|
| LINT_REG_017|MEDIUM|Les méthodes privées non utilisées sont à supprimer|
| LINT_REG_018 |LOW|les clauses `if` , `else` doivent avoir des accolades |

Si une règle est bloquante, alors remonter l'erreur est mettre fin à l'analyse du fichier en cours.
### INPUT :
Expand Down
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<maven.compiler.source>19</maven.compiler.source>
<maven.compiler.target>19</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/com/ensao/gi5/lint/constantes/Constantes.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
public class Constantes {
public static final String LINT_REG_000 = "LINT_REG_000";
public static final String LINT_REG_001 = "LINT_REG_001";
public static final String LINT_REG_002 = "LINT_REG_002";
public static final String LINT_REG_004 = "LINT_REG_004";
public static final String LINT_REG_006 = "LINT_REG_006";
public static final String LINT_REG_008 = "LINT_REG_008";
public static final String LINT_REG_011 = "LINT_REG_011";
public static final String LINT_REG_013 = "LINT_REG_013";

private Constantes() {
throw new IllegalStateException("not to be instantiated");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.ensao.gi5.lint.rules;
package com.ensao.gi5.lint.enumeration;

public enum Level {
BLOCKER,
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/ensao/gi5/lint/enumeration/RulesEnum.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.ensao.gi5.lint.enumeration;

public enum RulesEnum {
UNUSED_IMPORT_STATEMENT,
PARSE_ERROR,
CLASS_NAME,
BOOLEAN_EXPRESSION,
METHOD_LINES,
ATTRIBUTE_VISIBILITY,
ATTRIBUTE_NAME,
CLASS_METHODS
}
19 changes: 19 additions & 0 deletions src/main/java/com/ensao/gi5/lint/factory/RuleFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.ensao.gi5.lint.factory;

import com.ensao.gi5.lint.enumeration.RulesEnum;
import com.ensao.gi5.lint.rules.*;

public class RuleFactory {
public Rule getRule(RulesEnum ruleSubClass) {
return switch(ruleSubClass) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏽

case UNUSED_IMPORT_STATEMENT -> new UnusedImportsRule();
case PARSE_ERROR -> new ParseErrorRule();
case CLASS_NAME -> new TypeNameRule();
case BOOLEAN_EXPRESSION -> new BooleanExpressionRule();
case METHOD_LINES -> new MethodStatementsRule();
case ATTRIBUTE_VISIBILITY -> new AttributeVisibilityRule();
case ATTRIBUTE_NAME -> new AttributeNameRule();
case CLASS_METHODS -> new ClassMethodsRule();
};
}
}
43 changes: 43 additions & 0 deletions src/main/java/com/ensao/gi5/lint/rules/AttributeNameRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.ensao.gi5.lint.rules;

import com.ensao.gi5.lint.constantes.Constantes;
import com.ensao.gi5.lint.enumeration.Level;
import com.ensao.gi5.lint.visitor.AttributeVisitor;
import com.ensao.gi5.lint.wrapper.AttributeWrapper;
import com.ensao.gi5.lint.wrapper.CompilationUnitWrapper;

import java.util.ArrayList;
import java.util.List;

public class AttributeNameRule extends Rule {

public AttributeNameRule() {
super(Constantes.LINT_REG_004, Level.HIGH);
}
@Override
public void apply(CompilationUnitWrapper compilationUnit) {
List<AttributeWrapper> attributes = new ArrayList<>();
compilationUnit.accept(new AttributeVisitor(), attributes);
for (AttributeWrapper attribute: attributes) {
if (
Character.isUpperCase(attribute.getFieldName().charAt(0))
&& isAttributeNotConstant(attribute)
) {
buildViolationThenAddToCollection(
attribute.getLine(),
attribute + " should start with a lower case",
compilationUnit.getFileName()
);
}
}
}

public boolean isAttributeNotConstant(AttributeWrapper attribute) {
return !attribute.isStatic() && !attribute.isFinal();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it is final, it doesn't mean it is static
example

private final String foo;

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to ckeck for constants because they should start with an uppercase thats why i checked for both in this case

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see.
a constant is static && final,
the opposite is not (static && final) so the condition will be isAttributeNotConstant => not static || not final

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thanks for the clarification

}

@Override
public boolean isActive() {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.ensao.gi5.lint.rules;

import com.ensao.gi5.lint.constantes.Constantes;
import com.ensao.gi5.lint.enumeration.Level;
import com.ensao.gi5.lint.visitor.AttributeVisitor;
import com.ensao.gi5.lint.wrapper.AttributeWrapper;
import com.ensao.gi5.lint.wrapper.CompilationUnitWrapper;

import java.util.ArrayList;
import java.util.List;

public class AttributeVisibilityRule extends Rule{

public AttributeVisibilityRule() {
super(Constantes.LINT_REG_013, Level.HIGHEST);
}

@Override
public void apply(CompilationUnitWrapper compilationUnit) {
List<AttributeWrapper> attributes = new ArrayList<>();
compilationUnit.accept(new AttributeVisitor(), attributes);
for (AttributeWrapper attribute: attributes) {
if (attribute.getAccessModifier().isEmpty()) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that this is a wrapper, put this logic in wrapped method

if(attribute.hasNoAccessModifiers()) { .....

buildViolationThenAddToCollection(
attribute.getLine(),
attribute + " should have an access modifier declared",
compilationUnit.getFileName()
);
}
}
}

@Override
public boolean isActive() {
return true;
}
}
41 changes: 41 additions & 0 deletions src/main/java/com/ensao/gi5/lint/rules/BooleanExpressionRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.ensao.gi5.lint.rules;

import com.ensao.gi5.lint.constantes.Constantes;
import com.ensao.gi5.lint.enumeration.Level;
import com.ensao.gi5.lint.visitor.BooleanExpressionVisitor;
import com.ensao.gi5.lint.wrapper.BooleanExpressionWrapper;
import com.ensao.gi5.lint.wrapper.CompilationUnitWrapper;

import java.util.ArrayList;
import java.util.List;

public class BooleanExpressionRule extends Rule {

public BooleanExpressionRule() {
super(Constantes.LINT_REG_006, Level.HIGHEST);
}

@Override
public void apply(CompilationUnitWrapper compilationUnit) {
List<BooleanExpressionWrapper> booleanExpressions = new ArrayList<>();
compilationUnit.accept(new BooleanExpressionVisitor(), booleanExpressions);
for (BooleanExpressionWrapper booleanExpression: booleanExpressions) {
if (checkIfBooleanExpressionHasMoreThanTwoOperands(booleanExpression)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checkIfBooleanExpressionHasMoreThanTwoOperands ==> booleanExpressionHasMoreThanTwoOperands
in the reading it will be if boolean expression has more than two operands

buildViolationThenAddToCollection(
booleanExpression.getLine(),
"Boolean Expression " + booleanExpression + " should have 2 operands at most",
compilationUnit.getFileName()
);
}
}
}

public boolean checkIfBooleanExpressionHasMoreThanTwoOperands(BooleanExpressionWrapper booleanWrapper) {
String[] booleanOperands = booleanWrapper.getCondition().split("(&&) | (\\|\\|)");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be done by a visitor pattern

return booleanOperands.length > 2;
}
@Override
public boolean isActive() {
return true;
}
}
37 changes: 37 additions & 0 deletions src/main/java/com/ensao/gi5/lint/rules/ClassMethodsRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.ensao.gi5.lint.rules;

import com.ensao.gi5.lint.constantes.Constantes;
import com.ensao.gi5.lint.enumeration.Level;
import com.ensao.gi5.lint.visitor.TypeVisitor;
import com.ensao.gi5.lint.wrapper.CompilationUnitWrapper;
import com.ensao.gi5.lint.wrapper.TypeWrapper;

import java.util.ArrayList;
import java.util.List;

public class ClassMethodsRule extends Rule {

public ClassMethodsRule() {
super(Constantes.LINT_REG_011, Level.HIGHEST);
}

@Override
public void apply(CompilationUnitWrapper compilationUnit) {
List<TypeWrapper> typesDeclared = new ArrayList<>();
compilationUnit.accept(new TypeVisitor(), typesDeclared);
for (TypeWrapper type: typesDeclared) {
if (type.getMethodsNumber() > 20) {
buildViolationThenAddToCollection(
type.getLine(),
type + " shouldn't have more than 20 methods declared inside of it",
compilationUnit.getFileName()
);
}
}
}

@Override
public boolean isActive() {
return true;
}
}
40 changes: 40 additions & 0 deletions src/main/java/com/ensao/gi5/lint/rules/MethodStatementsRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.ensao.gi5.lint.rules;

import com.ensao.gi5.lint.constantes.Constantes;
import com.ensao.gi5.lint.enumeration.Level;
import com.ensao.gi5.lint.visitor.MethodVisitor;
import com.ensao.gi5.lint.wrapper.CompilationUnitWrapper;
import com.ensao.gi5.lint.wrapper.MethodWrapper;

import java.util.ArrayList;
import java.util.List;

public class MethodStatementsRule extends Rule {

public MethodStatementsRule() {
super(Constantes.LINT_REG_008, Level.HIGHEST);
}

@Override
public void apply(CompilationUnitWrapper compilationUnit) {
List<MethodWrapper> methods = new ArrayList<>();
compilationUnit.accept(new MethodVisitor(), methods);
for (MethodWrapper method: methods) {
if (checkIfMethodHasMoreThanThirtyLines(method)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checkIfMethodHasMoreThanThirtyLines ==> methodHasMoreThanThirtyLines

buildViolationThenAddToCollection(
method.getLine(),
method + "shouldn't contain more than 30 statements",
compilationUnit.getFileName()
);
}
}
}

public boolean checkIfMethodHasMoreThanThirtyLines(MethodWrapper methodWrapper) {
return methodWrapper.getStatements().size() > 30;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put this logic into the wrapper class

}
@Override
public boolean isActive() {
return true;
}
}
15 changes: 6 additions & 9 deletions src/main/java/com/ensao/gi5/lint/rules/ParseErrorRule.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.ensao.gi5.lint.rules;

import com.ensao.gi5.lint.constantes.Constantes;
import com.ensao.gi5.lint.rules.violations.Violation;
import com.ensao.gi5.lint.enumeration.Level;
import com.ensao.gi5.lint.wrapper.CompilationUnitWrapper;
import com.github.javaparser.JavaToken;
import com.github.javaparser.Problem;
Expand All @@ -17,20 +17,17 @@ public ParseErrorRule() {
public void apply(CompilationUnitWrapper compilationUnit) {

for (Problem problem : compilationUnit.getProblems()) {
final Violation violation = new Violation();
violation.setDescription(problem.getMessage());
violation.setFileName(compilationUnit.getFileName());

int line = problem.getLocation()
.map(TokenRange::getBegin)
.flatMap(JavaToken::getRange)
.map(range -> range.begin)
.map(position -> position.line)
.orElse(-1);


violation.setLine(line);
addViolation(violation);
buildViolationThenAddToCollection(
line,
problem.getMessage(),
compilationUnit.getFileName()
);
}
}

Expand Down
13 changes: 12 additions & 1 deletion src/main/java/com/ensao/gi5/lint/rules/Rule.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.ensao.gi5.lint.rules;

import com.ensao.gi5.lint.enumeration.Level;
import com.ensao.gi5.lint.rules.violations.Violation;
import com.ensao.gi5.lint.rules.violations.ViolationBuilder;
import com.ensao.gi5.lint.wrapper.CompilationUnitWrapper;

import java.util.Objects;
Expand All @@ -10,7 +12,7 @@
public abstract class Rule {
private final String id;
private final Level level;

protected static final ViolationBuilder violationBuilder = new ViolationBuilder();
protected final Set<Violation> violations = new TreeSet<>();

protected Rule(String id, Level level) {
Expand Down Expand Up @@ -40,6 +42,15 @@ public Level getLevel() {

public abstract boolean isActive();

public void buildViolationThenAddToCollection(int line, String description, String fileName) {
final Violation violation = violationBuilder
.withDescription(description)
.withFileName(fileName)
.withLine(line)
.build();
addViolation(violation);
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand Down
37 changes: 37 additions & 0 deletions src/main/java/com/ensao/gi5/lint/rules/TypeNameRule.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.ensao.gi5.lint.rules;

import com.ensao.gi5.lint.constantes.Constantes;
import com.ensao.gi5.lint.enumeration.Level;
import com.ensao.gi5.lint.util.Utils;
import com.ensao.gi5.lint.visitor.BooleanExpressionVisitor;
import com.ensao.gi5.lint.visitor.TypeVisitor;
import com.ensao.gi5.lint.wrapper.BooleanExpressionWrapper;
import com.ensao.gi5.lint.wrapper.CompilationUnitWrapper;
import com.ensao.gi5.lint.wrapper.TypeWrapper;

import java.util.ArrayList;
import java.util.List;

public class TypeNameRule extends Rule {
public TypeNameRule() {
super(Constantes.LINT_REG_002, Level.HIGHEST);
}
@Override
public void apply(CompilationUnitWrapper compilationUnit) {
List<TypeWrapper> typeNames = new ArrayList<>();
compilationUnit.accept(new TypeVisitor(), typeNames);
typeNames = Utils.checkIfNamesDontFollowsRule(typeNames);
for (TypeWrapper typeName: typeNames) {
buildViolationThenAddToCollection(
typeName.getLine(),
typeName + " should start with uppercase and shouldn't contain underscores",
compilationUnit.getFileName()
);
}
}

@Override
public boolean isActive() {
return true;
}
}
Loading