-- @nsURI smm=http://www.eclipse.org/MoDisco/SMM/1.0.Beta2/smm -- @nsURI java=http://www.eclipse.org/MoDisco/Java/0.2.incubation/java module analysis; create OUT: smm from IN: java; uses design; uses codestyle; uses multithreading; uses performance; uses bestPractices; uses documentation; uses errorProne; rule Java2SMM { from project: java!Model to model: smm!SmmModel ( name <- project.name, librairies <- lib ), lib: smm!MeasureLibrary ( name <- 'Java metrics', measureElements <- thisModule.allMeasures(project) ) } helper def: allMeasures(project: java!Model): Set(smm!Measure) = Set{-- Example rule -- thisModule.numberOfClasses(), -- Multithreading rules -- thisModule.dontCallThreadRun(), thisModule.avoidThreadGroup(), thisModule.useNotifyAllInsteadOfNotify(), -- Code Style rules -- thisModule.shortMethodName(), thisModule.tooManyStaticImports(), thisModule.avoidDollarSigns(), thisModule.shortClassName(), thisModule.extendsObject(), thisModule.unnecessaryReturn(), thisModule.longVariable(), thisModule.noPackageDeclaration(), thisModule.UnconditionalIfStatement(), thisModule.EmptyInitializer(), thisModule.ExcessiveClassLength(), thisModule.CloneMethodMustBePublic(), -- Design rules -- thisModule.tooManyFields(), thisModule.tooManyMethods(), thisModule.returnFromFinallyBlock(), thisModule.longInstantiation(), thisModule.shortInstantiation(), --thisModule.returnEmptyArrayRatherThanNull(), thisModule.excessiveParameterList(), 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.commentContent(), 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(), -- Best practices rules thisModule.avoidThrowingNewInstanceOfSameException(), 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) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), 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.' ), 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) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'AvoidDollarSigns', shortDescription <- 'Avoid using dollar signs in' + ' variable/method/class/interface names.' ), measurement: smm!DirectMeasurement ( error <- node.name + ' has dollar in ' + node.originalCompilationUnit.name ) do { noc; } } -- A Measure instance if the class violates the rule 'ShortMethodName'. rule MesureShortMethodName(method: java!MethodDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'ShortMethodName', 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 ) do { noc; } } -- A Measure instance if the class violates the rule 'ShortClassName'. rule MesureShortClassName(class: java!ClassDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'ShortClassName', shortDescription <- 'Short Classnames with fewer than e.g. five characters' + ' are not recommended.' ), measurement: smm!DirectMeasurement ( error <- 'The Class ' + class.name + ' is too short.' ) do { noc; } } -- creates a new Measure when Thread.run() is used instead of Thread.start() rule MeasureDontCallThreadRun(method: java!MethodInvocation) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), 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.' ), 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) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'TooManyFields', 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' ) do { noc; } } -- 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, measurements <- measurement ), 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.' ), measurement: smm!DirectMeasurement ( error <- 'The class ' + method.originalCompilationUnit.name + ' violates the' + ' rule index of char.' ) do { noc; } } ------------------------------------------------------------------------------------------ rule numberOfClasses() { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'Number of Classes' ), measurement: smm!DirectMeasurement ( value <- java!ClassDeclaration.allInstances() -> reject(each | each. isProxy()) -> size() ) do { noc; } } -- 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 ( measure <- tooFewBranchesForASwitchStatement, measurements <- measurement ), 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.' ), measurement: smm!DirectMeasurement ( error <- 'Too few branches for SwitchStatement in Class : ' + switchStatement. originalCompilationUnit.name, value <- thisModule.nbBranchesOfASwitchStatement(switchStatement) ) do { tooFewBranchesForASwitchStatement; } } --------------------------------------------- ShortInstantiation --- --------------------------------------------- -- A Measure instance if the class violates the rule 'ShortInstantiation'. rule MeasureShortInstantiation(variable: java!CompilationUnit) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), 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.' ), measurement: smm!DirectMeasurement ( error <- 'In the Class ' + variable.name + ' an instantiation of Short must' + ' be Short.ValueOf().' ) do { noc; } } --------------------------------------------- LongInstantiation --- --------------------------------------------- -- A Measure instance if the class violates the rule 'LongInstantiation'. rule MeasureLongInstantiation(variable: java!CompilationUnit) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), 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.' ), measurement: smm!DirectMeasurement ( error <- 'In the Class ' + variable.name + ' an instantiation of Long must be' + ' Long.ValueOf().' ) do { noc; } } --------------------------------------------- DoNotExtendJavaLangThrowable --- --------------------------------------------- -- A Measure instance if the class violates the rule DoNotExtendJavaLangThrowable. rule MeasureDoNotExtendJavaLangThrowable(variable: java!ClassDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'DoNotExtendJavaLangThrowable ', 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 .' ) 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(); -- Returns the number of Fields in Class helper def: numberFieldsInClasse(s: java!ClassDeclaration): Integer = -- Return the number of FieldDeclaration in a class. 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(); -- 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 -- To test, use input model : missing-break-in-switch.xmi rule createMeasureForMissingBreakInSwitch(ss: java!SwitchStatement) { to om: smm!ObservedMeasure ( measure <- missingBreakInSwitch, measurements <- measurement ), 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.' ), measurement: smm!DirectMeasurement ( 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) ) do { missingBreakInSwitch; } } -- A Measure instance if the class violates the rule 'TooManyMethods'. rule MesureTooManyMethods(class: java!ClassDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), 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.' ), measurement: smm!DirectMeasurement ( error <- class.originalCompilationUnit.name + ' has too many methods' ) do { noc; } } -- A Measure instance if the class violates the rule ReturnFromFinallyBlock. rule MesureReturnFromFinallyBlock(method: java!MethodDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'returnFromFinallyBlock', 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.' ) do { noc; } } -- A Measure instance if the class violates the rule 'TooManyStaticImports'. rule MesureTooManyStaticImports(class: java!CompilationUnit) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), 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).' ), measurement: smm!DirectMeasurement ( error <- class.name + ' has too many static imports' ) do { noc; } } -- creates a new Measure when the method printStackTrace is used rule MeasureAvoidPrintStackTrace(method: java!MethodInvocation) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'Avoid print stack trace', shortDescription <- 'Avoid printStackTrace(); use a logger call instead.' ), measurement: smm!DirectMeasurement ( error <- 'The class ' + method.originalCompilationUnit.name + ' violates the' + ' rule avoid print stack trace.' ) do { noc; } } -- creates a new Measure when Thread.run() is used instead of Thread.start() rule measureAvoidThreadGroup(variable: java!VariableDeclarationFragment) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), 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.' ), measurement: smm!DirectMeasurement ( error <- 'The class ' + variable.originalCompilationUnit.name + ' violates' + ' the rule avoid thread group.' ) do { noc; } } --------------------------------------------- AvoidThrowingNewInstanceOfSameException --- --------------------------------------------- -- A Measure instance if the class violates the rule -- 'AvoidThrowingNewInstanceOfSameException'. rule MeasureAvoidThrowingNewInstanceOfSameException(catch: java!CatchClause) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), 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.' ), 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 --- --------------------------------------------- -- creates a new Measure when a method returns an empty method rather than null rule MesureReturnEmptyArrayRatherThanNull(method: java!ReturnStatement) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), 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.' ), measurement: smm!DirectMeasurement ( error <- 'A method in the class ' + method.originalCompilationUnit.name + '' + ' returns null instead of an empty array.' ) do { noc; } } --------------------------------------------- ExcessiveParameterList --- --------------------------------------------- -- creates a new Measure when a method has more than 10 parameters rule MesureExcessiveParameterList(method: java!MethodDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'ExcessiveParameterList', 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.' ) do { noc; } } -- A Measure instance if the class violates the rule 'AvoidFieldNameMatchingMethodName'. rule MesureAvoidFieldNameMatchingMethodName(class: java!ClassDeclaration, method: java!MethodDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), 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.' ), measurement: smm!DirectMeasurement ( error <- 'In the ' + class.name + ' class you have an field and an method' + ' with the same name : ' + method.name ) do { noc; } } -- Creates a measure instance when rule 'UseNotifyAllInsteadOfNotify' is violated rule MeasureUseNotifyAllInsteadOfNotify(method: java!MethodInvocation) { to om: smm!ObservedMeasure ( measure <- useNotifyAllInsteadOfNotify, measurements <- measurement ), 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.' ), measurement: smm!DirectMeasurement ( error <- 'Used notify() instead of notifyAll() in Class : ' + method. originalCompilationUnit.name ) do { useNotifyAllInsteadOfNotify; } } --- Creates a measure instance for each element that violates the rule : CommentRequired rule MeasureCommentRequired(element: java!BodyDeclaration, violatedProperties: Set(String)) { to om: smm!ObservedMeasure ( measure <- commentRequired, measurements <- measurement ), commentRequired: smm!DimensionalMeasure ( name <- 'CommentRequired', 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() ) do { commentRequired; } } rule MeasureCommentContent(element: Sequence(String)){ to om: smm!ObservedMeasure ( measure <- commentContent, measurements <- measurement ), commentContent: smm!DimensionalMeasure ( name <- 'CommentContent', 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 ' ) do { commentContent; } } --- Returns the name of a BodyDeclaration 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; --- 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))); -- A Measure instance if the class violates the rule 'SuspiciousEqualsMethodName' rule MeasureSuspiciousEqualsMethodName(method: java!MethodDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), 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.' ), measurement: smm!DirectMeasurement ( error <- 'The class ' + method.originalCompilationUnit.name + ' has a' + ' suspicious \'equals\' method name : ' + method.toString() ) do { noc; } } -- A Measure instance if the class violates the rule 'AvoidUsingShortType' rule MeasureAvoidUsingShortType(typeShort: java!VariableDeclarationStatement) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), 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.' ), measurement: smm!DirectMeasurement ( error <- 'The class ' + typeShort.originalCompilationUnit.name + ' has' + ' \'short\' type variable.' ) do { noc; } } -- A Measure instance if the class violates the rule 'EmptyStatementBlock' rule MeasureEmptyStatementBlock(block: java!Block) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'Empty Statement Block', 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.' ) do { noc; } } --------------------------------------------- DoNotExtendJavaLangError --- --------------------------------------------- -- A Measure instance if the class violates the rule DoNotExtendJavaLangError. rule MeasureDoNotExtendJavaLangError(variable: java!ClassDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), 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.' ) do { noc; } } --------------------------------------------- MeasureFinalFieldCouldBeStatic --- --------------------------------------------- -- A Measure instance if the class violates the rule MeasureFinalFieldCouldBeStatic. rule MeasureFinalFieldCouldBeStatic(field: java!FieldDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), 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.' ), measurement: smm!DirectMeasurement ( error <- 'The field ' + field.fragments -> collect(i | i.name) -> first() + '' + ' could be static in the class ' + field.originalCompilationUnit. name + '.' ) do { noc; } } --------------------------------------------- MeasureExtendsObject --- --------------------------------------------- -- A Measure instance if the class violates the rule ExtendsObject. rule MeasureExtendsObject(variable: java!ClassDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), 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.' ) do { noc; } } --------------------------------------------- SwitchDensity --- --------------------------------------------- -- A Measure instance if the class violates the rule SwitchDensity. rule MeasureSwitchDensity(switch: java!SwitchStatement) { to om: smm!ObservedMeasure ( measure <- noc, 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.' ) do { noc; } } --------------------------------------------- SignatureDeclareThrowsException --- --------------------------------------------- -- A Measure instance if the class violates the rule SignatureDeclareThrowsException. rule MeasureSignatureDeclareThrowsException(class: java!ClassDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'SignatureDeclareThrowsException ', 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.' ) do { noc; } } --------------------------------------------- UnnecessaryReturn --- --------------------------------------------- -- A Measure instance if the class violates the rule UnnecessaryReturn. rule MeasureUnnecessaryReturn(state: java!ReturnStatement) { to om: smm!ObservedMeasure ( measure <- noc, 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.' ) do { noc; } } --------------------------------------------- MeasureCompareObjectsWithEquals --- --------------------------------------------- --A measure instance if the class violates the rule MeasureCompareObjectsWithEquals. rule MeasureCompareObjectsWithEquals(expression: java!InfixExpression) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'CompareObjectsWithEquals', 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.' ) do { noc; } } --------------------------------------------- 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.' ) do { noc; } } --------------------------------------------- IntegerInstantiation --- --------------------------------------------- -- A Measure instance if the class violates the rule 'IntegerInstantiation'. 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.' ), measurement: smm!DirectMeasurement ( error <- 'In the Class ' + variable.name + ' an instantiation of Integer must' + ' be Integer.ValueOf().' ) do { noc; } } --------------------------------------------- LongVariable --- --------------------------------------------- -- A Measure instance if the variable violates the rule LongVariable. rule MeasureLongVariable(variable: java!VariableDeclarationFragment) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'LongVariable', 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 ' ) do { noc; } } --------------------------------------------- AvoidCallingFinalize --- --------------------------------------------- -- A Measure instance if the class violates the rule LongVariable. rule MeasureAvoidCallingFinalize(methode: java!MethodInvocation) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'AvoidCallingFinalize', 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 ) do { noc; } } --------------------------------------------- AvoidStringBufferField --- --------------------------------------------- -- A Measure instance if the class violates AvoidStringBufferField . rule MeasureAvoidStringBufferField(declaration: java!VariableDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'AvoidStringBufferField', 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 ) do { noc; } } --------------------- AvoidThrowingNullPointerException---------------------------------- -- A Measure instance if the class violates AvoidThrowingNullPointerException . rule MeasureAvoidThrowingNullPointerException(c: java!ClassInstanceCreation) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'AvoidThrowingNullPointerException', 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 ) do { noc; } } --------------------- EmptyTryBlock---------------------------------- --A measure instance if the class violates the rule EmptyTryBlock. rule MeasureEmptyTryBlock(t: java!TryStatement) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'EmptyTryBlock', shortDescription <- ': Avoid empty try blocks - what s the point?' ), measurement: smm!DirectMeasurement ( error <- 'EmptyTryBlock is detected in ' + t.originalCompilationUnit.name ) do { noc; } } ---------------------EmptyWhileStmt---------------------------------- --A measure instance if the class violates the rule EmptyWhileStmt. rule MeasureEmptyWhileStmt(w: java!TryStatement) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'EmptyWhileStmt', shortDescription <- ': Empty While Statement finds all instances where a' + ' while statement does nothing.' ), measurement: smm!DirectMeasurement ( error <- 'EmptyWhileStmt is detected in ' + w.originalCompilationUnit.name ) do { noc; } } ------------------------------------------- --- MeasureDontImportSun---------------------------------------------- -- A Measure instance if the class violate the rule DontImportSun 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) ) do { noc; } } ------------------------------------------- --- FinalizeShouldBeProtected---------------------------------------------- -- A Measure instance if the class violate the rule FinalizeShouldBeProtected 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 ) do { noc; } } -- A Measure instance if the class violates the rule AvoidNoPackageDeclaration. 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; } } -- A Measure instance if the class violates the rule UnconditionalIfStatement. 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; } } -- A Measure instance if the class violates the rule EmptyInitializer. rule MeasureEmptyInitializer(w: java!Initializer) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'EmptyInitializer', shortDescription <- ': EmptyInitializer finds ' ), measurement: smm!DirectMeasurement ( error <- 'do not declare an EmptyInitializer, EmptyInitializer is detected in ' + w.originalCompilationUnit.name + ' this block need to be deleted' ) do { noc; } } -- A Measure instance if the class violates the rule ExcessiveClassLength. rule MeasureExcessiveClassLength(w: java!MethodDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'ExcessiveClassLength', shortDescription <- ': class file lengths are usually indications that the class may be burdened with excessive responsibilities that could be provided by external classes or functions' ), measurement: smm!DirectMeasurement ( error <- w.originalCompilationUnit.name+ 'has a block with more than 1000 line of code per a method it may need a separation in the code' ) do { noc; } } -- A Measure instance if the class violates the rule CloneMethodMustBePublic. rule MeasureCloneMethodMustBePublic(w: java!MethodDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'CloneMethodMustBePublic', shortDescription <- 'CloneMethodMustBePublic' ), measurement: smm!DirectMeasurement ( error <- w.originalCompilationUnit.name+ 'the clone methode in here need to be public ' ) do { noc; } }