Commit 5897dc16 authored by Gerson SUNYE's avatar Gerson SUNYE
Browse files

Merge branch 'master' into 'master'

Fix #760 SimplifyConditional

Closes #908 and #760

See merge request !172
parents c128189e 75cee539
<?xml version="1.0" encoding="ASCII"?>
<java:Model xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:java="http://www.eclipse.org/MoDisco/Java/0.2.incubation/java" name="test">
<ownedElements name="test">
<ownedElements xsi:type="java:ClassDeclaration" originalCompilationUnit="//@compilationUnits.0" name="Foo">
<modifier/>
<bodyDeclarations xsi:type="java:MethodDeclaration" originalCompilationUnit="//@compilationUnits.0" name="bar">
<modifier/>
<body originalCompilationUnit="//@compilationUnits.0">
<statements xsi:type="java:IfStatement" originalCompilationUnit="//@compilationUnits.0">
<expression xsi:type="java:InfixExpression" originalCompilationUnit="//@compilationUnits.0" operator="&amp;&amp;">
<rightOperand xsi:type="java:InstanceofExpression" originalCompilationUnit="//@compilationUnits.0">
<rightOperand type="//@ownedElements.1/@ownedPackages.0/@ownedElements.1"/>
<leftOperand xsi:type="java:SingleVariableAccess" variable="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@parameters.0"/>
</rightOperand>
<leftOperand xsi:type="java:InfixExpression" originalCompilationUnit="//@compilationUnits.0" operator="!=">
<rightOperand xsi:type="java:NullLiteral" originalCompilationUnit="//@compilationUnits.0"/>
<leftOperand xsi:type="java:SingleVariableAccess" variable="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@parameters.0"/>
</leftOperand>
</expression>
<thenStatement xsi:type="java:Block" originalCompilationUnit="//@compilationUnits.0">
<comments xsi:type="java:LineComment" originalCompilationUnit="//@compilationUnits.0" content="// just drop the &quot;x != null&quot; check" enclosedByParent="true"/>
</thenStatement>
</statements>
<statements xsi:type="java:IfStatement" originalCompilationUnit="//@compilationUnits.0">
<expression xsi:type="java:InfixExpression" originalCompilationUnit="//@compilationUnits.0" operator="||">
<rightOperand xsi:type="java:InstanceofExpression" originalCompilationUnit="//@compilationUnits.0">
<rightOperand type="//@ownedElements.1/@ownedPackages.0/@ownedElements.1"/>
<leftOperand xsi:type="java:SingleVariableAccess" variable="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@parameters.0"/>
</rightOperand>
<leftOperand xsi:type="java:InfixExpression" originalCompilationUnit="//@compilationUnits.0" operator="==">
<rightOperand xsi:type="java:NullLiteral" originalCompilationUnit="//@compilationUnits.0"/>
<leftOperand xsi:type="java:SingleVariableAccess" variable="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@parameters.0"/>
</leftOperand>
</expression>
<thenStatement xsi:type="java:Block" originalCompilationUnit="//@compilationUnits.0"/>
</statements>
<statements xsi:type="java:IfStatement" originalCompilationUnit="//@compilationUnits.0">
<expression xsi:type="java:InfixExpression" originalCompilationUnit="//@compilationUnits.0" operator="&amp;&amp;">
<rightOperand xsi:type="java:InstanceofExpression" originalCompilationUnit="//@compilationUnits.0">
<rightOperand type="//@ownedElements.1/@ownedPackages.0/@ownedElements.1"/>
<leftOperand xsi:type="java:SingleVariableAccess" variable="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@parameters.0"/>
</rightOperand>
<leftOperand xsi:type="java:InfixExpression" originalCompilationUnit="//@compilationUnits.0" operator="!=">
<rightOperand xsi:type="java:NullLiteral" originalCompilationUnit="//@compilationUnits.0"/>
<leftOperand xsi:type="java:SingleVariableAccess" variable="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@parameters.1"/>
</leftOperand>
</expression>
<thenStatement xsi:type="java:Block" originalCompilationUnit="//@compilationUnits.0">
<comments xsi:type="java:LineComment" originalCompilationUnit="//@compilationUnits.0" content="// just drop the &quot;x != null&quot; check" enclosedByParent="true"/>
</thenStatement>
</statements>
<statements xsi:type="java:IfStatement" originalCompilationUnit="//@compilationUnits.0">
<expression xsi:type="java:InfixExpression" originalCompilationUnit="//@compilationUnits.0" operator="&amp;&amp;">
<rightOperand xsi:type="java:InstanceofExpression" originalCompilationUnit="//@compilationUnits.0">
<rightOperand type="//@ownedElements.1/@ownedPackages.0/@ownedElements.1"/>
<leftOperand xsi:type="java:SingleVariableAccess" variable="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@parameters.1"/>
</rightOperand>
<leftOperand xsi:type="java:InfixExpression" originalCompilationUnit="//@compilationUnits.0" operator="!=">
<rightOperand xsi:type="java:SingleVariableAccess" variable="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@parameters.1"/>
<leftOperand xsi:type="java:NullLiteral" originalCompilationUnit="//@compilationUnits.0"/>
</leftOperand>
</expression>
<thenStatement xsi:type="java:Block" originalCompilationUnit="//@compilationUnits.0">
<comments xsi:type="java:LineComment" originalCompilationUnit="//@compilationUnits.0" content="// just drop the &quot;x != null&quot; check" enclosedByParent="true"/>
</thenStatement>
</statements>
<statements xsi:type="java:IfStatement" originalCompilationUnit="//@compilationUnits.0">
<expression xsi:type="java:InfixExpression" originalCompilationUnit="//@compilationUnits.0" operator="&amp;&amp;">
<rightOperand xsi:type="java:InstanceofExpression" originalCompilationUnit="//@compilationUnits.0">
<rightOperand type="//@ownedElements.1/@ownedPackages.0/@ownedElements.1"/>
<leftOperand xsi:type="java:SingleVariableAccess" variable="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@parameters.1"/>
</rightOperand>
<leftOperand xsi:type="java:BooleanLiteral" originalCompilationUnit="//@compilationUnits.0" value="true"/>
</expression>
<thenStatement xsi:type="java:Block" originalCompilationUnit="//@compilationUnits.0">
<comments xsi:type="java:LineComment" originalCompilationUnit="//@compilationUnits.0" content="// just drop the &quot;x != null&quot; check" enclosedByParent="true"/>
</thenStatement>
</statements>
</body>
<parameters originalCompilationUnit="//@compilationUnits.0" name="x" usageInVariableAccess="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.0/@expression/@leftOperand/@leftOperand //@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.0/@expression/@rightOperand/@leftOperand //@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.1/@expression/@leftOperand/@leftOperand //@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.1/@expression/@rightOperand/@leftOperand //@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.2/@expression/@rightOperand/@leftOperand">
<modifier/>
<type type="//@ownedElements.1/@ownedPackages.0/@ownedElements.0"/>
</parameters>
<parameters originalCompilationUnit="//@compilationUnits.0" name="y" usageInVariableAccess="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.2/@expression/@leftOperand/@leftOperand //@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.3/@expression/@leftOperand/@rightOperand //@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.3/@expression/@rightOperand/@leftOperand //@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.4/@expression/@rightOperand/@leftOperand">
<modifier/>
<type type="//@ownedElements.1/@ownedPackages.0/@ownedElements.0"/>
</parameters>
<returnType type="//@orphanTypes.5"/>
</bodyDeclarations>
</ownedElements>
</ownedElements>
<ownedElements name="java" proxy="true">
<ownedPackages name="lang" proxy="true">
<ownedElements xsi:type="java:ClassDeclaration" name="Object" proxy="true" usagesInTypeAccess="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@parameters.0/@type //@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@parameters.1/@type"/>
<ownedElements xsi:type="java:ClassDeclaration" name="String" proxy="true" usagesInTypeAccess="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.0/@expression/@rightOperand/@rightOperand //@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.1/@expression/@rightOperand/@rightOperand //@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.2/@expression/@rightOperand/@rightOperand //@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.3/@expression/@rightOperand/@rightOperand //@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.4/@expression/@rightOperand/@rightOperand">
<superInterfaces type="//@ownedElements.1/@ownedPackages.1/@ownedElements.0"/>
<superInterfaces type="//@ownedElements.1/@ownedPackages.0/@ownedElements.2"/>
<superInterfaces type="//@ownedElements.1/@ownedPackages.0/@ownedElements.3"/>
</ownedElements>
<ownedElements xsi:type="java:InterfaceDeclaration" name="Comparable" proxy="true" usagesInTypeAccess="//@ownedElements.1/@ownedPackages.0/@ownedElements.1/@superInterfaces.1">
<typeParameters name="T" proxy="true"/>
</ownedElements>
<ownedElements xsi:type="java:InterfaceDeclaration" name="CharSequence" proxy="true" usagesInTypeAccess="//@ownedElements.1/@ownedPackages.0/@ownedElements.1/@superInterfaces.2"/>
</ownedPackages>
<ownedPackages name="io" proxy="true">
<ownedElements xsi:type="java:InterfaceDeclaration" name="Serializable" proxy="true" usagesInTypeAccess="//@ownedElements.1/@ownedPackages.0/@ownedElements.1/@superInterfaces.0"/>
</ownedPackages>
</ownedElements>
<orphanTypes xsi:type="java:PrimitiveTypeInt" name="int"/>
<orphanTypes xsi:type="java:PrimitiveTypeLong" name="long"/>
<orphanTypes xsi:type="java:PrimitiveTypeFloat" name="float"/>
<orphanTypes xsi:type="java:PrimitiveTypeDouble" name="double"/>
<orphanTypes xsi:type="java:PrimitiveTypeBoolean" name="boolean"/>
<orphanTypes xsi:type="java:PrimitiveTypeVoid" name="void" usagesInTypeAccess="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@returnType"/>
<orphanTypes xsi:type="java:PrimitiveTypeChar" name="char"/>
<orphanTypes xsi:type="java:PrimitiveTypeShort" name="short"/>
<orphanTypes xsi:type="java:PrimitiveTypeByte" name="byte"/>
<compilationUnits name="Foo.java" originalFilePath="E:\Henri\Documents\Projet Gerson\test\src\test\Foo.java" commentList="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.0/@thenStatement/@comments.0 //@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.2/@thenStatement/@comments.0 //@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.3/@thenStatement/@comments.0 //@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.4/@thenStatement/@comments.0" package="//@ownedElements.0" types="//@ownedElements.0/@ownedElements.0"/>
</java:Model>
......@@ -31,8 +31,8 @@ rule Java2SMM {
helper def: allMeasures(project : java!Model): Set(smm!Measure) =
Set{
-- Example rule
--
--Example rule
thisModule.numberOfClasses(),
-- Multithreading rules
......@@ -77,6 +77,7 @@ helper def: allMeasures(project : java!Model): Set(smm!Measure) =
thisModule.tooManyFields(),
thisModule.tooManyMethods(),
thisModule.SimplifyBooleanAssertion(),
thisModule.simplifyConditional(),
-- Performance rules
--
......@@ -1424,6 +1425,27 @@ rule MeasureSimplifyBooleanAssertion(i : java!PrefixExpression) {
}
}
-- ------------------------------------------- SimplifyConditional ---------------------------------------------
--- Triggers the rule when a variable is compared to null and then tested in instanceof
rule MeasureSimplifyConditional(class : String, method: String) {
to
om: smm!ObservedMeasure (
measure <- noc,
measurements <- measurement
),
noc: smm!DimensionalMeasure (
name <- 'SimplifyConditional',
shortDescription <- 'Test if a variable is null is useless before an "instanceof".'
),
measurement: smm!DirectMeasurement (
error<-'The method ' + method + ' in ' + class + ' contains null check followed by an instanceof check on the same variable.'
)
do {
noc;
}
}
-- ----------------------------------------- start with ------------------------------------------------------------------------------------
--- TODO: Add comment
rule MeasureStartWith(w: java!MethodInvocation) {
......
......@@ -139,6 +139,60 @@ helper def: SimplifyBooleanAssertion() : Set(java!PrefixExpression) =
-> select(i | i.eContainer().method.name = 'assertTrue' or i.eContainer().method.name = 'assertFalse')
-> collect(i | thisModule.MeasureSimplifyBooleanAssertion(i));
--------------------------------------------- SimplifyConditional ---------------------------------------------
--- Main helper for SimplifyConditional : collects all "&&" and "||" where left operand checks if a variable is null and right operand tests the instance type of the variable.
helper def: simplifyConditional() : Set(smm!Measure) =
java!InfixExpression.allInstances()
->select(bool | thisModule.dealWithAnds(bool) or thisModule.dealWithOrs(bool))
->collect(bool | thisModule.MeasureSimplifyConditional(bool.originalCompilationUnit.name, bool.getMethodName()));
--- Checks on && expressions
helper def: dealWithAnds(exp:java!InfixExpression) : Boolean =
exp.operator.toString() = '&&' and
exp.leftOperand.operateLeft('!=') and
exp.rightOperand.oclIsTypeOf(java!InstanceofExpression) and
exp.rightOperand.getName() = exp.leftOperand.getName();
--- Checks on || expressions
helper def: dealWithOrs(exp:java!InfixExpression) : Boolean =
exp.operator.toString() = '||' and
exp.leftOperand.operateLeft('==') and
exp.rightOperand.oclIsTypeOf(java!InstanceofExpression) and
exp.rightOperand.getName() = exp.leftOperand.getName();
--- Gets the name of the variable compared to null
helper context java!InfixExpression def: getName(): String =
self.leftOperand.getVariableName().concat(self.rightOperand.getVariableName());
--- Gets the name of the variable which type is tested
helper context java!InstanceofExpression def: getName(): String =
self.leftOperand.getVariableName();
helper context OclAny def: getName(): String =
'';
helper context java!SingleVariableAccess def: getVariableName(): String =
self.variable.name;
helper context OclAny def: getVariableName(): String =
'';
--- Computes verifications on the left part of the initial expression
helper context java!InfixExpression def: operateLeft(s:String): Boolean =
self.operator.toString() = s and
self.rightOperand.oclIsTypeOf(java!NullLiteral) or
self.leftOperand.oclIsTypeOf(java!NullLiteral);
helper context java!Expression def: operateLeft(s:String): Boolean =
false;
helper context java!MethodDeclaration def: getMethodName(): String =
self.name;
helper context OclAny def: getMethodName(): String =
self.eContainer().getMethodName();
--------------------------------------------- AbstractClassWithoutAnyMethod ---------------------------------------------
-- Rule for metrics AbstractClassWithoutAnyMethod : return the set of class Measures that violates the rule.
helper def: abstractClassWithoutAnyMethod() : Set(smm!Measure) =
......
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