-- @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.avoidThreadGroup(), thisModule.useNotifyAllInsteadOfNotify(), thisModule.dontCallThreadRun(), -- Code Style rules -- thisModule.avoidPrefixingMethodParameters(), thisModule.extendsObject(), thisModule.fieldDeclarationsShouldBeAtStartOfClass(), thisModule.genericsNaming(), thisModule.longVariable(), thisModule.misLeadingVariableName(), thisModule.noPackageDeclaration(), thisModule.shortClassName(), thisModule.shortMethodName(), thisModule.shortVariableName(), thisModule.tooManyStaticImports(), thisModule.unnecessaryReturn(), -- Design rules -- thisModule.ExcessiveClassLength(), thisModule.IfBraces(), thisModule.excessiveParameterList(), thisModule.finalFieldCouldBeStatic(), thisModule.longInstantiation(), thisModule.returnFromFinallyBlock(), thisModule.shortInstantiation(), thisModule.signatureDeclareThrowsException(), thisModule.tooManyFields(), thisModule.tooManyMethods(), thisModule.SimplifyBooleanAssertion(), thisModule.abstractClassWithoutAnyMethod(), thisModule.excessiveImports(), -- Performance rules -- thisModule.addEmptyString(), thisModule.avoidPrintStackTrace(), thisModule.avoidRethrowingException(), thisModule.avoidUsingShortType(), thisModule.emptyStatementBlock(), thisModule.insufficientStringBufferDeclaration(), thisModule.integerInstantiation(), thisModule.useIndexOfChar(), thisModule.uselessStringValueOf(), thisModule.startsWith(), thisModule.tooFewBranchesForASwitchStatement(), -- Documentation rules -- thisModule.commentContent(), -- Error prone rules -- thisModule.avoidCallingFinalize(), thisModule.AvoidCatchingNPE(), thisModule.avoidCatchingThrowable(), thisModule.AvoidEnumAsIdentifier(), thisModule.CloneMethodMustBePublic(), thisModule.doNotCallGarbageCollectionExplicitly(), thisModule.doNotCallSystemExit(), thisModule.doNotExtendJavaLangError(), thisModule.doNotExtendJavaLangThrowable(), thisModule.dontImportSun(), thisModule.emptyCatchBlock(), thisModule.EmptyInitializer(), thisModule.emptySwitchStatement(), thisModule.emptySynchronizedBlock(), thisModule.emptyTryBlock(), thisModule.importFromSamePackage(), thisModule.missingBreakInSwitch(), thisModule.suspiciousEqualsMethodName(), thisModule.testClassWithoutTest(), thisModule.UnconditionalIfStatement(), thisModule.UseProperClassLoader(), -- Best practices rules thisModule.forLoopVariableCount(), thisModule.switchDensity(), thisModule.useAssertSameInsteadOfAssertTrue(), thisModule.useAssertTrueInsteadOfAssertEquals() -- Bugged rules: -- -- thisModule.avoidThrowingNullPointerException(), -- thisModule.UseArrayListInsteadOfVector(), -- thisModule.commentRequired(), -- thisModule.compareObjectsWithEquals(), -- thisModule.emptyWhileStmt(), -- thisModule.emptyFinallyBlock(), -- thisModule.emptyfinalizeMethod(), -- thisModule.doNotThrowExceptionInFinally(), -- thisModule.finalizeShouldBeProtected(), -- thisModule.avoidDollarSigns(), -- thisModule.returnEmptyArrayRatherThanNull(), -- thisModule.replaceVectorToList() -- thisModule.unusedPrivateMethod () -- thisModule.avoidStringBufferField() -- thisModule.avoidThrowingNewInstanceOfSameException(), -- thisModule.stringToString(), -- thisModule.methodWithSameNameAsEnclosingClass(), -- thisModule.dontUseFloatTypeForLoopIndices(), -- thisModule.methodWithSameNameAsEnclosingClass(), }; -- 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; } } -- A Measure instance if the variable violates the rule 'ShortVariableName'. rule MesureShortVariableName(variable : java!VariableDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'ShortVariableName', shortDescription <- 'Short Variable names with fewer than e.g. three characters are not recommended.' ), measurement: smm!DirectMeasurement ( error <- 'The Variable ' + variable.name + ' is too short.' ) do { noc; } } -- A Measure instance if the method violates the rule 'StringToString'. rule MeasureStringToString(method : java!MethodInvocation) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'StringToString', shortDescription <- 'Avoid calling toString() on objects already known to be string instances; this is unnecessary.' ), measurement: smm!DirectMeasurement ( error <- 'The Object ' + method.expression.variable.name + ' is already a String in ' + method.originalCompilationUnit.name ) do { noc; } } -- creates a new Measure when Thread.run() is used instead of Thread.start() rule MeasureDontCallThreadRun(method : java!MethodDeclaration) { 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!VariableDeclarationStatement) { 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; } } -- Creates a measure instance when a bad word is found in a comment 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; } } -- Creates a measure instance when a for loop uses a float as loop indice rule MeasureDontUseFloatTypeForLoopIndices(){ to om: smm!ObservedMeasure ( measure <- dontUseFloatTypeForLoopIndices, measurements <- measurement ), dontUseFloatTypeForLoopIndices: smm!DimensionalMeasure ( name <- 'DontUseFloatTypeForLoopIndices()', shortDescription <- 'Don’t use floating point for loop indices.' ), measurement: smm!DirectMeasurement ( error <- 'Use integer instead of floats as loop indice' ) do { dontUseFloatTypeForLoopIndices; } } --- 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; } } --------------------------------------------- UseAssertTrueInsteadOfAssertEquals --------------------------------------------- -- A Measure instance if the class violates the rule UseAssertTrueInsteadOfAssertEquals. rule MesureUseAssertTrueInsteadOfAssertEquals(class : java!MethodInvocation) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'UseAssertTrueInsteadOfAssertEquals', shortDescription <- 'Use AssertTrue instead of AssertEquals' ), measurement: smm!DirectMeasurement ( error <- class.originalCompilationUnit.name + ' Use AssertTrue instead of AssertEquals ' ) 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; } } -----------------------EmptySwitchStatement--------------------------------------------- -- A Measure instance if the class violates the rule 'EmptySwitchStatement' rule MeasureEmptySwitchStatement(switchStatement: java!SwitchStatement) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'Empty Switch Statement ', shortDescription <- 'Empty Switch statements serve no purpose and should be removed.' ), measurement: smm!DirectMeasurement ( error <- 'EmptyswitchStatement is detected in ' + switchStatement.originalCompilationUnit.name ) do { noc; } } --------------------------------EmptySynchronizedBlock--------------------------------------------- -- A Measure instance if the class violates the rule 'EmptySynchronizedBlock' rule MeasureEmptySynchronizedBlock(synchronizedBlock: java!SynchronizedStatement) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'Empty Synchronized Block ', shortDescription <- 'Empty Synchronized Block serve no purpose and should be removed.' ), measurement: smm!DirectMeasurement ( error <- 'EmptySynchronizedBlock is detected in ' + synchronizedBlock.originalCompilationUnit.name ) do { noc; } } --------------------- EmptyFinallyBlock---------------------------------- --A measure instance if the class violates the rule EmptyFinallyBlock. rule MeasureEmptyFinallyBlock(finallyBlock : java!TryStatement) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'EmptyFinallyBlock', shortDescription <- ': Avoid empty Finally blocks - what s the point?' ), measurement: smm!DirectMeasurement ( error <- 'EmptyFinallyBlock is detected in ' + finallyBlock.originalCompilationUnit.name ) do { noc; } } --------------------- EmptyFinalizer---------------------------------- --A measure instance if the class violates the rule EmptyFinalizer. rule MeasureEmptyFinalizer(finalizeMethod : java!MethodDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'EmptyFinalizer', shortDescription <- ': Avoid empty Finalizer - what s the point?' ), measurement: smm!DirectMeasurement ( error <- 'EmptyFinalizer is detected in ' + finalizeMethod.originalCompilationUnit.name ) do { noc; } } -------------------------------------------UseAssertSameInsteadOfAssertTrue---------------------------------------------- -- A Measure instance if the class violate the rule AssertSameInsteadOfAssertTrue rule MesureUseAssertSameInsteadOfAssertTrue(tab :java!Package) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'Use AssertSame Instead Of AssertTrue', shortDescription <- 'Use AssertSame Instead Of AssertTrue' ), measurement: smm!DirectMeasurement ( error<- 'Use AssertSame Instead Of AssertTrue.' ) 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 <- 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' ), 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' ), measurement: smm!DirectMeasurement ( error <- ' class '+w.originalCompilationUnit.name +' hase an empty Initializer! do not declare an EmptyInitializer, EmptyInitializer! 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 <- ' class '+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 <- ': Clone Method Must Be Public' ), measurement: smm!DirectMeasurement ( error <- ' class '+w.originalCompilationUnit.name+ ' has a clone methode witch need to be public ' ) do { noc; } } -- A Measure instance if the class violates the rule AvoidEnumAsIdentifier. rule MeasureAvoidEnumAsIdentifier(w: java!VariableDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'AvoidEnumAsIdentifier', shortDescription <- ': Avoid Enum As Identifier' ), measurement: smm!DirectMeasurement ( error <- ' class '+w.originalCompilationUnit.name+ ' has a variable named to enum witch is a reserved name' ) do { noc; } } -- A Measure instance if the class violates the rule AvoidCatchingNPE. rule MeasureAvoidCatchingNPE(w: java!CatchClause) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'AvoidCatchingNPE', shortDescription <- ': Avoid Catching NullPointerExceptions' ), measurement: smm!DirectMeasurement ( error <- ' class '+w.originalCompilationUnit.name+ ' has a Code that should never throw NullPointerExceptions under normal circumstances. A catch block may hide the original error, causing other, more subtle problems later on.' ) do { noc; } } -- A Measure instance if the class violates the rule UseProperClassLoader. rule MeasureUseProperClassLoader(w: java!MethodInvocation) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'UseProperClassLoader', shortDescription <- ': Use ProperClassLoader' ), measurement: smm!DirectMeasurement ( error <- ' class'+ w.originalCompilationUnit.name+ ' Use a statement with getClassLoader(), use Thread.currentThread().getContextClassLoader() instead ' ) do { noc; } } -------------------------------------------GenericsNaming---------------------------------------------- -- A Measure instance if the class violate the rule GenericsNaming rule MeasureGenericsNaming(type :java!TypeParameter) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'GenericsNaming', shortDescription <- 'Names for references to generic values should be limited to a single uppercase letter.' ), measurement: smm!DirectMeasurement ( error<- 'The generic type ' + type.name + ' should be limited to a single uppercase letter.' ) do { noc; } } -------------------------------------------MisLeadingVariableName---------------------------------------------- -- A Measure instance if the class violate the rule MisLeadingVariableName rule MeasureMisLeadingVariableName(variable :java!VariableDeclarationFragment) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'MisLeadingVariableName', shortDescription <- 'Detects when a non-field has a name starting with �m_�. This usually denotes a field and could be confusing.' ), measurement: smm!DirectMeasurement ( error<- 'Variable ' + variable.name + ' should not start with �m_� as it is not a field.' ) do { noc; } } -------------------------------------------AvoidCatchingThrowable---------------------------------------------- -- A Measure instance if the class violate the rule MisLeadingVariableName rule MeasureAvoidCatchingThrowable(catch :java!CatchClause) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'AvoidCatchingThrowable', shortDescription <- 'Catching Throwable errors is not recommended since its scope is very broad. It includes runtime issues such as OutOfMemoryError that should be exposed and managed separately.' ), measurement: smm!DirectMeasurement ( error<- 'Throwable ' + catch.exception.name + ' should not be catched.' ) do { noc; } } -------------------------------------------DoNotCallGarbageCollectionExplicitly---------------------------------------------- -- A Measure instance if the class violate the rule DoNotCallGarbageCollectionExplicitly rule MeasureDoNotCallGarbageCollectionExplicitly(method : java!MethodInvocation) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'DoNotCallGarbageCollectionExplicitly', shortDescription <- 'Calls to System.gc(), Runtime.getRuntime().gc(), and System.runFinalization() are not advised.' ), measurement: smm!DirectMeasurement ( error<- 'Garbage collector is called explicitly in ' + method.originalCompilationUnit.name ) do { noc; } } -------------------------------------------EmptyCatchBlock---------------------------------------------- -- A Measure instance if the class violate the rule EmptyCatchBlock rule MeasureEmptyCatchBlock(catch : java!CatchClause) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'EmptyCatchBlock', shortDescription <- 'Empty Catch Block finds instances where an exception is caught, but nothing is done. In most circumstances, this swallows an exception which should either be acted on or reported.' ), measurement: smm!DirectMeasurement ( error<- 'Empty catch block in ' + catch.originalCompilationUnit.name ) do { noc; } } -------------------------------------------ImportFromSamePackage---------------------------------------------- -- A Measure instance if the class violate the rule ImportFromSamePackage rule MeasureImportFromSamePackage(import : java!ImportDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'ImportFromSamePackage', shortDescription <- 'There is no need to import a type that lives in the same package.' ), measurement: smm!DirectMeasurement ( error<- 'No need to import ' + import.importedElement.name + ' in ' + import.originalCompilationUnit.name ) do { noc; } } -------------------------------------------MethodWithSameNameAsEnclosingClass---------------------------------------------- -- A Measure instance if the class violate the rule MethodWithSameNameAsEnclosingClass rule MeasureMethodWithSameNameAsEnclosingClass(method : java!MethodDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'MethodWithSameNameAsEnclosingClass', shortDescription <- 'Non-constructor methods should not have the same name as the enclosing class.' ), measurement: smm!DirectMeasurement ( error<- 'Method ' + method.name + ' has the same name as ' + method.originalCompilationUnit.name + ' and is not a contructor.' ) do { noc; } } --------------------------------------------- ExcessiveImports --------------------------------------------- -- creates a new Measure when a class has more than 4 imports rule MeasureExcessiveImports(i : java!CompilationUnit) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'ExcessiveImports', shortDescription <- 'A high number of imports can indicate a high degree of coupling within an object. This rule counts the number of unique imports and reports a violation if the count is above the user-specified threshold.' ), measurement: smm!DirectMeasurement ( error<-'The class '+ i.name + ' has an excessive imports.', value<- i.imports.size() ) do { noc; } } --------------------------------------------- IfStmtsMustUseBraces --------------------------------------------- -- creates a new Measure when a class that contains an if statement without braces. rule MeasureIfStmtsMustUseBraces(i : java!IfStatement) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'If then Statement must use braces', shortDescription <- 'Deprecated Avoid using if statements without using braces to surround the code block. If the code formatting...' ), measurement: smm!DirectMeasurement ( error <- 'The class ' + i.originalCompilationUnit.name + ' has an if statement without braces. ' ) do { noc; } } --------------------------------------------- SimplifyBooleanAssertion --------------------------------------------- -- creates a new Measure when a class contains a negation in an assertTrue or assertFalse. rule MeasureSimplifyBooleanAssertion(i : java!PrefixExpression) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'SimplifyBooleanAssertion', shortDescription <- 'Avoid negation in an assertTrue or assertFalse test.' ), measurement: smm!DirectMeasurement ( error<-'The method test ' + i.eContainer().eContainer().eContainer().eContainer().name + ' contains a negation in an assertTrue or assertFalse.' ) do { noc; } } --------------------------------------------- AbstractClassWithoutAnyMethod --------------------------------------------- -- creates a new Measure when an abstract class does not provides any methods. rule MeasureAbstractClassWithoutAnyMethod(i : java!ClassDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'AbstractClassWithoutAnyMethod', shortDescription <- 'If an abstract class does not provides any methods, it may be acting as a simple data containerth...' ), measurement: smm!DirectMeasurement ( error<-'The class anstract' + i.name + ' has not method.' ) do { noc; } } ------------------------------------------- start with ------------------------------------------------------------------------------------ rule MeasureStartWith(w: java!MethodInvocation) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'startWith', shortDescription <- ': methode startWith found in' ), measurement: smm!DirectMeasurement ( error <- ' class'+ w.originalCompilationUnit.name+ 'has an instruction that use startWith, use chartAt(0) instand ' ) do { noc; } } ------------------------------------------- insufficientStringBufferDeclaration ------------------------------------------------------------------------------------ rule MeasureInsufficientStringBufferDeclaration(w: java!CompilationUnit) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'insufficientStringBufferDeclaration', shortDescription <- ' : insufficientStringBufferDeclaration.' ), measurement: smm!DirectMeasurement ( error <- ' class'+ w.name+ 'has insufficientStringBufferDeclaration' ) do { noc; } } ------------------------------------------- testClassWithoutTest ------------------------------------------------------------------------------------ rule MeasureTestClassWithoutTest(w: java!CompilationUnit) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'testClassWithoutTest', shortDescription <- ' : testClassWithoutTest.' ), measurement: smm!DirectMeasurement ( error <- ' class'+ w.name+ 'has testClassWithoutTest' ) do { noc; } } ------------------------------------------- AddEmptyString ------------------------------------------------------------------------------------ rule MesureAddEmptyString(w: java!CompilationUnit) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'AddEmptyString', shortDescription <- ' : AddEmptyString.' ), measurement: smm!DirectMeasurement ( error <- ' class'+ w.name+ 'has AddEmptyString' ) do { noc; } } ------------------------------------------- DoNotCallSystemExit---------------------------------------------- -- A Measure instance if the class violates the rule DoNotCallSystemExit. rule MeasureDoNotCallSystemExit(invocation : java!MethodInvocation) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'DoNotCallSystemExit', shortDescription <- 'Applications should not call System.exit(), since only the web container or the application server should stop the JVM' ), measurement: smm!DirectMeasurement ( error<- 'Do not call ' + invocation.method.getMethodClassName() + '.' + invocation.method.name + ' in the file ' + invocation.originalCompilationUnit.name ) do { noc; } } ------------------------------------------- ForLoopVariableCount---------------------------------------------- -- A Measure instance if the class violates the rule ForLoopVariableCount. rule MeasureForLoopVariableCount(forStatement: java!ForStatement) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'ForLoopVariableCount', shortDescription <- 'Having a lot of control variables in a "for" loop makes it harder to see what range of values the loop iterates over.' ), measurement: smm!DirectMeasurement ( error<- 'A "for" loop use more than one local variable in the file ' + forStatement.originalCompilationUnit.name ) do { noc; } } ------------------------------------------- AvoidPrefixingMethodParameters---------------------------------------------- -- A Measure instance if the class violates the rule AvoidPrefixingMethodParameters. rule MeasureAvoidPrefixingMethodParameters(method: java!MethodDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'AvoidPrefixingMethodParameters', shortDescription <- 'Prefixing parameters by ‘in’ or ‘out’ pollutes the name of the parameters and reduces code readability.' ), measurement: smm!DirectMeasurement ( error<- 'Bad parameters : ' + method.getIncorrectParameters() + ', for the method ' + method.name + ' defined in the file ' + method.originalCompilationUnit.name ) do { noc; } } ------------------------------------------- FieldDeclarationsShouldBeAtStartOfClass---------------------------------------------- -- A Measure instance if the class violates the rule FieldDeclarationsShouldBeAtStartOfClass. rule MeasureFieldDeclarationsShouldBeAtStartOfClass(class: java!ClassDeclaration) { to om: smm!ObservedMeasure ( measure <- noc, measurements <- measurement ), noc: smm!DimensionalMeasure ( name <- 'FieldDeclarationsShouldBeAtStartOfClass', shortDescription <- 'Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes.' ), measurement: smm!DirectMeasurement ( error<- 'Some of the fields of the class ' + class.name + ' are not declared at the top' ) do { noc; } }