Commit a872a2f2 authored by Marion HUNAULT's avatar Marion HUNAULT Committed by Gerson SUNYE
Browse files

Correction #904 String toString

parent 2d3a3528
...@@ -91,6 +91,7 @@ helper def: allMeasures(project : java!Model): Set(smm!Measure) = ...@@ -91,6 +91,7 @@ helper def: allMeasures(project : java!Model): Set(smm!Measure) =
thisModule.integerInstantiation(), thisModule.integerInstantiation(),
-- #FIXME: -- #FIXME:
-- thisModule.startsWith(), -- thisModule.startsWith(),
thisModule.stringToString(),
thisModule.tooFewBranchesForASwitchStatement(), thisModule.tooFewBranchesForASwitchStatement(),
-- #FIXME: thisModule.useArraysAsList(), -- #FIXME: thisModule.useArraysAsList(),
thisModule.useIndexOfChar(), thisModule.useIndexOfChar(),
...@@ -152,7 +153,6 @@ helper def: allMeasures(project : java!Model): Set(smm!Measure) = ...@@ -152,7 +153,6 @@ helper def: allMeasures(project : java!Model): Set(smm!Measure) =
-- thisModule.replaceVectorToList() -- thisModule.replaceVectorToList()
-- thisModule.unusedPrivateMethod () -- thisModule.unusedPrivateMethod ()
-- thisModule.avoidThrowingNewInstanceOfSameException(), -- thisModule.avoidThrowingNewInstanceOfSameException(),
-- thisModule.stringToString(),
-- thisModule.methodWithSameNameAsEnclosingClass(), -- thisModule.methodWithSameNameAsEnclosingClass(),
-- thisModule.dontUseFloatTypeForLoopIndices(), -- thisModule.dontUseFloatTypeForLoopIndices(),
-- thisModule.methodWithSameNameAsEnclosingClass(), -- thisModule.methodWithSameNameAsEnclosingClass(),
...@@ -1895,6 +1895,25 @@ rule MesureShortVariableName(variable : java!VariableDeclaration) { ...@@ -1895,6 +1895,25 @@ rule MesureShortVariableName(variable : java!VariableDeclaration) {
} }
} }
--- Creates a new Measure when the method toString() is unnecessarily invoked.
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;
}
}
--- A Measure instance if the class violates the rule 'TooManyFields'. --- A Measure instance if the class violates the rule 'TooManyFields'.
-- #FIXME: Typo -- #FIXME: Typo
rule MesureTooManyFields(class : java!ClassDeclaration) { rule MesureTooManyFields(class : java!ClassDeclaration) {
...@@ -2083,8 +2102,4 @@ helper context java!FieldDeclaration def: getBodyDeclarationName() : String = ...@@ -2083,8 +2102,4 @@ helper context java!FieldDeclaration def: getBodyDeclarationName() : String =
-- ATTENTION !!! -- ATTENTION !!!
-- Before adding a new rule in the end of the file, remember that rules respect an alphabetical order. -- Before adding a new rule in the end of the file, remember that rules respect an alphabetical order.
\ No newline at end of file
library performance; library performance;
--------------------------------------------- UselessStringValueOf--------------------------------------------- --- AddEmptyString
helper def: addEmptyString() : Set(smm!Measure) =
--Goes through all the methods to check if the following rule is followed: java!InfixExpression.allInstances()
--No need to call String.valueOf to append to a string; just use the valueOf() argument directly. ->select(expression | expression.operator.name = '+')
helper def: uselessStringValueOf() : Set(smm!Measure) = ->select(expression | (expression.leftOperand.oclIsTypeOf(java!StringLiteral) and expression.rightOperand.oclIsTypeOf(java!NumberLiteral)) or (expression.leftOperand.oclIsTypeOf(java!NumberLiteral) and expression.rightOperand.oclIsTypeOf(java!StringLiteral)))
java!MethodInvocation.allInstances() ->collect(expression | thisModule.MesureAddEmptyString(expression.originalCompilationUnit))
-> select (m | m.method.name='valueOf' ) ;
-> select (m | m.refImmediateComposite().oclIsTypeOf(java!InfixExpression))
-> collect (m | thisModule.MeasureUselessStringValueOf(m)); --- AvoidInstantiatingObjectInLoops
helper def: avoidInstantiatingObjectsInLoops(): Set(smm!Measure) =
------------------------------------ TooFewBranchesForASwitchStatement-------------------------------------- java!Statement.allInstances()
->select(s | s.oclIsTypeOf(java!ForStatement) or s.oclIsTypeOf(java!DoStatement) or s.oclIsTypeOf(java!WhileStatement))
-- Returns a set of measures for each switch statement that violates the rule : number of switch cases < 3 ->select(s | s.body.statements
-- To test, use input model : tooFewBranchesForASwitchStatement.xmi ->select(s2 | s2.oclIsTypeOf(java!VariableDeclarationStatement))
helper def: tooFewBranchesForASwitchStatement(): Set(smm!Measure) = ->select(s2 | s2.fragments->exists(f | f.oclIsTypeOf(java!VariableDeclarationFragment)))
-- If the number of switch cases for the current switch statement is < 3 then add a new measure to the set ->exists(s2 | s2.fragments->exists(f | f.initializer.oclIsTypeOf(java!ClassInstanceCreation)))
java!SwitchStatement.allInstances() )
-> select (switchStatement | thisModule.nbBranchesOfASwitchStatement(switchStatement) < 3) ->collect(s | thisModule.MeasureAvoidInstantiatingObjectInLoops(s))
-> collect (switchStatement | thisModule.MeasureTooFewBranchesForASwitchStatement(switchStatement)) ;
;
--- AvoidRethrowingException
--------------------------------------------- UseIndexOfChar--------------------------------------------- -- Rule for metrics AvoidRethrowingException :
helper def: avoidRethrowingException() : Set (smm!Measure) =
--Goes through all the MethodInvocation to check if the following rule is followed: -- Browse through all try statements
--Use String.indexOf(char) when checking for the index of a single character; it executes faster. java!TryStatement.allInstances() ->iterate(tryStatement; res : Set(smm!Measure) = Set{} |
helper def: useIndexOfChar() : Set(smm!Measure) = tryStatement.catchClauses
java!MethodInvocation.allInstances() ->select(catchClause | catchClause.body <> OclUndefined and catchClause.body.statements.size() = 1)
-> select (m | m.method.name='indexOf') ->collect(catchClause | catchClause.body.statements)
-> select (m | m.arguments.size() = 1) ->iterate(catchStatement; res1 : Set(smm!Measure) = Set{} |
-> select (m | not m.arguments.first().oclIsTypeOf(java!CharacterLiteral)) catchStatement
-> collect (m | thisModule.MeasureUseIndexOfChar(m)) ->select(catchState | catchState.oclIsTypeOf(java!ThrowStatement))
; ->collect(catchState | thisModule.MeasureAvoidRethrowingException(catchState))
)
--------------------------------------------- avoidThrowingNewInstanceOfSameException --------------------------------------------- )
-- Returns a set of Measures for each catch block throws a new instance of the caught exception ;
helper def: avoidThrowingNewInstanceOfSameException() : Set(smm!Measure) =
java!CatchClause.allInstances() ->iterate(catch; catchRes : Set(smm!Measure) = Set{} | --- AvoidThrowingNewInstanceOfSameException
if catch.body <> OclUndefined -- Returns a set of Measures for each catch block throws a new instance of the caught exception
then catch.body.statements helper def: avoidThrowingNewInstanceOfSameException() : Set(smm!Measure) =
-> select(catchStatement | catchStatement.oclIsTypeOf(java!ThrowStatement) java!CatchClause.allInstances() ->iterate(catch; catchRes : Set(smm!Measure) = Set{} |
and catchStatement.expression.oclIsTypeOf(java!ClassInstanceCreation)) if catch.body <> OclUndefined
-> select(catchStatement | catchStatement.expression.type.type.name = catch.exception.type.type.name) then catch.body.statements
-> collect(catchStatement | catchStatement.expression.arguments) -> select(catchStatement | catchStatement.oclIsTypeOf(java!ThrowStatement)
-> iterate(arguments; argumentsRes : Set(smm!Measure) = Set{} | and catchStatement.expression.oclIsTypeOf(java!ClassInstanceCreation))
arguments -> select(catchStatement | catchStatement.expression.type.type.name = catch.exception.type.type.name)
-> select(argument | argument.oclIsTypeOf(java!SingleVariableAccess)) -> collect(catchStatement | catchStatement.expression.arguments)
-> select(argument | argument.variable.name = catch.exception.name) -> iterate(arguments; argumentsRes : Set(smm!Measure) = Set{} |
-> collect(argument | thisModule.MeasureAvoidThrowingNewInstanceOfSameException(catch)) arguments
) -> select(argument | argument.oclIsTypeOf(java!SingleVariableAccess))
else catchRes -> select(argument | argument.variable.name = catch.exception.name)
endif -> collect(argument | thisModule.MeasureAvoidThrowingNewInstanceOfSameException(catch))
); )
else catchRes
endif
--------------------------------------------- AvoidUsingShortType--------------------------------------------- )
;
--Detects the use of the primitive type 'short' for rule AvoidUsingShortType. Prefer the use of 'int' instead of 'short'.
helper def: avoidUsingShortType() : Set(smm!Measure) = --- AvoidUsingShortType
java!VariableDeclarationStatement.allInstances() -- Detects the use of the primitive type 'short' for rule AvoidUsingShortType. Prefer the use of 'int' instead of 'short'.
->select(variable | variable.type.type.name = 'short') helper def: avoidUsingShortType() : Set(smm!Measure) =
->collect(variable | thisModule.MeasureAvoidUsingShortType(variable)); java!VariableDeclarationStatement.allInstances()
->select(variable | variable.type.type.name = 'short')
--------------------------------------------- ShortInstantiation --------------------------------------------- ->collect(variable | thisModule.MeasureAvoidUsingShortType(variable))
;
-- Rule for metrics ShortInstantiation : return the set of class Measures that violates the rule.
helper def: shortInstantiation() : Set(smm!Measure) = --- InefficientEmptyStringCheck
-- Take all ClassInstanceCreation with allInstances() helper def: inefficientEmptyStringCheck() : Set(smm!Measure) =
java!ClassInstanceCreation.allInstances() java!MethodInvocation.allInstances()
-- Select all class who declare a Short type ->select(i | i.method.name = 'isEmpty')
->select(it| it.method.oclIsTypeOf(java!ConstructorDeclaration) and it.method.name = 'Short') ->select(i | i.expression.oclIsTypeOf(java!MethodInvocation))
-- collect every results and send an error message ->select(i | thisModule.expressionMethodIs(i.expression,'trim'))
->collect(it2|thisModule.MeasureShortInstantiation(it2.originalCompilationUnit)) ->collect(i | thisModule.MeasureInefficientEmptyStringCheck(i));
;
helper def: inefficientEmptyStringCheck2() : Set(smm!Measure) =
--------------------------------------------- LongInstantiation --------------------------------------------- java!InfixExpression.allInstances()
->select(i | i.rightOperand.oclIsTypeOf(java!NumberLiteral))
-- Rule for metricsLongInstantiation : return the set of class Measures that violates the rule. ->select(i | i.rightOperand.tokenValue = '0')
helper def: longInstantiation() : Set(smm!Measure) = ->select(i | i.leftOperand.oclIsTypeOf(java!MethodInvocation))
-- Take all ClassInstanceCreation with allInstances() ->select(i | i.leftOperand.method.name = 'length')
java!ClassInstanceCreation.allInstances() ->select(i | i.leftOperand.expression.oclIsTypeOf(java!MethodInvocation))
-- Select all class who declare a Long type ->select(i | i.leftOperand.expression.method.name = 'trim')
->select(it| it.method.oclIsTypeOf(java!ConstructorDeclaration) and it.method.name = 'Long') ->collect(i | thisModule.MeasureInefficientEmptyStringCheck(i));
-- collect every results and send an error message
->collect(it2|thisModule.MeasureLongInstantiation(it2.originalCompilationUnit)) helper def: expressionMethodIs(expr: java!Expression,str: String) : Boolean =
; expr.method.name = str;
--------------------------------------------- AvoidRethrowingException --------------------------------------------- --- InsufficientStringBufferDeclaration
-- Rule for metrics AvoidRethrowingException : helper def: insufficientStringBufferDeclaration() : Set(smm!Measure) =
helper def: avoidRethrowingException() : Set (smm!Measure) = java!MethodInvocation.allInstances()
-- Browse through all try statements ->select(it| it.method.name = 'append')
java!TryStatement.allInstances() ->iterate(tryStatement; res : Set(smm!Measure) = Set{} | ->select(it1| it1.method.abstractTypeDeclaration.name = 'StringBuffer' or it1.method.abstractTypeDeclaration.name = 'StringBuilder')
tryStatement.catchClauses ->select(it2|thisModule.unsuffisentInisialization(it2.expression, it2.arguments.first()))
->select(catchClause | catchClause.body <> OclUndefined and catchClause.body.statements.size() = 1) ->collect(it2|thisModule.MeasureInsufficientStringBufferDeclaration(it2.originalCompilationUnit))
->collect(catchClause | catchClause.body.statements) ;
->iterate(catchStatement; res1 : Set(smm!Measure) = Set{} |
catchStatement -- -2 to ignone " at the begin and at end
->select(catchState | catchState.oclIsTypeOf(java!ThrowStatement)) helper def:unsuffisentInisialization(variable:java!SingleVariableAccess, str:java!StringLiteral): Boolean =
->collect(catchState | thisModule.MeasureAvoidRethrowingException(catchState)) str.escapedValue.size()-2 > thisModule.FixedSize(variable.variable.initializer);
)
); helper def:FixedSize(variable:java!ClassInstanceCreation): Integer =
--------------------------------------------- IntegerInstantiation --------------------------------------------- if variable.arguments.size() = 0 then
16
-- Rule for metricsIntegerInstantiation : returns the set of class Measures that violates the rule. else
helper def: integerInstantiation() : Set(smm!Measure) = if variable.arguments.first().oclIsTypeOf(java!NumberLiteral) then
-- Take all ClassInstanceCreation with allInstances() thisModule.sizeOf(variable.arguments.first())
java!ClassInstanceCreation.allInstances() else
-- Select all classes that declare an Integer type thisModule.sizeOfLitteral(variable.arguments.first())
->select(it|it.method.oclIsTypeOf(java!ConstructorDeclaration) and it.method.name = 'Integer') endif
-- collect every result and sends an error message endif;
->collect(it2|thisModule.MeasureIntegerInstantiation(it2.originalCompilationUnit))
; helper def:sizeOfLitteral(variable:java!StringLiteral): Integer =
variable.escapedValue.size();
--------------------------------------------- Use ArrayList Instead Of Vector ---------------------------------------------
helper def:sizeOf(variable:java!NumberLiteral): Integer =
helper def: UseArrayListInsteadOfVector() : Set(smm!Measure) = variable.tokenValue.toInteger();
-- Browse through all class(CompilationUnit)
--On recupere tout les new Vector et on verifie que le Vector appelé appartient au package java.utile --- IntegerInstantiation
java!ConstructorDeclaration.allInstances()-> -- Rule for metricsIntegerInstantiation : returns the set of class Measures that violates the rule.
collect(i|i.abstractTypeDeclaration) helper def: integerInstantiation() : Set(smm!Measure) =
->select(p|p.name='Vector')->collect(i|i.package) -- Take all ClassInstanceCreation with allInstances()
->select(p|p.name='util')->collect(i|i.package) java!ClassInstanceCreation.allInstances()
->select(p|p.name='java') -- Select all classes that declare an Integer type
->collect(i |thisModule.RuleUseArrayListInsteadOfVector(i)); ->select(it|it.method.oclIsTypeOf(java!ConstructorDeclaration) and it.method.name = 'Integer')
-- collect every result and sends an error message
--------------------------------------------- StringToString --------------------------------------------- ->collect(it2|thisModule.MeasureIntegerInstantiation(it2.originalCompilationUnit))
;
-- Rule for metrics stringToString : returns the set of class Measures that violates the rule.
helper def: stringToString() : Set(smm!Measure) = --- LongInstantiation
java!MethodInvocation.allInstances() -- Rule for metricsLongInstantiation : return the set of class Measures that violates the rule.
-> select( i | i.method.name = 'toString' and i.expression.variable.variablesContainer.type.type.name = 'String') helper def: longInstantiation() : Set(smm!Measure) =
-> collect ( i | thisModule.MeasureStringToString(i) ) -- Take all ClassInstanceCreation with allInstances()
; java!ClassInstanceCreation.allInstances()
-- Select all class who declare a Long type
->select(it| it.method.oclIsTypeOf(java!ConstructorDeclaration) and it.method.name = 'Long')
--------------------------------------------- start with --------------------------------------------- -- collect every results and send an error message
helper def: startsWith() : Set(smm!Measure) = ->collect(it2|thisModule.MeasureLongInstantiation(it2.originalCompilationUnit))
-- Take all MethodInvocation with allInstances() ;
java!MethodInvocation.allInstances()
->select(it| it.method.name= 'startsWith') --- ShortInstantiation
->select(it2| thisModule.isLengthUnder1(it2.arguments.first())) -- Rule for metrics ShortInstantiation : return the set of class Measures that violates the rule.
->collect(err|thisModule.MeasureStartWith(err)); helper def: shortInstantiation() : Set(smm!Measure) =
-- Take all ClassInstanceCreation with allInstances()
----- <=3 because we have to ignore '"' at begin and at end java!ClassInstanceCreation.allInstances()
helper def:isLengthUnder1(s:java!StringLiteral): Boolean = -- Select all class who declare a Short type
s.escapedValue.size() <= 3 ; ->select(it| it.method.oclIsTypeOf(java!ConstructorDeclaration) and it.method.name = 'Short')
-- collect every results and send an error message
->collect(it2|thisModule.MeasureShortInstantiation(it2.originalCompilationUnit))
;
--------------------------------------------- insufficientStringBufferDeclaration --------------------------------------------------------
--- Start with
helper def: startsWith() : Set(smm!Measure) =
-- Take all MethodInvocation with allInstances()
helper def: insufficientStringBufferDeclaration() : Set(smm!Measure) = java!MethodInvocation.allInstances()
java!MethodInvocation.allInstances() ->select(it| it.method.name= 'startsWith')
->select(it| it.method.name = 'append') ->select(it2| thisModule.isLengthUnder1(it2.arguments.first()))
->select(it1| it1.method.abstractTypeDeclaration.name = 'StringBuffer' or it1.method.abstractTypeDeclaration.name = 'StringBuilder') ->collect(err|thisModule.MeasureStartWith(err))
->select(it2|thisModule.unsuffisentInisialization(it2.expression, it2.arguments.first())) ;
->collect(it2|thisModule.MeasureInsufficientStringBufferDeclaration(it2.originalCompilationUnit))
; -- <=3 because we have to ignore '"' at begin and at end
helper def:isLengthUnder1(s:java!StringLiteral): Boolean =
-- -2 to ignone " at the begin and at end s.escapedValue.size() <= 3
helper def:unsuffisentInisialization(variable:java!SingleVariableAccess, str:java!StringLiteral): Boolean = ;
str.escapedValue.size()-2 > thisModule.FixedSize(variable.variable.initializer);
--- StringToString
helper def:FixedSize(variable:java!ClassInstanceCreation): Integer = -- Rule for metrics stringToString : returns the set of class Measures that violates the rule.
if variable.arguments.size() = 0 then helper def: stringToString() : Set(smm!Measure) =
16 java!MethodInvocation.allInstances()
else -> select( i | i.method.name = 'toString')
if variable.arguments.first().oclIsTypeOf(java!NumberLiteral) then -> select( i | i.expression.oclIsTypeOf(java!SingleVariableAccess))
thisModule.sizeOf(variable.arguments.first()) -> select( i | i.expression.variable.oclIsTypeOf(java!VariableDeclarationFragment))
else -> select( i | not i.expression.variable.variablesContainer.type.oclIsUndefined())
thisModule.sizeOfLitteral(variable.arguments.first()) -> select( i | not i.expression.variable.variablesContainer.type.type.oclIsUndefined())
endif -> select( i | i.expression.variable.variablesContainer.type.type.name = 'String')
endif; -> collect ( i | thisModule.MeasureStringToString(i) )
;
helper def:sizeOfLitteral(variable:java!StringLiteral): Integer =
variable.escapedValue.size(); --- TooFewBranchesForASwitchStatement
-- Returns a set of measures for each switch statement that violates the rule : number of switch cases < 3
helper def:sizeOf(variable:java!NumberLiteral): Integer = -- To test, use input model : tooFewBranchesForASwitchStatement.xmi
variable.tokenValue.toInteger(); helper def: tooFewBranchesForASwitchStatement(): Set(smm!Measure) =
-- If the number of switch cases for the current switch statement is < 3 then add a new measure to the set
java!SwitchStatement.allInstances()
-> select (switchStatement | thisModule.nbBranchesOfASwitchStatement(switchStatement) < 3)
------------------------------------------- AddEmptyString ------------------------------------------------------------------------------------ -> collect (switchStatement | thisModule.MeasureTooFewBranchesForASwitchStatement(switchStatement))
;
helper def: addEmptyString() : Set(smm!Measure) =
java!InfixExpression.allInstances() --- UseArraysAsList
->select(expression | expression.operator.name = '+') helper def: useArraysAsList() : Set(smm!Measure) =
->select(expression | (expression.leftOperand.oclIsTypeOf(java!StringLiteral) and expression.rightOperand.oclIsTypeOf(java!NumberLiteral)) or (expression.leftOperand.oclIsTypeOf(java!NumberLiteral) and expression.rightOperand.oclIsTypeOf(java!StringLiteral))) java!ForStatement.allInstances()
->collect(expression | thisModule.MesureAddEmptyString(expression.originalCompilationUnit)); ->select(st | st.body.statements.size() = 1)
->select(st | st.body.statements.get(0).expression.method.name = 'add')
->select(st | st.body.statements.get(0).expression.method.abstractTypeDeclaration.name = 'Collection'
------------------------------------------- UseArraysAsList ------------------------------------------------------------------------------------ or st.body.statements.get(0).expression.method.abstractTypeDeclaration.name = 'List'
or st.body.statements.get(0).expression.method.abstractTypeDeclaration.name = 'ArrayList')
helper def: useArraysAsList() : Set(smm!Measure) = ->select(st | st.body.statements.get(0).expression.expression.variable.initializer.type.type.type.type.name = 'ArrayList')
java!ForStatement.allInstances() ->select(st | st.body.statements.get(0).expression.arguments.size() = 1
->select(st | st.body.statements.size() = 1) and st.body.statements.get(0).expression.arguments.get(0).oclIsTypeOf(java!ArrayAccess))
->select(st | st.body.statements.get(0).expression.method.name = 'add') ->select(st | st.body.statements.get(0).expression.arguments.get(0).array.variable.type.type.oclIsTypeOf(java!ArrayType))
->select(st | st.body.statements.get(0).expression.method.abstractTypeDeclaration.name = 'Collection' ->collect(st | thisModule.MeasureUseArraysAsList(st.originalCompilationUnit))
or st.body.statements.get(0).expression.method.abstractTypeDeclaration.name = 'List' ;
or st.body.statements.get(0).expression.method.abstractTypeDeclaration.name = 'ArrayList')
->select(st | st.body.statements.get(0).expression.expression.variable.initializer.type.type.type.type.name = 'ArrayList') --- Use ArrayList Instead Of Vector
->select(st | st.body.statements.get(0).expression.arguments.size() = 1 helper def: UseArrayListInsteadOfVector() : Set(smm!Measure) =
and st.body.statements.get(0).expression.arguments.get(0).oclIsTypeOf(java!ArrayAccess)) -- Browse through all class(CompilationUnit)
->select(st | st.body.statements.get(0).expression.arguments.get(0).array.variable.type.type.oclIsTypeOf(java!ArrayType)) -- On recupere tout les new Vector et on verifie que le Vector appelé appartient au package java.utile
->collect(st | thisModule.MeasureUseArraysAsList(st.originalCompilationUnit)); java!ConstructorDeclaration.allInstances()->
collect(i|i.abstractTypeDeclaration)
------------------------------------------- InefficientEmptyStringCheck ------------------------------------------------------------------------------------ ->select(p|p.name='Vector')->collect(i|i.package)
->select(p|p.name='util')->collect(i|i.package)
helper def: inefficientEmptyStringCheck() : Set(smm!Measure) = ->select(p|p.name='java')
java!MethodInvocation.allInstances() ->collect(i |thisModule.RuleUseArrayListInsteadOfVector(i))
->select(i | i.method.name = 'isEmpty') ;
->select(i | i.expression.oclIsTypeOf(java!MethodInvocation))
->select(i | thisModule.expressionMethodIs(i.expression,'trim')) --- UseIndexOfChar
->collect(i | thisModule.MeasureInefficientEmptyStringCheck(i)); --Goes through all the MethodInvocation to check if the following rule is followed:
--Use String.indexOf(char) when checking for the index of a single character; it executes faster.
helper def: inefficientEmptyStringCheck2() : Set(smm!Measure) = helper def: useIndexOfChar() : Set(smm!Measure) =
java!InfixExpression.allInstances() java!MethodInvocation.allInstances()
->select(i | i.rightOperand.oclIsTypeOf(java!NumberLiteral)) -> select (m | m.method.name='indexOf')
->select(i | i.rightOperand.tokenValue = '0') -> select (m | m.arguments.size() = 1)
->select(i | i.leftOperand.oclIsTypeOf(java!MethodInvocation)) -> select (m | not m.arguments.first().oclIsTypeOf(java!CharacterLiteral))
->select(i | i.leftOperand.method.name = 'length') -> collect (m | thisModule.MeasureUseIndexOfChar(m))
->select(i | i.leftOperand.expression.oclIsTypeOf(java!MethodInvocation)) ;
->select(i | i.leftOperand.expression.method.name = 'trim')
->collect(i | thisModule.MeasureInefficientEmptyStringCheck(i)); --- UselessStringValueOf
--Goes through all the methods to check if the following rule is followed:
--No need to call String.valueOf to append to a string; just use the valueOf() argument directly.
helper def: expressionMethodIs(expr: java!Expression,str: String) : Boolean = helper def: uselessStringValueOf() : Set(smm!Measure) =
expr.method.name = str; java!MethodInvocation.allInstances()
-> select (m | m.method.name='valueOf' )
--------------------------------------------- AvoidInstantiatingObjectInLoops --------------------------------------------- -> select (m | m.refImmediateComposite().oclIsTypeOf(java!InfixExpression))
-> collect (m | thisModule.MeasureUselessStringValueOf(m))
helper def: avoidInstantiatingObjectsInLoops(): Set(smm!Measure) = ;
java!Statement.allInstances() \ No newline at end of file
->select(s | s.oclIsTypeOf(java!ForStatement) or s.oclIsTypeOf(java!DoStatement) or s.oclIsTypeOf(java!WhileStatement))
->select(s | s.body.statements
->select(s2 | s2.oclIsTypeOf(java!VariableDeclarationStatement))
->select(s2 | s2.fragments->exists(f | f.oclIsTypeOf(java!VariableDeclarationFragment)))
->exists(s2 | s2.fragments->exists(f | f.initializer.oclIsTypeOf(java!ClassInstanceCreation)))
)
->collect(s | thisModule.MeasureAvoidInstantiatingObjectInLoops(s));
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment