diff --git a/input/no-package-declaration.xmi b/input/no-package-declaration.xmi new file mode 100644 index 0000000000000000000000000000000000000000..831730feaf12fc47932105397e98c3b96dd00870 --- /dev/null +++ b/input/no-package-declaration.xmi @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/input/un-conditional-If-statement.xmi b/input/un-conditional-If-statement.xmi new file mode 100644 index 0000000000000000000000000000000000000000..6c755011fdaf1620116bdbb9541b0278ab42a86d --- /dev/null +++ b/input/un-conditional-If-statement.xmi @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/atl/analysis.atl b/src/main/atl/analysis.atl index 7821a1b28df6fb99c8b969e115224d7933879128..09118fa2df763df7a3f7011246d952d2c723a870 100644 --- a/src/main/atl/analysis.atl +++ b/src/main/atl/analysis.atl @@ -28,81 +28,73 @@ rule Java2SMM { ) } -helper def: allMeasures(project : java!Model): Set(smm!Measure) = - - Set{ - -- Example rule +helper def: allMeasures(project: java!Model): Set(smm!Measure) = + Set{-- Example rule -- thisModule.numberOfClasses(), - - -- Multithreading rules + -- Multithreading rules -- thisModule.dontCallThreadRun(), - thisModule.avoidThreadGroup(), - thisModule.useNotifyAllInsteadOfNotify(), - - -- Code Style rules + thisModule.avoidThreadGroup(), + thisModule.useNotifyAllInsteadOfNotify(), + -- Code Style rules -- thisModule.shortMethodName(), - thisModule.tooManyStaticImports(), - thisModule.avoidDollarSigns(), - thisModule.shortClassName(), - thisModule.extendsObject(), - thisModule.unnecessaryReturn(), - thisModule.longVariable(), - - -- Design rules + thisModule.tooManyStaticImports(), + thisModule.avoidDollarSigns(), + thisModule.shortClassName(), + thisModule.extendsObject(), + thisModule.unnecessaryReturn(), + thisModule.longVariable(), + + thisModule.noPackageDeclaration(), + thisModule.UnconditionalIfStatement(), + -- Design rules -- thisModule.tooManyFields(), - thisModule.tooManyMethods(), - thisModule.returnFromFinallyBlock(), - thisModule.longInstantiation(), - thisModule.shortInstantiation(), - thisModule.returnEmptyArrayRatherThanNull(), + thisModule.tooManyMethods(), + thisModule.returnFromFinallyBlock(), + thisModule.longInstantiation(), + thisModule.shortInstantiation(), + --thisModule.returnEmptyArrayRatherThanNull(), thisModule.excessiveParameterList(), - thisModule.finalFieldCouldBeStatic(), - thisModule.signatureDeclareThrowsException(), - thisModule.avoidThrowingNullPointerException(), - - -- Performance rules + thisModule.finalFieldCouldBeStatic(), + thisModule.signatureDeclareThrowsException(), + thisModule.avoidThrowingNullPointerException(), + -- Performance rules -- thisModule.uselessStringValueOf(), - thisModule.tooFewBranchesForASwitchStatement(), - thisModule.useIndexOfChar(), - thisModule.avoidPrintStackTrace(), - thisModule.avoidUsingShortType(), - thisModule.emptyStatementBlock(), - thisModule.avoidRethrowingException(), - thisModule.integerInstantiation(), - - -- Documentation rules + thisModule.tooFewBranchesForASwitchStatement(), + thisModule.useIndexOfChar(), + thisModule.avoidPrintStackTrace(), + thisModule.avoidUsingShortType(), + thisModule.emptyStatementBlock(), + thisModule.avoidRethrowingException(), + thisModule.integerInstantiation(), + -- Documentation rules -- thisModule.commentContent(), - thisModule.commentRequired(), - - - -- Error prone rules + thisModule.commentRequired(), + -- Error prone rules -- thisModule.missingBreakInSwitch(), - thisModule.suspiciousEqualsMethodName(), - thisModule.doNotExtendJavaLangThrowable(), - thisModule.doNotExtendJavaLangError(), - thisModule.compareObjectsWithEquals(), - thisModule.avoidCallingFinalize(), - thisModule.emptyTryBlock(), - thisModule.emptyWhileStmt(), - thisModule.dontImportSun(), - thisModule.finalizeShouldBeProtected(), + thisModule.suspiciousEqualsMethodName(), + thisModule.doNotExtendJavaLangThrowable(), + thisModule.doNotExtendJavaLangError(), + thisModule.compareObjectsWithEquals(), + thisModule.avoidCallingFinalize(), + thisModule.emptyTryBlock(), + thisModule.emptyWhileStmt(), + thisModule.dontImportSun(), + --thisModule.finalizeShouldBeProtected(), -- Best practices rules thisModule.avoidThrowingNewInstanceOfSameException(), - thisModule.switchDensity(), - thisModule.avoidStringBufferField() -}; - + thisModule.switchDensity() --thisModule.avoidStringBufferField() + }; -- creates a new Measure when String.valueOf is called to append its argument to a string -rule MeasureUselessStringValueOf(method : java!MethodInvocation) { +rule MeasureUselessStringValueOf(method: java!MethodInvocation) { to om: smm!ObservedMeasure ( measure <- noc, @@ -110,20 +102,21 @@ rule MeasureUselessStringValueOf(method : java!MethodInvocation) { ), noc: smm!DimensionalMeasure ( name <- 'Useless string value of', - shortDescription <- 'No need to call String.valueOf to append to a string; just use the valueOf() argument directly.' + shortDescription <- 'No need to call String.valueOf to append to a string;' + + ' just use the valueOf() argument directly.' ), - measurement: smm!DirectMeasurement ( - error<- 'The class '+ method.originalCompilationUnit.name + ' violates the rule useless string value of.' - ) + measurement: smm!DirectMeasurement ( + error <- 'The class ' + method.originalCompilationUnit.name + ' violates the' + + ' rule useless string value of.' + ) do { noc; } } ------------------------------------------------------------------------------------------ - -- A Measure instance if the class violates the rule 'AvoidDollarSigns'. -rule MesureAvoidDollarSigns(node : java!ASTNode) { +rule MesureAvoidDollarSigns(node: java!ASTNode) { to om: smm!ObservedMeasure ( measure <- noc, @@ -131,7 +124,8 @@ rule MesureAvoidDollarSigns(node : java!ASTNode) { ), noc: smm!DimensionalMeasure ( name <- 'AvoidDollarSigns', - shortDescription <- 'Avoid using dollar signs in variable/method/class/interface names.' + shortDescription <- 'Avoid using dollar signs in' + + ' variable/method/class/interface names.' ), measurement: smm!DirectMeasurement ( error <- node.name + ' has dollar in ' + node.originalCompilationUnit.name @@ -141,10 +135,8 @@ rule MesureAvoidDollarSigns(node : java!ASTNode) { } } - - -- A Measure instance if the class violates the rule 'ShortMethodName'. -rule MesureShortMethodName(method : java!MethodDeclaration) { +rule MesureShortMethodName(method: java!MethodDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, @@ -152,19 +144,20 @@ rule MesureShortMethodName(method : java!MethodDeclaration) { ), noc: smm!DimensionalMeasure ( name <- 'ShortMethodName', - shortDescription <- 'Method names names that are very short are not helpful to the reader.' + shortDescription <- 'Method names names that are very short are not helpful' + + ' to the reader.' ), measurement: smm!DirectMeasurement ( - error <- method.name + ' is too short in ' + method.originalCompilationUnit.name + error <- method.name + ' is too short in ' + method.originalCompilationUnit. + name ) do { noc; } } - -- A Measure instance if the class violates the rule 'ShortClassName'. -rule MesureShortClassName(class : java!ClassDeclaration) { +rule MesureShortClassName(class: java!ClassDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, @@ -172,7 +165,8 @@ rule MesureShortClassName(class : java!ClassDeclaration) { ), noc: smm!DimensionalMeasure ( name <- 'ShortClassName', - shortDescription <- 'Short Classnames with fewer than e.g. five characters are not recommended.' + shortDescription <- 'Short Classnames with fewer than e.g. five characters' + + ' are not recommended.' ), measurement: smm!DirectMeasurement ( error <- 'The Class ' + class.name + ' is too short.' @@ -182,9 +176,8 @@ rule MesureShortClassName(class : java!ClassDeclaration) { } } - -- creates a new Measure when Thread.run() is used instead of Thread.start() -rule MeasureDontCallThreadRun(method : java!MethodInvocation) { +rule MeasureDontCallThreadRun(method: java!MethodInvocation) { to om: smm!ObservedMeasure ( measure <- noc, @@ -192,19 +185,21 @@ rule MeasureDontCallThreadRun(method : java!MethodInvocation) { ), noc: smm!DimensionalMeasure ( name <- 'Don t call Thread.run()', - shortDescription <- 'Explicitly calling Thread.run() method will execute in the caller s thread of control. Instead, call Thread.start() for the intended behavior.' + shortDescription <- 'Explicitly calling Thread.run() method will execute in' + + ' the caller s thread of control. Instead, call Thread.start() for' + + ' the intended behavior.' ), - measurement: smm!DirectMeasurement ( - error<-'The class '+ method.originalCompilationUnit.name + ' violates the rule don t call Thread.run().' + measurement: smm!DirectMeasurement ( + error <- 'The class ' + method.originalCompilationUnit.name + ' violates the' + + ' rule don t call Thread.run().' ) do { noc; } } - -- A Measure instance if the class violates the rule 'TooManyFields'. -rule MesureTooManyFields(class : java!ClassDeclaration) { +rule MesureTooManyFields(class: java!ClassDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, @@ -212,7 +207,8 @@ rule MesureTooManyFields(class : java!ClassDeclaration) { ), noc: smm!DimensionalMeasure ( name <- 'TooManyFields', - shortDescription <- 'Classes that have too many fields can become unwieldy and could be redesigned to have fewer field.' + shortDescription <- 'Classes that have too many fields can become unwieldy' + + ' and could be redesigned to have fewer field.' ), measurement: smm!DirectMeasurement ( error <- class.originalCompilationUnit.name + ' have too many fields' @@ -222,9 +218,9 @@ rule MesureTooManyFields(class : java!ClassDeclaration) { } } - --- creates a new Measure when the parameter of String.indexOf(char) is not of type char when checking for the index of a single character -rule MeasureUseIndexOfChar(method : java!MethodInvocation) { +-- creates a new Measure when the parameter of String.indexOf(char) is not of type char + -- when checking for the index of a single character +rule MeasureUseIndexOfChar(method: java!MethodInvocation) { to om: smm!ObservedMeasure ( measure <- noc, @@ -232,10 +228,12 @@ rule MeasureUseIndexOfChar(method : java!MethodInvocation) { ), noc: smm!DimensionalMeasure ( name <- 'Use index of char', - shortDescription <- 'Use String.indexOf(char) when checking for the index of a single character; it executes faster.' + shortDescription <- 'Use String.indexOf(char) when checking for the index of' + + ' a single character; it executes faster.' ), - measurement: smm!DirectMeasurement ( - error<- 'The class '+ method.originalCompilationUnit.name + ' violates the rule index of char.' + measurement: smm!DirectMeasurement ( + error <- 'The class ' + method.originalCompilationUnit.name + ' violates the' + + ' rule index of char.' ) do { noc; @@ -243,7 +241,6 @@ rule MeasureUseIndexOfChar(method : java!MethodInvocation) { } ------------------------------------------------------------------------------------------ - rule numberOfClasses() { to om: smm!ObservedMeasure ( @@ -254,7 +251,8 @@ rule numberOfClasses() { name <- 'Number of Classes' ), measurement: smm!DirectMeasurement ( - value <- java!ClassDeclaration.allInstances() -> reject(each | each.isProxy()) -> size() + value <- java!ClassDeclaration.allInstances() -> reject(each | each. + isProxy()) -> size() ) do { @@ -262,8 +260,8 @@ rule numberOfClasses() { } } - --- Rule that creates an instance of Measure for the switch statement with too few branches passed in parameter +-- Rule that creates an instance of Measure for the switch statement with too few + -- branches passed in parameter rule MeasureTooFewBranchesForASwitchStatement(switchStatement: java!SwitchStatement) { to om: smm!ObservedMeasure ( @@ -272,10 +270,15 @@ rule MeasureTooFewBranchesForASwitchStatement(switchStatement: java!SwitchStatem ), tooFewBranchesForASwitchStatement: smm!DimensionalMeasure ( name <- 'TooFewBranchesForASwitchStatement', - shortDescription <- 'Switch statements are intended to be used to support complex branching behaviour. Using a switch for only a few cases is ill-advised, since switches are not as easy to understand as if-then statements. In these cases use the if-then statement to increase code readability.' + shortDescription <- 'Switch statements are intended to be used to support' + + ' complex branching behaviour. Using a switch for only a few cases' + + ' is ill-advised, since switches are not as easy to understand as' + + ' if-then statements. In these cases use the if-then statement to' + + ' increase code readability.' ), measurement: smm!DirectMeasurement ( - error <- 'Too few branches for SwitchStatement in Class : ' + switchStatement.originalCompilationUnit.name, + error <- 'Too few branches for SwitchStatement in Class : ' + switchStatement. + originalCompilationUnit.name, value <- thisModule.nbBranchesOfASwitchStatement(switchStatement) ) do { @@ -283,9 +286,10 @@ rule MeasureTooFewBranchesForASwitchStatement(switchStatement: java!SwitchStatem } } ---------------------------------------------- ShortInstantiation --------------------------------------------- +--------------------------------------------- ShortInstantiation +--- --------------------------------------------- -- A Measure instance if the class violates the rule 'ShortInstantiation'. -rule MeasureShortInstantiation(variable : java!CompilationUnit) { +rule MeasureShortInstantiation(variable: java!CompilationUnit) { to om: smm!ObservedMeasure ( measure <- noc, @@ -293,10 +297,15 @@ rule MeasureShortInstantiation(variable : java!CompilationUnit) { ), noc: smm!DimensionalMeasure ( name <- 'ShortInstantiation', - shortDescription <- 'Calling new Short() causes memory allocation that can be avoided by the static Short.valueOf(). It makes use of an internal cache that recycles earlier instances making it more memory efficient. Note that new Short() is deprecated since JDK 9 for that reason.' + shortDescription <- 'Calling new Short() causes memory allocation that can be' + + ' avoided by the static Short.valueOf(). It makes use of an' + + ' internal cache that recycles earlier instances making it more' + + ' memory efficient. Note that new Short() is deprecated since JDK 9' + + ' for that reason.' ), - measurement: smm!DirectMeasurement ( - error<-'In the Class '+ variable.name + ' an instantiation of Short must be Short.ValueOf().' + measurement: smm!DirectMeasurement ( + error <- 'In the Class ' + variable.name + ' an instantiation of Short must' + + ' be Short.ValueOf().' ) do { @@ -304,10 +313,10 @@ rule MeasureShortInstantiation(variable : java!CompilationUnit) { } } - ---------------------------------------------- LongInstantiation --------------------------------------------- +--------------------------------------------- LongInstantiation +--- --------------------------------------------- -- A Measure instance if the class violates the rule 'LongInstantiation'. -rule MeasureLongInstantiation(variable : java!CompilationUnit) { +rule MeasureLongInstantiation(variable: java!CompilationUnit) { to om: smm!ObservedMeasure ( measure <- noc, @@ -315,10 +324,15 @@ rule MeasureLongInstantiation(variable : java!CompilationUnit) { ), noc: smm!DimensionalMeasure ( name <- 'LongInstantiation', - shortDescription <- 'Calling new Long() causes memory allocation that can be avoided by the static Long.valueOf(). It makes use of an internal cache that recycles earlier instances making it more memory efficient. Note that new Long() is deprecated since JDK 9 for that reason.' + shortDescription <- 'Calling new Long() causes memory allocation that can be' + + ' avoided by the static Long.valueOf(). It makes use of an internal' + + ' cache that recycles earlier instances making it more memory' + + ' efficient. Note that new Long() is deprecated since JDK 9 for' + + ' that reason.' ), - measurement: smm!DirectMeasurement ( - error<-'In the Class '+ variable.name + ' an instantiation of Long must be Long.ValueOf().' + measurement: smm!DirectMeasurement ( + error <- 'In the Class ' + variable.name + ' an instantiation of Long must be' + + ' Long.ValueOf().' ) do { @@ -326,9 +340,10 @@ rule MeasureLongInstantiation(variable : java!CompilationUnit) { } } ---------------------------------------------- DoNotExtendJavaLangThrowable --------------------------------------------- +--------------------------------------------- DoNotExtendJavaLangThrowable +--- --------------------------------------------- -- A Measure instance if the class violates the rule DoNotExtendJavaLangThrowable. -rule MeasureDoNotExtendJavaLangThrowable(variable : java!ClassDeclaration) { +rule MeasureDoNotExtendJavaLangThrowable(variable: java!ClassDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, @@ -336,44 +351,45 @@ rule MeasureDoNotExtendJavaLangThrowable(variable : java!ClassDeclaration) { ), noc: smm!DimensionalMeasure ( name <- 'DoNotExtendJavaLangThrowable ', - shortDescription <- 'Extend Exception or RuntimeException instead of Throwable.' - + shortDescription <- 'Extend Exception or RuntimeException instead of' + + ' Throwable.' ), - measurement: smm!DirectMeasurement ( - error<-'In the Class '+ variable.name + ' should not extend Throwable but RuntimeException or Exception .' + measurement: smm!DirectMeasurement ( + error <- 'In the Class ' + variable.name + ' should not extend Throwable but' + + ' RuntimeException or Exception .' ) do { noc; } } - + -- Returns the number of branches in the switch statement passed in parameter -helper def: nbBranchesOfASwitchStatement(switchStatement:java!SwitchStatement) : Integer = - switchStatement.statements->select(each | each.oclIsTypeOf(java!SwitchCase)).size() -; +helper def: nbBranchesOfASwitchStatement(switchStatement: java!SwitchStatement): Integer = + switchStatement.statements -> select(each | each.oclIsTypeOf(java!SwitchCase)).size(); -- Returns the number of Fields in Class -helper def: numberFieldsInClasse(s:java!ClassDeclaration) : Integer = +helper def: numberFieldsInClasse(s: java!ClassDeclaration): Integer = -- Return the number of FieldDeclaration in a class. - s.bodyDeclarations-> select(r | r.oclIsTypeOf(java!FieldDeclaration))->size(); + s.bodyDeclarations -> select(r | r.oclIsTypeOf(java!FieldDeclaration)) -> size(); -- Returns the number of breaks of the switch statement passed in parameter -helper def: nbBreakStatementOfASwitchStatement(ss:java!SwitchStatement) : Integer = - ss.statements->select(each | each.oclIsTypeOf(java!BreakStatement)).size() -; +helper def: nbBreakStatementOfASwitchStatement(ss: java!SwitchStatement): Integer = + ss.statements -> select(each | each.oclIsTypeOf(java!BreakStatement)).size(); -- Returns the number of expressions of the switch statement passed in parameter -helper def: nbExpressionsStatementOfASwitchStatement(ss:java!SwitchStatement) : Integer = - ss.statements->select(each | each.oclIsTypeOf(java!ExpressionStatement)).size() -; - --- Returns the number of intentional fall-through (empty switch cases) of a switchStatement -helper def: nbIntentionalFallThroughOfASwitchStatement(ss:java!SwitchStatement) : Integer = - thisModule.nbBranchesOfASwitchStatement(ss) - thisModule.nbExpressionsStatementOfASwitchStatement(ss) -; - --- Creates an instance of Measure for the switch statement missing one or more break statements +helper def: nbExpressionsStatementOfASwitchStatement(ss: java!SwitchStatement): Integer = + ss.statements -> select(each | each.oclIsTypeOf(java!ExpressionStatement)).size(); + +-- Returns the number of intentional fall-through (empty switch cases) of a + -- switchStatement +helper def: nbIntentionalFallThroughOfASwitchStatement(ss: java!SwitchStatement): Integer + = + thisModule.nbBranchesOfASwitchStatement(ss) - thisModule. + nbExpressionsStatementOfASwitchStatement(ss); + +-- Creates an instance of Measure for the switch statement missing one or more break + -- statements -- To test, use input model : missing-break-in-switch.xmi rule createMeasureForMissingBreakInSwitch(ss: java!SwitchStatement) { to @@ -383,12 +399,17 @@ rule createMeasureForMissingBreakInSwitch(ss: java!SwitchStatement) { ), missingBreakInSwitch: smm!DimensionalMeasure ( name <- 'Missing break in Switch', - shortDescription <- 'Switch statements without break or return statements for each case option may indicate problematic behaviour. Empty cases are ignored as these indicate an intentional fall-through.' + shortDescription <- 'Switch statements without break or return statements for' + + ' each case option may indicate problematic behaviour. Empty cases' + + ' are ignored as these indicate an intentional fall-through.' ), measurement: smm!DirectMeasurement ( - error <- 'Missing breaks in Switch in Class : ' + ss.originalCompilationUnit.name + '', + error <- 'Missing breaks in Switch in Class : ' + ss.originalCompilationUnit. + name + '', -- Indicates the number of breaks missing in the switch statement - value <- (thisModule.nbBranchesOfASwitchStatement(ss) - thisModule.nbIntentionalFallThroughOfASwitchStatement(ss)) - thisModule.nbBreakStatementOfASwitchStatement(ss) + value <- (thisModule.nbBranchesOfASwitchStatement(ss) - thisModule. + nbIntentionalFallThroughOfASwitchStatement(ss)) - thisModule. + nbBreakStatementOfASwitchStatement(ss) ) do { missingBreakInSwitch; @@ -396,7 +417,7 @@ rule createMeasureForMissingBreakInSwitch(ss: java!SwitchStatement) { } -- A Measure instance if the class violates the rule 'TooManyMethods'. -rule MesureTooManyMethods(class : java!ClassDeclaration) { +rule MesureTooManyMethods(class: java!ClassDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, @@ -404,7 +425,9 @@ rule MesureTooManyMethods(class : java!ClassDeclaration) { ), noc: smm!DimensionalMeasure ( name <- 'TooManyMethods', - shortDescription <- 'A class with too many methods is probably a good suspect for refactoring, in order to reduce its complexity and find a way to have more fine grained objects.' + shortDescription <- 'A class with too many methods is probably a good suspect' + + ' for refactoring, in order to reduce its complexity and find a way' + + ' to have more fine grained objects.' ), measurement: smm!DirectMeasurement ( error <- class.originalCompilationUnit.name + ' has too many methods' @@ -416,7 +439,7 @@ rule MesureTooManyMethods(class : java!ClassDeclaration) { } -- A Measure instance if the class violates the rule ReturnFromFinallyBlock. -rule MesureReturnFromFinallyBlock(method : java!MethodDeclaration) { +rule MesureReturnFromFinallyBlock(method: java!MethodDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, @@ -424,10 +447,13 @@ rule MesureReturnFromFinallyBlock(method : java!MethodDeclaration) { ), noc: smm!DimensionalMeasure ( name <- 'returnFromFinallyBlock', - shortDescription <- 'Avoid returning from a finally block, this can discard exceptions.' + shortDescription <- 'Avoid returning from a finally block, this can discard' + + ' exceptions.' ), measurement: smm!DirectMeasurement ( - error <- 'The method ' + method.name + ' in the class ' + method.originalCompilationUnit.name + ' has a return statement in a finally block.' + error <- 'The method ' + method.name + ' in the class ' + method. + originalCompilationUnit.name + ' has a return statement in a finally' + + ' block.' ) do { noc; @@ -435,7 +461,7 @@ rule MesureReturnFromFinallyBlock(method : java!MethodDeclaration) { } -- A Measure instance if the class violates the rule 'TooManyStaticImports'. -rule MesureTooManyStaticImports(class : java!CompilationUnit) { +rule MesureTooManyStaticImports(class: java!CompilationUnit) { to om: smm!ObservedMeasure ( measure <- noc, @@ -443,7 +469,12 @@ rule MesureTooManyStaticImports(class : java!CompilationUnit) { ), noc: smm!DimensionalMeasure ( name <- 'TooManyStaticImports', - shortDescription <- 'If you overuse the static import feature, it can make your program unreadable and unmaintainable, polluting its namespace with all the static members you import. Readers of your code (including you, a few months after you wrote it) will not know which class a static member comes from (Sun 1.5 Language Guide).' + shortDescription <- 'If you overuse the static import feature, it can make' + + ' your program unreadable and unmaintainable, polluting its' + + ' namespace with all the static members you import. Readers of your' + + ' code (including you, a few months after you wrote it) will not' + + ' know which class a static member comes from (Sun 1.5 Language' + + ' Guide).' ), measurement: smm!DirectMeasurement ( error <- class.name + ' has too many static imports' @@ -454,7 +485,7 @@ rule MesureTooManyStaticImports(class : java!CompilationUnit) { } -- creates a new Measure when the method printStackTrace is used -rule MeasureAvoidPrintStackTrace(method : java!MethodInvocation) { +rule MeasureAvoidPrintStackTrace(method: java!MethodInvocation) { to om: smm!ObservedMeasure ( measure <- noc, @@ -462,10 +493,11 @@ rule MeasureAvoidPrintStackTrace(method : java!MethodInvocation) { ), noc: smm!DimensionalMeasure ( name <- 'Avoid print stack trace', - shortDescription <- 'Avoid printStackTrace(); use a logger call instead.' + shortDescription <- 'Avoid printStackTrace(); use a logger call instead.' ), - measurement: smm!DirectMeasurement ( - error<- 'The class '+ method.originalCompilationUnit.name + ' violates the rule avoid print stack trace.' + measurement: smm!DirectMeasurement ( + error <- 'The class ' + method.originalCompilationUnit.name + ' violates the' + + ' rule avoid print stack trace.' ) do { noc; @@ -473,7 +505,7 @@ rule MeasureAvoidPrintStackTrace(method : java!MethodInvocation) { } -- creates a new Measure when Thread.run() is used instead of Thread.start() -rule measureAvoidThreadGroup(variable : java!VariableDeclarationFragment) { +rule measureAvoidThreadGroup(variable: java!VariableDeclarationFragment) { to om: smm!ObservedMeasure ( measure <- noc, @@ -481,10 +513,13 @@ rule measureAvoidThreadGroup(variable : java!VariableDeclarationFragment) { ), noc: smm!DimensionalMeasure ( name <- 'Avoid Thread Group', - shortDescription <- 'Avoid using java.lang.ThreadGroup; although it is intended to be used in a threaded environment it contains methods that are not thread-safe.' + shortDescription <- 'Avoid using java.lang.ThreadGroup; although it is' + + ' intended to be used in a threaded environment it contains methods' + + ' that are not thread-safe.' ), - measurement: smm!DirectMeasurement ( - error<-'The class '+ variable.originalCompilationUnit.name + ' violates the rule avoid thread group.' + measurement: smm!DirectMeasurement ( + error <- 'The class ' + variable.originalCompilationUnit.name + ' violates' + + ' the rule avoid thread group.' ) do { @@ -492,9 +527,11 @@ rule measureAvoidThreadGroup(variable : java!VariableDeclarationFragment) { } } ---------------------------------------------- AvoidThrowingNewInstanceOfSameException --------------------------------------------- --- A Measure instance if the class violates the rule 'AvoidThrowingNewInstanceOfSameException'. -rule MeasureAvoidThrowingNewInstanceOfSameException(catch : java!CatchClause) { +--------------------------------------------- AvoidThrowingNewInstanceOfSameException +--- --------------------------------------------- +-- A Measure instance if the class violates the rule + -- 'AvoidThrowingNewInstanceOfSameException'. +rule MeasureAvoidThrowingNewInstanceOfSameException(catch: java!CatchClause) { to om: smm!ObservedMeasure ( measure <- noc, @@ -502,19 +539,24 @@ rule MeasureAvoidThrowingNewInstanceOfSameException(catch : java!CatchClause) { ), noc: smm!DimensionalMeasure ( name <- 'AvoidThrowingNewInstanceOfSameException', - shortDescription <- 'Catch blocks that merely rethrow a caught exception wrapped inside a new instance of the same type only add to code size and runtime complexity.' + shortDescription <- 'Catch blocks that merely rethrow a caught exception' + + ' wrapped inside a new instance of the same type only add to code' + + ' size and runtime complexity.' ), - measurement: smm!DirectMeasurement ( - error <-'The class '+ catch.originalCompilationUnit.name + ' has a method that rethrows a caught exception wrapped inside a new instance of the same type.' + measurement: smm!DirectMeasurement ( + error <- 'The class ' + catch.originalCompilationUnit.name + ' has a method' + + ' that rethrows a caught exception wrapped inside a new instance of' + + ' the same type.' ) do { noc; } } ---------------------------------------------- ReturnEmptyArrayRatherThanNull --------------------------------------------- +--------------------------------------------- ReturnEmptyArrayRatherThanNull +--- --------------------------------------------- -- creates a new Measure when a method returns an empty method rather than null -rule MesureReturnEmptyArrayRatherThanNull(method : java!ReturnStatement) { +rule MesureReturnEmptyArrayRatherThanNull(method: java!ReturnStatement) { to om: smm!ObservedMeasure ( measure <- noc, @@ -522,19 +564,22 @@ rule MesureReturnEmptyArrayRatherThanNull(method : java!ReturnStatement) { ), noc: smm!DimensionalMeasure ( name <- 'ReturnEmptyArrayRatherThanNull', - shortDescription <- 'For any method that returns an array, it is a better to return an empty array rather than a null reference.' + shortDescription <- 'For any method that returns an array, it is a better to' + + ' return an empty array rather than a null reference.' ), measurement: smm!DirectMeasurement ( - error <- 'A method in the class ' + method.originalCompilationUnit.name + ' returns null instead of an empty array.' + error <- 'A method in the class ' + method.originalCompilationUnit.name + '' + + ' returns null instead of an empty array.' ) do { noc; } } ---------------------------------------------- ExcessiveParameterList --------------------------------------------- +--------------------------------------------- ExcessiveParameterList +--- --------------------------------------------- -- creates a new Measure when a method has more than 10 parameters -rule MesureExcessiveParameterList(method : java!MethodDeclaration) { +rule MesureExcessiveParameterList(method: java!MethodDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, @@ -542,10 +587,12 @@ rule MesureExcessiveParameterList(method : java!MethodDeclaration) { ), noc: smm!DimensionalMeasure ( name <- 'ExcessiveParameterList', - shortDescription <- 'Methods with numerous parameters are a challenge to maintain, especially if most of them share the same datatype.' + shortDescription <- 'Methods with numerous parameters are a challenge to' + + ' maintain, especially if most of them share the same datatype.' ), - measurement: smm!DirectMeasurement ( - error<-'The method '+ method.name + ' in the class ' + method.originalCompilationUnit.name + ' has an excessive parameter list.' + measurement: smm!DirectMeasurement ( + error <- 'The method ' + method.name + ' in the class ' + method. + originalCompilationUnit.name + ' has an excessive parameter list.' ) do { noc; @@ -553,7 +600,8 @@ rule MesureExcessiveParameterList(method : java!MethodDeclaration) { } -- A Measure instance if the class violates the rule 'AvoidFieldNameMatchingMethodName'. -rule MesureAvoidFieldNameMatchingMethodName(class : java!ClassDeclaration, method : java!MethodDeclaration) { +rule MesureAvoidFieldNameMatchingMethodName(class: java!ClassDeclaration, method: + java!MethodDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, @@ -561,10 +609,15 @@ rule MesureAvoidFieldNameMatchingMethodName(class : java!ClassDeclaration, metho ), noc: smm!DimensionalMeasure ( name <- 'AvoidFieldNameMatchingMethodName', - shortDescription <- 'It can be confusing to have a field name with the same name as a method. While this is permitted, having information (field) and actions (method) is not clear naming. Developers versed in Smalltalk often prefer this approach as the methods denote accessor methods.' + shortDescription <- 'It can be confusing to have a field name with the same' + + ' name as a method. While this is permitted, having information' + + ' (field) and actions (method) is not clear naming. Developers' + + ' versed in Smalltalk often prefer this approach as the methods' + + ' denote accessor methods.' ), measurement: smm!DirectMeasurement ( - error <- 'In the ' + class.name + ' class you have an field and an method with the same name : '+ method.name + error <- 'In the ' + class.name + ' class you have an field and an method' + + ' with the same name : ' + method.name ) do { noc; @@ -580,10 +633,14 @@ rule MeasureUseNotifyAllInsteadOfNotify(method: java!MethodInvocation) { ), useNotifyAllInsteadOfNotify: smm!DimensionalMeasure ( name <- 'UseNotifyAllInsteadOfNotify', - shortDescription <- 'Thread.notify() awakens a thread monitoring the object. If more than one thread is monitoring, then only one is chosen. The thread chosen is arbitrary; thus its usually safer to call notifyAll() instead.' + shortDescription <- 'Thread.notify() awakens a thread monitoring the object.' + + ' If more than one thread is monitoring, then only one is chosen.' + + ' The thread chosen is arbitrary; thus its usually safer to call' + + ' notifyAll() instead.' ), measurement: smm!DirectMeasurement ( - error <- 'Used notify() instead of notifyAll() in Class : ' + method.originalCompilationUnit.name + error <- 'Used notify() instead of notifyAll() in Class : ' + method. + originalCompilationUnit.name ) do { useNotifyAllInsteadOfNotify; @@ -591,7 +648,8 @@ rule MeasureUseNotifyAllInsteadOfNotify(method: java!MethodInvocation) { } --- Creates a measure instance for each element that violates the rule : CommentRequired -rule MeasureCommentRequired(element: java!BodyDeclaration, violatedProperties: Set(String)) { +rule MeasureCommentRequired(element: java!BodyDeclaration, violatedProperties: + Set(String)) { to om: smm!ObservedMeasure ( measure <- commentRequired, @@ -599,14 +657,18 @@ rule MeasureCommentRequired(element: java!BodyDeclaration, violatedProperties: S ), commentRequired: smm!DimensionalMeasure ( name <- 'CommentRequired', - shortDescription <- 'Denotes whether comments are required (or unwanted) for specific language elements.' + shortDescription <- 'Denotes whether comments are required (or unwanted) for' + + ' specific language elements.' ), measurement: smm!DirectMeasurement ( - error <- 'Violated the properties ' + violatedProperties + ' in Class: ' + element.originalCompilationUnit.name + ' -> ' + element.oclType().name + ': ' + element.modifier.visibility + ' ' + element.getBodyDeclarationName() + error <- 'Violated the properties ' + violatedProperties + ' in Class: ' + + element.originalCompilationUnit.name + ' -> ' + element.oclType(). + name + ': ' + element.modifier.visibility + ' ' + element. + getBodyDeclarationName() ) do { commentRequired; - } + } } rule MeasureCommentContent(element: Sequence(String)){ @@ -617,39 +679,39 @@ rule MeasureCommentContent(element: Sequence(String)){ ), commentContent: smm!DimensionalMeasure ( name <- 'CommentContent', - shortDescription <- 'A rule for the politically correct… we don’t want to offend anyone.' + shortDescription <- 'A rule for the politically correct… we don’t want to' + + ' offend anyone.' ), measurement: smm!DirectMeasurement ( - error <- 'The words ' + element +' were found in a comment ' + error <- 'The words ' + element + ' were found in a comment ' ) do { - commentContent; - } + commentContent; + } } --- Returns the name of a BodyDeclaration -helper context java!BodyDeclaration def: getBodyDeclarationName() : String = - self.name; +helper context java!BodyDeclaration def: getBodyDeclarationName(): String = + self.name; ---- In FielDeclaration, the attribute 'name' is NULL, this information is contained in "fragments" instead -helper context java!FieldDeclaration def: getBodyDeclarationName() : String = - self.fragments.first().name; +--- In FielDeclaration, the attribute 'name' is NULL, this information is contained in +--- "fragments" instead +helper context java!FieldDeclaration def: getBodyDeclarationName(): String = + self.fragments.first().name; --- Returns the AnnotationTypeDeclaration corresponding to the given BodyDeclaration -- This is necessary because BodyDeclaration.annotations returns Sequence(!IN) -helper def: getAnnotationTypeDeclarationsFromBodyDeclaration(elem: java!BodyDeclaration): Set(java!AnnotationTypeDeclaration) = - java!AnnotationTypeDeclaration.allInstances() - ->select(annotTypeDec | - annotTypeDec.usagesInTypeAccess->exists(usage | - (usage.eContainer().eContainer().name = elem.name) - .and(usage.eContainer().eContainer().modifier.visibility = elem.modifier.visibility) - .and(usage.eContainer().eContainer().originalCompilationUnit.name = elem.originalCompilationUnit.name)) - ) -; +helper def: getAnnotationTypeDeclarationsFromBodyDeclaration(elem: java!BodyDeclaration): + Set(java!AnnotationTypeDeclaration) = + java!AnnotationTypeDeclaration.allInstances() -> select(annotTypeDec | annotTypeDec. + usagesInTypeAccess -> exists(usage | (usage.eContainer().eContainer().name = + elem.name).and(usage.eContainer().eContainer().modifier.visibility = elem. + modifier.visibility).and(usage.eContainer().eContainer(). + originalCompilationUnit.name = elem.originalCompilationUnit.name))); -- A Measure instance if the class violates the rule 'SuspiciousEqualsMethodName' -rule MeasureSuspiciousEqualsMethodName(method : java!MethodDeclaration) { +rule MeasureSuspiciousEqualsMethodName(method: java!MethodDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, @@ -657,18 +719,21 @@ rule MeasureSuspiciousEqualsMethodName(method : java!MethodDeclaration) { ), noc: smm!DimensionalMeasure ( name <- 'Suspicious Equals Method Name', - shortDescription <- 'The method name and parameter number are suspiciously close to equals(Object), which can denote an intention to override the equals(Object) method.' + shortDescription <- 'The method name and parameter number are suspiciously' + + ' close to equals(Object), which can denote an intention to' + + ' override the equals(Object) method.' ), measurement: smm!DirectMeasurement ( - error <- 'The class ' + method.originalCompilationUnit.name + ' has a suspicious \'equals\' method name : ' + method.toString() + error <- 'The class ' + method.originalCompilationUnit.name + ' has a' + + ' suspicious \'equals\' method name : ' + method.toString() ) do { - noc; + noc; } } -- A Measure instance if the class violates the rule 'AvoidUsingShortType' -rule MeasureAvoidUsingShortType(typeShort : java!VariableDeclarationStatement) { +rule MeasureAvoidUsingShortType(typeShort: java!VariableDeclarationStatement) { to om: smm!ObservedMeasure ( measure <- noc, @@ -676,22 +741,25 @@ rule MeasureAvoidUsingShortType(typeShort : java!VariableDeclarationStatement) { ), noc: smm!DimensionalMeasure ( name <- 'Avoid using short type', - shortDescription <- 'Java uses the \'short\' type to reduce memory usage, not to optimize calculation.' - + ' In fact, the JVM does not have any arithmetic capabilities for the short type:' - + ' the JVM must convert the short into an int, do the proper calculation and convert' - + ' the int back to a short. Thus any storage gains found through use of the \'short\' type' - + ' may be offset by adverse impacts on performance.' + shortDescription <- 'Java uses the \'short\' type to reduce memory usage, not' + + ' to optimize calculation.' + ' In fact, the JVM does not have any' + + ' arithmetic capabilities for the short type:' + ' the JVM must' + + ' convert the short into an int, do the proper calculation and' + + ' convert' + ' the int back to a short. Thus any storage gains' + + ' found through use of the \'short\' type' + ' may be offset by' + + ' adverse impacts on performance.' ), measurement: smm!DirectMeasurement ( - error <- 'The class ' + typeShort.originalCompilationUnit.name + ' has \'short\' type variable.' + error <- 'The class ' + typeShort.originalCompilationUnit.name + ' has' + + ' \'short\' type variable.' ) do { - noc; + noc; } } -- A Measure instance if the class violates the rule 'EmptyStatementBlock' -rule MeasureEmptyStatementBlock(block : java!Block) { +rule MeasureEmptyStatementBlock(block: java!Block) { to om: smm!ObservedMeasure ( measure <- noc, @@ -699,19 +767,22 @@ rule MeasureEmptyStatementBlock(block : java!Block) { ), noc: smm!DimensionalMeasure ( name <- 'Empty Statement Block', - shortDescription <- 'Empty block statements serve no purpose and should be removed.' + shortDescription <- 'Empty block statements serve no purpose and should be' + + ' removed.' ), measurement: smm!DirectMeasurement ( - error <- 'The class ' + block.originalCompilationUnit.name + ' has an empty statement block.' + error <- 'The class ' + block.originalCompilationUnit.name + ' has an empty' + + ' statement block.' ) do { - noc; + noc; } } ---------------------------------------------- DoNotExtendJavaLangError --------------------------------------------- +--------------------------------------------- DoNotExtendJavaLangError +--- --------------------------------------------- -- A Measure instance if the class violates the rule DoNotExtendJavaLangError. -rule MeasureDoNotExtendJavaLangError(variable : java!ClassDeclaration) { +rule MeasureDoNotExtendJavaLangError(variable: java!ClassDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, @@ -720,10 +791,10 @@ rule MeasureDoNotExtendJavaLangError(variable : java!ClassDeclaration) { noc: smm!DimensionalMeasure ( name <- 'DoNotExtendJavaLangError ', shortDescription <- 'Errors are system exceptions. Do not extend them.' - ), - measurement: smm!DirectMeasurement ( - error<-'In the Class '+ variable.name + ' Do not extend Error, Errors are system exceptions.' + measurement: smm!DirectMeasurement ( + error <- 'In the Class ' + variable.name + ' Do not extend Error, Errors are' + + ' system exceptions.' ) do { @@ -731,9 +802,10 @@ rule MeasureDoNotExtendJavaLangError(variable : java!ClassDeclaration) { } } ---------------------------------------------- MeasureFinalFieldCouldBeStatic --------------------------------------------- +--------------------------------------------- MeasureFinalFieldCouldBeStatic +--- --------------------------------------------- -- A Measure instance if the class violates the rule MeasureFinalFieldCouldBeStatic. -rule MeasureFinalFieldCouldBeStatic(field : java!FieldDeclaration) { +rule MeasureFinalFieldCouldBeStatic(field: java!FieldDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, @@ -741,11 +813,14 @@ rule MeasureFinalFieldCouldBeStatic(field : java!FieldDeclaration) { ), noc: smm!DimensionalMeasure ( name <- 'FinalFieldCouldBeStatic', - shortDescription <- 'If a final field is assigned to a compile-time constant, it could be made static, thus saving overhead in each object at runtime.' - + shortDescription <- 'If a final field is assigned to a compile-time constant,' + + ' it could be made static, thus saving overhead in each object at' + + ' runtime.' ), - measurement: smm!DirectMeasurement ( - error<-'The field '+ field.fragments->collect(i | i.name)->first() + ' could be static in the class ' + field.originalCompilationUnit.name +'.' + measurement: smm!DirectMeasurement ( + error <- 'The field ' + field.fragments -> collect(i | i.name) -> first() + '' + + ' could be static in the class ' + field.originalCompilationUnit. + name + '.' ) do { @@ -753,10 +828,10 @@ rule MeasureFinalFieldCouldBeStatic(field : java!FieldDeclaration) { } } - ---------------------------------------------- MeasureExtendsObject --------------------------------------------- +--------------------------------------------- MeasureExtendsObject +--- --------------------------------------------- -- A Measure instance if the class violates the rule ExtendsObject. -rule MeasureExtendsObject(variable : java!ClassDeclaration) { +rule MeasureExtendsObject(variable: java!ClassDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, @@ -765,10 +840,10 @@ rule MeasureExtendsObject(variable : java!ClassDeclaration) { noc: smm!DimensionalMeasure ( name <- 'ExtendsObject', shortDescription <- 'No need to explicitly extend Object.' - ), - measurement: smm!DirectMeasurement ( - error<-'In the Class '+ variable.name + ' No need to explicitly extend Object.' + measurement: smm!DirectMeasurement ( + error <- 'In the Class ' + variable.name + ' No need to explicitly extend' + + ' Object.' ) do { @@ -776,9 +851,10 @@ rule MeasureExtendsObject(variable : java!ClassDeclaration) { } } ---------------------------------------------- SwitchDensity --------------------------------------------- +--------------------------------------------- SwitchDensity +--- --------------------------------------------- -- A Measure instance if the class violates the rule SwitchDensity. -rule MeasureSwitchDensity(switch : java!SwitchStatement) { +rule MeasureSwitchDensity(switch: java!SwitchStatement) { to om: smm!ObservedMeasure ( @@ -786,21 +862,22 @@ rule MeasureSwitchDensity(switch : java!SwitchStatement) { measurements <- measurement ), noc: smm!DimensionalMeasure ( - name <- 'SwitchDensity ', shortDescription <- 'Statement to label ratio is too high (> 10)' - ), - measurement: smm!DirectMeasurement ( - error<-'In the Class '+ switch.originalCompilationUnit.name + ' a switch case contains too many statements.' + measurement: smm!DirectMeasurement ( + error <- 'In the Class ' + switch.originalCompilationUnit.name + ' a switch' + + ' case contains too many statements.' ) do { noc; } -} ---------------------------------------------- SignatureDeclareThrowsException --------------------------------------------- +} + +--------------------------------------------- SignatureDeclareThrowsException +--- --------------------------------------------- -- A Measure instance if the class violates the rule SignatureDeclareThrowsException. -rule MeasureSignatureDeclareThrowsException(class : java!ClassDeclaration) { +rule MeasureSignatureDeclareThrowsException(class: java!ClassDeclaration) { to om: smm!ObservedMeasure ( @@ -808,22 +885,23 @@ rule MeasureSignatureDeclareThrowsException(class : java!ClassDeclaration) { measurements <- measurement ), noc: smm!DimensionalMeasure ( - name <- 'SignatureDeclareThrowsException ', - shortDescription <- 'A method/constructor should not explicitly throw the generic java.lang.Exception' - + shortDescription <- 'A method/constructor should not explicitly throw the' + + ' generic java.lang.Exception' ), - measurement: smm!DirectMeasurement ( - error<-'In the Class '+ class.name + ' a method/constructor explicitly throws the generic java.lang.Exception.' + measurement: smm!DirectMeasurement ( + error <- 'In the Class ' + class.name + ' a method/constructor explicitly' + + ' throws the generic java.lang.Exception.' ) do { noc; } -} +} ---------------------------------------------- UnnecessaryReturn --------------------------------------------- +--------------------------------------------- UnnecessaryReturn +--- --------------------------------------------- -- A Measure instance if the class violates the rule UnnecessaryReturn. -rule MeasureUnnecessaryReturn(state : java!ReturnStatement) { +rule MeasureUnnecessaryReturn(state: java!ReturnStatement) { to om: smm!ObservedMeasure ( @@ -831,23 +909,22 @@ rule MeasureUnnecessaryReturn(state : java!ReturnStatement) { measurements <- measurement ), noc: smm!DimensionalMeasure ( - name <- 'UnnecessaryReturn ', shortDescription <- 'Avoid the use of unnecessary return statements.' - ), - measurement: smm!DirectMeasurement ( - error<-'In the Class '+ state.originalCompilationUnit.name + ' an unnecessary return was used.' + measurement: smm!DirectMeasurement ( + error <- 'In the Class ' + state.originalCompilationUnit.name + ' an' + + ' unnecessary return was used.' ) do { noc; } } - ---------------------------------------------- MeasureCompareObjectsWithEquals --------------------------------------------- +--------------------------------------------- MeasureCompareObjectsWithEquals +--- --------------------------------------------- --A measure instance if the class violates the rule MeasureCompareObjectsWithEquals. -rule MeasureCompareObjectsWithEquals(expression : java!InfixExpression) { +rule MeasureCompareObjectsWithEquals(expression: java!InfixExpression) { to om: smm!ObservedMeasure ( measure <- noc, @@ -855,56 +932,61 @@ rule MeasureCompareObjectsWithEquals(expression : java!InfixExpression) { ), noc: smm!DimensionalMeasure ( name <- 'CompareObjectsWithEquals', - shortDescription <- 'Use equals() to compare object references; avoid comparing them with ==.' - + shortDescription <- 'Use equals() to compare object references; avoid' + + ' comparing them with ==.' ), - measurement: smm!DirectMeasurement ( - error<-'The Class '+ expression.originalCompilationUnit.name + ' is using == instead of equals() to compare objects.' + measurement: smm!DirectMeasurement ( + error <- 'The Class ' + expression.originalCompilationUnit.name + ' is using' + + ' == instead of equals() to compare objects.' ) do { noc; } -} - +} ---------------------------------------------- AvoidRethrowingException --------------------------------------------- - --A Measure instance if the class violates the rule AvoidRethrowingException. -rule MeasureAvoidRethrowingException(statement : java!TryStatement) { +--------------------------------------------- AvoidRethrowingException +--- --------------------------------------------- +--A Measure instance if the class violates the rule AvoidRethrowingException. +rule MeasureAvoidRethrowingException(statement: java!TryStatement) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( - name <- 'AvoidRethrowingException ', shortDescription <- 'Avoid merely rethrowing an exception.' - ), - measurement: smm!DirectMeasurement ( - error<-'In the Class '+ statement.originalCompilationUnit.name + ' an exception was caught and merely rethrown.' + measurement: smm!DirectMeasurement ( + error <- 'In the Class ' + statement.originalCompilationUnit.name + ' an' + + ' exception was caught and merely rethrown.' ) do { noc; } -} - ---------------------------------------------- IntegerInstantiation --------------------------------------------- +} + +--------------------------------------------- IntegerInstantiation +--- --------------------------------------------- -- A Measure instance if the class violates the rule 'IntegerInstantiation'. -rule MeasureIntegerInstantiation(variable : java!CompilationUnit) { +rule MeasureIntegerInstantiation(variable: java!CompilationUnit) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( - name <- 'IntegerInstantiation', - shortDescription <- 'Calling new Integer() causes memory allocation that can be avoided by the static Integer.valueOf(). It makes use of an internal cache that recycles earlier instances making it more memory efficient. Note that new Integer() is deprecated since JDK 9 for that reason.' + shortDescription <- 'Calling new Integer() causes memory allocation that can' + + ' be avoided by the static Integer.valueOf(). It makes use of an' + + ' internal cache that recycles earlier instances making it more' + + ' memory efficient. Note that new Integer() is deprecated since JDK' + + ' 9 for that reason.' ), - measurement: smm!DirectMeasurement ( - error<-'In the Class '+ variable.name + ' an instantiation of Integer must be Integer.ValueOf().' + measurement: smm!DirectMeasurement ( + error <- 'In the Class ' + variable.name + ' an instantiation of Integer must' + + ' be Integer.ValueOf().' ) do { @@ -912,9 +994,10 @@ rule MeasureIntegerInstantiation(variable : java!CompilationUnit) { } } ---------------------------------------------- LongVariable --------------------------------------------- +--------------------------------------------- LongVariable +--- --------------------------------------------- -- A Measure instance if the variable violates the rule LongVariable. -rule MeasureLongVariable(variable : java!VariableDeclarationFragment) { +rule MeasureLongVariable(variable: java!VariableDeclarationFragment) { to om: smm!ObservedMeasure ( measure <- noc, @@ -922,19 +1005,21 @@ rule MeasureLongVariable(variable : java!VariableDeclarationFragment) { ), noc: smm!DimensionalMeasure ( name <- 'LongVariable', - shortDescription <- ': Fields, formal arguments, or local variable names that are too long can make the code difficult ' + shortDescription <- ': Fields, formal arguments, or local variable names that' + + ' are too long can make the code difficult ' ), measurement: smm!DirectMeasurement ( - error <- variable.name + ' is too Long ' + error <- variable.name + ' is too Long ' ) do { noc; } } ---------------------------------------------- AvoidCallingFinalize --------------------------------------------- +--------------------------------------------- AvoidCallingFinalize +--- --------------------------------------------- -- A Measure instance if the class violates the rule LongVariable. -rule MeasureAvoidCallingFinalize(methode : java!MethodInvocation) { +rule MeasureAvoidCallingFinalize(methode: java!MethodInvocation) { to om: smm!ObservedMeasure ( measure <- noc, @@ -942,19 +1027,22 @@ rule MeasureAvoidCallingFinalize(methode : java!MethodInvocation) { ), noc: smm!DimensionalMeasure ( name <- 'AvoidCallingFinalize', - shortDescription <- ': The method Object.finalize() is called by the garbage collector on an object when garbage collect... ' + shortDescription <- ': The method Object.finalize() is called by the garbage' + + ' collector on an object when garbage collect... ' ), measurement: smm!DirectMeasurement ( - error <- 'finalize() is called in class' + methode.originalCompilationUnit.name + error <- 'finalize() is called in class' + methode.originalCompilationUnit. + name ) do { noc; } } ---------------------------------------------- AvoidStringBufferField --------------------------------------------- +--------------------------------------------- AvoidStringBufferField +--- --------------------------------------------- -- A Measure instance if the class violates AvoidStringBufferField . -rule MeasureAvoidStringBufferField(declaration : java!VariableDeclaration) { +rule MeasureAvoidStringBufferField(declaration: java!VariableDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, @@ -962,10 +1050,12 @@ rule MeasureAvoidStringBufferField(declaration : java!VariableDeclaration) { ), noc: smm!DimensionalMeasure ( name <- 'AvoidStringBufferField', - shortDescription <- ': StringBuffers/StringBuilders can grow considerably, and so may become a source of memory leaksif ...' + shortDescription <- ': StringBuffers/StringBuilders can grow considerably,' + + ' and so may become a source of memory leaksif ...' ), measurement: smm!DirectMeasurement ( - error <- 'AvoidStringBufferField is detected in ' + declaration.originalCompilationUnit.name + error <- 'AvoidStringBufferField is detected in ' + declaration. + originalCompilationUnit.name ) do { noc; @@ -974,7 +1064,7 @@ rule MeasureAvoidStringBufferField(declaration : java!VariableDeclaration) { --------------------- AvoidThrowingNullPointerException---------------------------------- -- A Measure instance if the class violates AvoidThrowingNullPointerException . -rule MeasureAvoidThrowingNullPointerException(c : java!ClassInstanceCreation) { +rule MeasureAvoidThrowingNullPointerException(c: java!ClassInstanceCreation) { to om: smm!ObservedMeasure ( measure <- noc, @@ -982,20 +1072,22 @@ rule MeasureAvoidThrowingNullPointerException(c : java!ClassInstanceCreation) { ), noc: smm!DimensionalMeasure ( name <- 'AvoidThrowingNullPointerException', - shortDescription <- 'Avoid throwing NullPointerExceptions manually. These are confusing because most people will assume that the virtual machine threw it' + shortDescription <- 'Avoid throwing NullPointerExceptions manually. These are' + + ' confusing because most people will assume that the virtual' + + ' machine threw it' ), measurement: smm!DirectMeasurement ( - error <- 'AvoidThrowingNullPointerException is detected in ' + c.originalCompilationUnit.name + error <- 'AvoidThrowingNullPointerException is detected in ' + c. + originalCompilationUnit.name ) do { noc; } } - --------------------- EmptyTryBlock---------------------------------- --A measure instance if the class violates the rule EmptyTryBlock. -rule MeasureEmptyTryBlock(t : java!TryStatement) { +rule MeasureEmptyTryBlock(t: java!TryStatement) { to om: smm!ObservedMeasure ( measure <- noc, @@ -1015,7 +1107,7 @@ rule MeasureEmptyTryBlock(t : java!TryStatement) { ---------------------EmptyWhileStmt---------------------------------- --A measure instance if the class violates the rule EmptyWhileStmt. -rule MeasureEmptyWhileStmt(w : java!TryStatement) { +rule MeasureEmptyWhileStmt(w: java!TryStatement) { to om: smm!ObservedMeasure ( measure <- noc, @@ -1023,7 +1115,8 @@ rule MeasureEmptyWhileStmt(w : java!TryStatement) { ), noc: smm!DimensionalMeasure ( name <- 'EmptyWhileStmt', - shortDescription <- ': Empty While Statement finds all instances where a while statement does nothing.' + shortDescription <- ': Empty While Statement finds all instances where a' + + ' while statement does nothing.' ), measurement: smm!DirectMeasurement ( error <- 'EmptyWhileStmt is detected in ' + w.originalCompilationUnit.name @@ -1033,46 +1126,86 @@ rule MeasureEmptyWhileStmt(w : java!TryStatement) { } } -------------------------------------------- MeasureDontImportSun---------------------------------------------- +------------------------------------------- +--- MeasureDontImportSun---------------------------------------------- -- A Measure instance if the class violate the rule DontImportSun -rule MeasureDontImportSun(p : java!CompilationUnit) { +rule MeasureDontImportSun(p: java!CompilationUnit) { to om: smm!ObservedMeasure ( - measure <- noc, - measurements <- measurement - ), - noc: smm!DimensionalMeasure ( - name <- 'DontImportSun', - shortDescription <- ' : Avoid importing anything from the sun. packages.' - ), - measurement: smm!DirectMeasurement ( - error <- ' Import Sun. , is detected in '+ p -> collect(i | i.name) - ) + measure <- noc, + measurements <- measurement + ), + noc: smm!DimensionalMeasure ( + name <- 'DontImportSun', + shortDescription <- ' : Avoid importing anything from the sun. packages.' + ), + measurement: smm!DirectMeasurement ( + error <- ' Import Sun. , is detected in ' + p -> collect(i | i.name) + ) do { noc; } } -------------------------------------------- FinalizeShouldBeProtected---------------------------------------------- +------------------------------------------- +--- FinalizeShouldBeProtected---------------------------------------------- -- A Measure instance if the class violate the rule FinalizeShouldBeProtected -rule MesureFinalizeShouldBeProtected(m : java!MethodDeclaration) { +rule MesureFinalizeShouldBeProtected(m: java!MethodDeclaration) { to om: smm!ObservedMeasure ( - measure <- noc, - measurements <- measurement - ), - noc: smm!DimensionalMeasure ( - name <- 'FinalizeShouldBeProtected', - shortDescription <- ' : When overriding the finalize(), the new method should be set as protected. ' - ), - measurement: smm!DirectMeasurement ( - error <- 'Finalize is not protected in class : ' + m.originalCompilationUnit.name - ) + measure <- noc, + measurements <- measurement + ), + noc: smm!DimensionalMeasure ( + name <- 'FinalizeShouldBeProtected', + shortDescription <- ' : When overriding the finalize(), the new method should' + + ' be set as protected. ' + ), + measurement: smm!DirectMeasurement ( + error <- 'Finalize is not protected in class : ' + m.originalCompilationUnit. + name + ) do { noc; } } +-- Khaled AMIRAT +-- A Measure instance if the class violates the rule 'AvoidFieldNameMatchingMethodName'. +rule MesureAvoidNoPackageDeclaration(class : java!CompilationUnit) { + to + om: smm!ObservedMeasure ( + measure <- noc, + measurements <- measurement + ), + noc: smm!DimensionalMeasure ( + name <- 'AvoidNoPackageDeclaration', + shortDescription <- 'you need to declare some package.' + ), + measurement: smm!DirectMeasurement ( + error <- 'In the ' + class.name + ' class have no package declaration' + ) + do { + noc; + } +} - +rule MeasureUnconditionalIfStatement(w: java!IfStatement) { + to + om: smm!ObservedMeasure ( + measure <- noc, + measurements <- measurement + ), + noc: smm!DimensionalMeasure ( + name <- 'UnconditionalIfStatement', + shortDescription <- ': UnconditionalIfStatement finds all instances where a' + + ' UnconditionalIfStatement statement does nothing.' + ), + measurement: smm!DirectMeasurement ( + error <- 'UnconditionalIfStatement is detected in ' + w.originalCompilationUnit.name + ) + do { + noc; + } +} \ No newline at end of file diff --git a/src/main/atl/bestPractices.atl b/src/main/atl/bestPractices.atl index 8d069f70d44df59d13a2fc036e3d27f3e2b24d84..58d0b5ba3d4c7afa43aa108d414aacece008dde4 100644 --- a/src/main/atl/bestPractices.atl +++ b/src/main/atl/bestPractices.atl @@ -68,4 +68,9 @@ helper def: switchDensity() : Set (smm!Measure) = helper def: avoidStringBufferField() : Set(smm!Measure) = java!FieldDeclaration.allInstances() ->select(dec | dec.type.type.name = 'StringBuffer' or dec.type.type.name = 'StringBuilder') - ->collect(dec | thisModule.MeasureAvoidStringBufferField(dec)); \ No newline at end of file + ->collect(dec | thisModule.MeasureAvoidStringBufferField(dec)); + + + + + diff --git a/src/main/atl/codestyle.atl b/src/main/atl/codestyle.atl index cc9c2eec17e1da68ad2029751d93ce342cc1be6d..099f0c55266238af4824ab8bb8b0898a19aa0570 100644 --- a/src/main/atl/codestyle.atl +++ b/src/main/atl/codestyle.atl @@ -1,3 +1,6 @@ +-- @nsURI smm=http://www.eclipse.org/MoDisco/SMM/1.0.Beta2/smm +-- @nsURI java=http://www.eclipse.org/MoDisco/Java/0.2.incubation/java + library codestyle; ------------------------------------------------------------------------------------------ @@ -64,3 +67,19 @@ helper def: longVariable() : Set(smm!Measure) = -> select( variable | variable.name.size() > 17) -> collect (variable | thisModule.MeasureLongVariable(variable)); +--====Khaled AMIRAT no package declaration +-- Rule for metrics noPackageDeclaration : return the set of class Measures that violates the rule. +helper def: noPackageDeclaration() : Set(smm!Measure) = + -- Browse through all class(CompilationUnit) + java!CompilationUnit.allInstances() + ->select(compUnit | compUnit.package.oclIsUndefined()) + ->collect(err | thisModule.MesureAvoidNoPackageDeclaration(err)); + + +--====Khaled AMIRAT no package declaration +-- Rule for metrics noPackageDeclaration : return the set of class Measures that violates the rule. +helper def: UnconditionalIfStatement() : Set(smm!Measure) = + -- Browse through all class(CompilationUnit) + java!IfStatement.allInstances() + ->select( w | w.expression.oclIsTypeOf(java!BooleanLiteral)) + ->collect(w | thisModule.MeasureUnconditionalIfStatement(w));