library bestPractices; --------------------------------------------- AvoidPrintStackTrace --------------------------------------------- --Goes through all the methods to check if the following rule is followed: --Avoid printStackTrace() helper def: avoidPrintStackTrace() : Set(smm!Measure) = java!MethodInvocation.allInstances() -> iterate(i; res : Set(smm!Measure) = Set{} | -- Add a new measurement if the argument of String.indexOf() is not of type char when checking for the index of a single character if thisModule.isAvoidPrintStackTrace(i) then res->union(Set{thisModule.MeasureAvoidPrintStackTrace(i)}) else res endif ); --Detect a wrong usage of the method printStackTrace() --return true if the method is called printStackTrace helper def:isAvoidPrintStackTrace(s:java!MethodInvocation): Boolean = if s.method.name = 'printStackTrace' then true else false endif; --------------------------------------------- AvoidFieldNameMatchingMethodName --------------------------------------------- -- Rule for metrics AvoidFieldNameMatchingMethodName : return the set of class Measures that violates the rule. helper def: avoidFieldNameMatchingMethodName() : Set(smm!Measure) = -- Browse through all class java!ClassDeclaration.allInstances()->iterate(i; res : Set(smm!Measure) = Set{} | -- Foreach FieldDeclaration, check all methods i.bodyDeclarations->iterate(field; resIter : Set(smm!Measure) = Set{} | if field.oclIsTypeOf(java!FieldDeclaration) then i.bodyDeclarations -- Check if the name method and the name field is the same ->select(method | method.oclIsTypeOf(java!MethodDeclaration) and method.name = field.fragments.first().name) ->collect(method | thisModule.MesureAvoidFieldNameMatchingMethodName(i, method)) else res endif ) ); --------------------------------------------- EmptyStatementBlock --------------------------------------------- --Detects the use of empty statements blocks. These blocks serve no purpose and should be removed helper def: emptyStatementBlock() : Set(smm!Measure) = java!Block.allInstances() ->select(block | block.statements.isEmpty()) ->collect(block | thisModule.MeasureEmptyStatementBlock(block)); --------------------------------------------- SwitchDensity --------------------------------------------- -- Rule for metrics SwitchDensity : helper def: switchDensity() : Set (smm!Measure) = -- Browse through all Switch Statements java!SwitchStatement.allInstances()->iterate(switchCase; res : Set(smm!Measure) = Set{} | switchCase.statements ->select(switchStatement | switchStatement.oclIsTypeOf(java!Block)) ->select(switchStatement | switchStatement.statements <> OclUndefined) ->select(switchStatement | switchStatement.statements.size() -1 >= 10) ->collect(switchStatement | thisModule.MeasureSwitchDensity(switchCase)) ); --------------------------------------------- useAssertTrueInsteadOfAssertEquals --------------------------------------------- helper def: useAssertTrueInsteadOfAssertEquals() : Set(smm!Measure) = -- Browse through all methods use java!MethodInvocation.allInstances() --Check if the method use is assertEqual and a Boolean is used ->select(assert | assert.method.name = 'assertEquals') ->select(assert | thisModule.isWrongUseAssertTrueInsteadOfAssertEquals(assert)) ->collect(assert | thisModule.MesureUseAssertTrueInsteadOfAssertEquals(assert)); helper def: isWrongUseAssertTrueInsteadOfAssertEquals(m:java!MethodInvocation) : Boolean = --Shorten the path m.arguments.last() to lastArgument and check if it's a boolean let lastArgument : java!Expression = m.arguments.last() in lastArgument.isBoolean(); --Checks if it's a BooleanLiteral helper context java!BooleanLiteral def: isBoolean() : Boolean = true; --Checks if the type of a Expression is Boolean helper context java!Expression def: isBoolean() : Boolean = self.variable.variablesContainer.isBoolean(); --Checks if the type of a VariableDeclarationStatement is Boolean helper context java!VariableDeclarationStatement def: isBoolean() : Boolean = self.type.type.name= 'boolean'; --Use in case of Boolean.TRUE or Boolean.FALSE helper context java!FieldDeclaration def: isBoolean() : Boolean = self.abstractTypeDeclaration.name = 'Boolean'; --------------------------------------------- AvoidStringBufferField --------------------------------------------- -- Rule for metrics AvoidStringBufferField helper def: avoidStringBufferField() : Set(smm!Measure) = java!FieldDeclaration.allInstances() ->select(dec | dec.type.type.name = 'StringBuffer' or dec.type.type.name = 'StringBuilder') ->collect(dec | thisModule.MeasureAvoidStringBufferField(dec)); ---------------------------------------------UseAssertSameInsteadOfAssertTrue--------------------------------------------- helper def: useAssertSameInsteadOfAssertTrue() : Set(smm!Measure) = -- Browse through all methods use java!MethodInvocation.allInstances() --Check if the method use is assertTrue and check if == is used ->select(assert | assert.method.name = 'assertTrue') ->select(assert | thisModule.isWrongUseAssertSameInsteadOfAssertTrue(assert)) ->collect(assert | thisModule.MesureUseAssertSameInsteadOfAssertTrue(assert)); helper def: isWrongUseAssertSameInsteadOfAssertTrue(m:java!MethodInvocation) : Boolean = --Browse through all arguments of the method assertTrue and see if == is used (m.arguments->select(t|t.oclIsTypeOf(java!InfixExpression))->select(t|t.operator.toString() = '==')->collect(t|t).notEmpty());