diff --git a/README.MD b/README.MD index 3b32ebe..4182373 100644 --- a/README.MD +++ b/README.MD @@ -14,19 +14,19 @@ Implémenter les règles suivantes : | 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_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_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 | +~~| 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 : diff --git a/src/main/java/com/ensao/gi5/lint/constantes/Constantes.java b/src/main/java/com/ensao/gi5/lint/constantes/Constantes.java index 32a57fb..a1e568b 100644 --- a/src/main/java/com/ensao/gi5/lint/constantes/Constantes.java +++ b/src/main/java/com/ensao/gi5/lint/constantes/Constantes.java @@ -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_003 = "LINT_REG_003"; + public static final String LINT_REG_004 = "LINT_REG_004"; + public static final String LINT_REG_005 ="LINT_REG_005" ; + public static final String LINT_REG_011 = "LINT_REG_011"; + public static final String LINT_REG_008 = "LINT_REG_008"; private Constantes() { throw new IllegalStateException("not to be instantiated"); diff --git a/src/main/java/com/ensao/gi5/lint/rules/AttributesNamingRule.java b/src/main/java/com/ensao/gi5/lint/rules/AttributesNamingRule.java new file mode 100644 index 0000000..8f3e836 --- /dev/null +++ b/src/main/java/com/ensao/gi5/lint/rules/AttributesNamingRule.java @@ -0,0 +1,47 @@ +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.wrapper.CompilationUnitWrapper; +import com.github.javaparser.ast.body.FieldDeclaration; +import com.github.javaparser.ast.body.TypeDeclaration; + +import java.util.List; + +public class AttributesNamingRule extends Rule{ + + protected AttributesNamingRule(String id, Level level) { + super(Constantes.LINT_REG_004, Level.HIGH); + } + + @Override + public void apply(CompilationUnitWrapper compilationUnit) { + final List> types = compilationUnit.getTypes(); + types.stream() + .forEach(type -> { + type.getMembers().stream() + .filter(member -> member instanceof FieldDeclaration && !((FieldDeclaration) member).isFinal()) + .map(member -> (FieldDeclaration) member) + .forEach(field -> { + field.getVariables().stream() + .filter(variable -> !Character.isLowerCase(variable.getNameAsString().charAt(0))) + .forEach(variable -> { + String message = "attribute " + variable.getNameAsString() + " must start with lowercase letter."; + final Violation violation = new Violation(); + violation.setDescription(message); + violation.setFileName(compilationUnit.getFileName()); + violation.setLine(field.getBegin().get().line); + addViolation(violation); + + }); + }); + }); + } + + + + @Override + public boolean isActive() { + return true; + } +} diff --git a/src/main/java/com/ensao/gi5/lint/rules/ConstantsNamingRule.java b/src/main/java/com/ensao/gi5/lint/rules/ConstantsNamingRule.java new file mode 100644 index 0000000..e88520c --- /dev/null +++ b/src/main/java/com/ensao/gi5/lint/rules/ConstantsNamingRule.java @@ -0,0 +1,39 @@ +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.wrapper.CompilationUnitWrapper; +import com.github.javaparser.ast.body.TypeDeclaration; + +import java.util.List; + +public class ConstantsNamingRule extends Rule{ + protected ConstantsNamingRule() { + super(Constantes.LINT_REG_005, Level.MEDIUM); + } + + @Override + public void apply(CompilationUnitWrapper compilationUnit) { + final List> types = compilationUnit.getTypes(); + + types.stream() + .forEach(type -> { + type.getFields().stream() + .filter(field -> field.isStatic() && field.isFinal() && !field.getVariables().get(0).getNameAsString().matches("^[A-Z_]+$")) + .forEach(field -> { + String message = "The constant " + field.getVariables().get(0).getNameAsString() + " must be in uppercase and separated with _ ."; + final Violation violation = new Violation(); + violation.setDescription(message); + violation.setFileName(compilationUnit.getFileName()); + violation.setLine(type.getName().getBegin().get().line); + addViolation(violation); + }); + }); + + } + + @Override + public boolean isActive() { + return true; + } +} diff --git a/src/main/java/com/ensao/gi5/lint/rules/LocalVariablesNamingRule.java b/src/main/java/com/ensao/gi5/lint/rules/LocalVariablesNamingRule.java new file mode 100644 index 0000000..e2bb681 --- /dev/null +++ b/src/main/java/com/ensao/gi5/lint/rules/LocalVariablesNamingRule.java @@ -0,0 +1,45 @@ +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.wrapper.CompilationUnitWrapper; +import com.github.javaparser.ast.body.MethodDeclaration; +import com.github.javaparser.ast.body.TypeDeclaration; +import com.github.javaparser.ast.body.VariableDeclarator; + +import java.util.List; + +public class LocalVariablesNamingRule extends Rule { + protected LocalVariablesNamingRule() { + super(Constantes.LINT_REG_003, Level.HIGH); + } + + @Override + public void apply(CompilationUnitWrapper compilationUnit) { + final List> types = compilationUnit.getTypes(); + types.stream() + .forEach(type -> { + type.findAll(MethodDeclaration.class) + .stream() + .forEach(method -> { + method.findAll(VariableDeclarator.class) + .stream() + .filter(var -> !Character.isLowerCase(var.getNameAsString().charAt(0))) + .forEach(var -> { + String message = "The local variable " + var.getNameAsString() + " must start with lowercase letter."; + final Violation violation = new Violation(); + violation.setDescription(message); + violation.setFileName(compilationUnit.getFileName()); + violation.setLine(var.getName().getBegin().get().line); + addViolation(violation); + }); + }); + }); + } + + + @Override + public boolean isActive() { + return true; + } +} diff --git a/src/main/java/com/ensao/gi5/lint/rules/MethodLinesRule.java b/src/main/java/com/ensao/gi5/lint/rules/MethodLinesRule.java new file mode 100644 index 0000000..2ecb4a4 --- /dev/null +++ b/src/main/java/com/ensao/gi5/lint/rules/MethodLinesRule.java @@ -0,0 +1,40 @@ +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.wrapper.CompilationUnitWrapper; +import com.github.javaparser.ast.body.MethodDeclaration; +import com.github.javaparser.ast.body.TypeDeclaration; + +import java.util.List; + +public class MethodLinesRule extends Rule{ + protected MethodLinesRule(String id, Level level) { + super(Constantes.LINT_REG_008, Level.HIGHEST); + } + + @Override + public void apply(CompilationUnitWrapper compilationUnitWrapper) { + List> types = compilationUnitWrapper.getTypes(); + for (TypeDeclaration type : types) { + List methods = type.getMethods(); + for (MethodDeclaration method : methods) { + int lineCount = method.getEnd().get().line - method.getBegin().get().line; + if (lineCount > 30) { + String message = "The method " + method.getNameAsString() + " has a body that exceeds 30 lines."; + final Violation violation = new Violation(); + violation.setDescription(message); + violation.setFileName(compilationUnitWrapper.getFileName()); + violation.setLine(method.getBegin().get().line); + addViolation(violation); + } + } + } + } + + + @Override + public boolean isActive() { + return true; + } +} diff --git a/src/main/java/com/ensao/gi5/lint/rules/MethodsNumberRule.java b/src/main/java/com/ensao/gi5/lint/rules/MethodsNumberRule.java new file mode 100644 index 0000000..410932f --- /dev/null +++ b/src/main/java/com/ensao/gi5/lint/rules/MethodsNumberRule.java @@ -0,0 +1,38 @@ +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.wrapper.CompilationUnitWrapper; +import com.github.javaparser.ast.body.TypeDeclaration; + +import java.util.List; + +public class MethodsNumberRule extends Rule{ + protected MethodsNumberRule(String id, Level level) { + super(Constantes.LINT_REG_011, Level.HIGHEST); + } + + @Override + public void apply(CompilationUnitWrapper compilationUnitWrapper) { + List> types = compilationUnitWrapper.getTypes(); + for (TypeDeclaration type : types) { + int methodCount = (int) type.getMethods().stream() + .filter(bodyDeclaration -> bodyDeclaration.isMethodDeclaration()) + .count(); + if (methodCount > 20) { + String message = "The class " + type.getNameAsString() + " has more than 20 methods declared."; + final Violation violation = new Violation(); + violation.setDescription(message); + violation.setFileName(compilationUnitWrapper.getFileName()); + violation.setLine(type.getName().getBegin().get().line); + addViolation(violation); + } + } + } + + + @Override + public boolean isActive() { + return true; + } +} diff --git a/src/main/java/com/ensao/gi5/lint/rules/TypesNamingRule.java b/src/main/java/com/ensao/gi5/lint/rules/TypesNamingRule.java new file mode 100644 index 0000000..722e7b2 --- /dev/null +++ b/src/main/java/com/ensao/gi5/lint/rules/TypesNamingRule.java @@ -0,0 +1,46 @@ +package com.ensao.gi5.lint.rules; + +import com.ensao.gi5.lint.rules.violations.Violation; +import com.ensao.gi5.lint.constantes.Constantes; +import com.ensao.gi5.lint.wrapper.CompilationUnitWrapper; +import com.github.javaparser.ast.body.TypeDeclaration; +import java.util.List; + +public class TypesNamingRule extends Rule{ + + protected TypesNamingRule() { + super(Constantes.LINT_REG_002, Level.HIGHEST); + } + + @Override + public void apply(CompilationUnitWrapper compilationUnit) { + // Obtenir tous les types déclarés dans le fichier + final List> types = compilationUnit.getTypes(); + + types.stream() + .filter(type -> !Character.isUpperCase(type.getNameAsString().charAt(0)) || type.getNameAsString().contains("_")) + .forEach(type -> { + String message = ""; + if (!Character.isUpperCase(type.getNameAsString().charAt(0))) { + message += "NAme of Type " + type.getNameAsString() + " must start with uppercase letter."; + } + if (type.getNameAsString().contains("_")) { + message += " Le nom du type " + type.getNameAsString() + " ne doit pas contenir de tirets bas."; + } + final Violation violation = new Violation(); + violation.setDescription(message); + violation.setFileName(compilationUnit.getFileName()); + violation.setLine(type.getName().getBegin().get().line); + addViolation(violation); + }); + + + + } + + @Override + public boolean isActive() { + return true; + } +} + diff --git a/src/main/java/com/ensao/gi5/lint/wrapper/CompilationUnitWrapper.java b/src/main/java/com/ensao/gi5/lint/wrapper/CompilationUnitWrapper.java index 0768852..0c7ba69 100644 --- a/src/main/java/com/ensao/gi5/lint/wrapper/CompilationUnitWrapper.java +++ b/src/main/java/com/ensao/gi5/lint/wrapper/CompilationUnitWrapper.java @@ -4,6 +4,7 @@ import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.ImportDeclaration; import com.github.javaparser.ast.NodeList; +import com.github.javaparser.ast.body.TypeDeclaration; import com.github.javaparser.ast.visitor.VoidVisitor; import java.util.ArrayList; @@ -21,6 +22,9 @@ public CompilationUnitWrapper(CompilationUnit compilationUnit, String fileName) } public NodeList getImports() {return compilationUnit.getImports();} + public List> getTypes() { + return compilationUnit.getTypes(); + } public void accept(VoidVisitor v, A arg) { compilationUnit.accept(v, arg);} diff --git a/src/main/java/com/ensao/gi5/lint/wrapper/TypeDeclarationWrapper.java b/src/main/java/com/ensao/gi5/lint/wrapper/TypeDeclarationWrapper.java new file mode 100644 index 0000000..f40aaa9 --- /dev/null +++ b/src/main/java/com/ensao/gi5/lint/wrapper/TypeDeclarationWrapper.java @@ -0,0 +1,36 @@ +package com.ensao.gi5.lint.wrapper; + +import java.lang.reflect.Modifier; +import com.github.javaparser.ast.body.TypeDeclaration; + +public class TypeDeclarationWrapper { + private TypeDeclaration typeDeclaration; + private String fileName; + + public TypeDeclarationWrapper(TypeDeclaration typeDeclaration, String fileName) { + this.typeDeclaration = typeDeclaration; + this.fileName = fileName; + } + + public String getName() { + return typeDeclaration.getName().asString(); + } + + public String getFileName() { + return fileName; + } + + + + public boolean isPrivate() { + return typeDeclaration.getModifiers().contains(Modifier.PRIVATE); + } + + public boolean isProtected() { + return typeDeclaration.getModifiers().contains(Modifier.PROTECTED); + } + + public boolean isPublic() { + return typeDeclaration.getModifiers().contains(Modifier.PUBLIC); + } +}