Commit fce77735 authored by Gerson SUNYE's avatar Gerson SUNYE
Browse files

Merge branch 'ReturnEmptyArrayRatherThanNull' into 'master'

Fix#851 Return empty array rather than null

See merge request naomod/mde/projet-2019!23
parents 94152812 48756479
<?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-projet">
<ownedElements name="(default package)">
<ownedElements xsi:type="java:ClassDeclaration" originalCompilationUnit="//@compilationUnits.0" name="ReturnEmptyArrayRatherThanNull">
<modifier visibility="public"/>
<bodyDeclarations xsi:type="java:MethodDeclaration" originalCompilationUnit="//@compilationUnits.0" name="badBehavior">
<comments xsi:type="java:LineComment" originalCompilationUnit="//@compilationUnits.0" content="// Not a good idea..." prefixOfParent="true"/>
<modifier visibility="public"/>
<body originalCompilationUnit="//@compilationUnits.0">
<statements xsi:type="java:ExpressionStatement" originalCompilationUnit="//@compilationUnits.0">
<expression xsi:type="java:MethodInvocation" originalCompilationUnit="//@compilationUnits.0" method="//@ownedElements.1/@ownedPackages.1/@ownedElements.1/@bodyDeclarations.0">
<arguments xsi:type="java:StringLiteral" originalCompilationUnit="//@compilationUnits.0" escapedValue="&quot;Bonjour&quot;"/>
<expression xsi:type="java:SingleVariableAccess" variable="//@ownedElements.1/@ownedPackages.0/@ownedElements.0/@bodyDeclarations.0/@fragments.0">
<qualifier xsi:type="java:TypeAccess" type="//@ownedElements.1/@ownedPackages.0/@ownedElements.0"/>
</expression>
</expression>
</statements>
<statements xsi:type="java:ReturnStatement" originalCompilationUnit="//@compilationUnits.0">
<expression xsi:type="java:NullLiteral" originalCompilationUnit="//@compilationUnits.0"/>
</statements>
</body>
<returnType type="//@orphanTypes.9"/>
</bodyDeclarations>
<bodyDeclarations xsi:type="java:MethodDeclaration" originalCompilationUnit="//@compilationUnits.0" name="bonnePratique">
<comments xsi:type="java:LineComment" originalCompilationUnit="//@compilationUnits.0" content="// Good behavior" prefixOfParent="true"/>
<modifier visibility="public"/>
<body originalCompilationUnit="//@compilationUnits.0">
<statements xsi:type="java:ExpressionStatement" originalCompilationUnit="//@compilationUnits.0">
<expression xsi:type="java:MethodInvocation" originalCompilationUnit="//@compilationUnits.0" method="//@ownedElements.1/@ownedPackages.1/@ownedElements.1/@bodyDeclarations.0">
<arguments xsi:type="java:StringLiteral" originalCompilationUnit="//@compilationUnits.0" escapedValue="&quot;Au revoir&quot;"/>
<expression xsi:type="java:SingleVariableAccess" variable="//@ownedElements.1/@ownedPackages.0/@ownedElements.0/@bodyDeclarations.0/@fragments.0">
<qualifier xsi:type="java:TypeAccess" type="//@ownedElements.1/@ownedPackages.0/@ownedElements.0"/>
</expression>
</expression>
</statements>
<statements xsi:type="java:ReturnStatement" originalCompilationUnit="//@compilationUnits.0">
<expression xsi:type="java:ArrayCreation" originalCompilationUnit="//@compilationUnits.0">
<dimensions xsi:type="java:NumberLiteral" originalCompilationUnit="//@compilationUnits.0" tokenValue="0"/>
<type type="//@orphanTypes.10"/>
</expression>
</statements>
</body>
<returnType type="//@orphanTypes.10"/>
</bodyDeclarations>
<bodyDeclarations xsi:type="java:MethodDeclaration" originalCompilationUnit="//@compilationUnits.0" name="testVoid">
<modifier visibility="public"/>
<body originalCompilationUnit="//@compilationUnits.0">
<statements xsi:type="java:ExpressionStatement" originalCompilationUnit="//@compilationUnits.0">
<expression xsi:type="java:MethodInvocation" originalCompilationUnit="//@compilationUnits.0" method="//@ownedElements.1/@ownedPackages.1/@ownedElements.1/@bodyDeclarations.0">
<arguments xsi:type="java:StringLiteral" originalCompilationUnit="//@compilationUnits.0" escapedValue="&quot;Coucou test&quot;"/>
<expression xsi:type="java:SingleVariableAccess" variable="//@ownedElements.1/@ownedPackages.0/@ownedElements.0/@bodyDeclarations.0/@fragments.0">
<qualifier xsi:type="java:TypeAccess" type="//@ownedElements.1/@ownedPackages.0/@ownedElements.0"/>
</expression>
</expression>
</statements>
</body>
<returnType type="//@orphanTypes.5"/>
</bodyDeclarations>
<bodyDeclarations xsi:type="java:MethodDeclaration" originalCompilationUnit="//@compilationUnits.0" name="testEmpty">
<modifier visibility="public"/>
<body originalCompilationUnit="//@compilationUnits.0"/>
<returnType type="//@orphanTypes.5"/>
</bodyDeclarations>
</ownedElements>
</ownedElements>
<ownedElements name="java" proxy="true">
<ownedPackages name="lang" proxy="true">
<ownedElements xsi:type="java:ClassDeclaration" name="System" proxy="true" usagesInTypeAccess="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.0/@expression/@expression/@qualifier //@ownedElements.0/@ownedElements.0/@bodyDeclarations.1/@body/@statements.0/@expression/@expression/@qualifier //@ownedElements.0/@ownedElements.0/@bodyDeclarations.2/@body/@statements.0/@expression/@expression/@qualifier">
<bodyDeclarations xsi:type="java:FieldDeclaration" proxy="true">
<fragments name="out" proxy="true" usagesInImports="//@compilationUnits.0/@imports.0" usageInVariableAccess="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.0/@expression/@expression //@ownedElements.0/@ownedElements.0/@bodyDeclarations.1/@body/@statements.0/@expression/@expression //@ownedElements.0/@ownedElements.0/@bodyDeclarations.2/@body/@statements.0/@expression/@expression"/>
</bodyDeclarations>
</ownedElements>
<ownedElements xsi:type="java:ClassDeclaration" name="String" proxy="true" usagesInTypeAccess="//@ownedElements.1/@ownedPackages.1/@ownedElements.1/@bodyDeclarations.0/@parameters.0/@type //@orphanTypes.10/@elementType">
<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"/>
<ownedElements xsi:type="java:InterfaceDeclaration" name="AutoCloseable" proxy="true" usagesInTypeAccess="//@ownedElements.1/@ownedPackages.1/@ownedElements.4/@superInterfaces.0"/>
<ownedElements xsi:type="java:InterfaceDeclaration" name="Appendable" proxy="true" usagesInTypeAccess="//@ownedElements.1/@ownedPackages.1/@ownedElements.1/@superInterfaces.0"/>
</ownedPackages>
<ownedPackages name="io" proxy="true">
<ownedElements xsi:type="java:InterfaceDeclaration" name="Serializable" proxy="true" usagesInTypeAccess="//@ownedElements.1/@ownedPackages.0/@ownedElements.1/@superInterfaces.0"/>
<ownedElements xsi:type="java:ClassDeclaration" name="PrintStream" proxy="true">
<bodyDeclarations xsi:type="java:MethodDeclaration" name="println" proxy="true" usages="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@body/@statements.0/@expression //@ownedElements.0/@ownedElements.0/@bodyDeclarations.1/@body/@statements.0/@expression //@ownedElements.0/@ownedElements.0/@bodyDeclarations.2/@body/@statements.0/@expression">
<parameters name="arg0" proxy="true">
<type type="//@ownedElements.1/@ownedPackages.0/@ownedElements.1"/>
</parameters>
</bodyDeclarations>
<superInterfaces type="//@ownedElements.1/@ownedPackages.0/@ownedElements.5"/>
<superInterfaces type="//@ownedElements.1/@ownedPackages.1/@ownedElements.4"/>
<superClass type="//@ownedElements.1/@ownedPackages.1/@ownedElements.2"/>
</ownedElements>
<ownedElements xsi:type="java:ClassDeclaration" name="FilterOutputStream" proxy="true" usagesInTypeAccess="//@ownedElements.1/@ownedPackages.1/@ownedElements.1/@superClass">
<superClass type="//@ownedElements.1/@ownedPackages.1/@ownedElements.3"/>
</ownedElements>
<ownedElements xsi:type="java:ClassDeclaration" name="OutputStream" proxy="true" usagesInTypeAccess="//@ownedElements.1/@ownedPackages.1/@ownedElements.2/@superClass">
<superInterfaces type="//@ownedElements.1/@ownedPackages.1/@ownedElements.4"/>
<superInterfaces type="//@ownedElements.1/@ownedPackages.1/@ownedElements.5"/>
</ownedElements>
<ownedElements xsi:type="java:InterfaceDeclaration" name="Closeable" proxy="true" usagesInTypeAccess="//@ownedElements.1/@ownedPackages.1/@ownedElements.3/@superInterfaces.0 //@ownedElements.1/@ownedPackages.1/@ownedElements.1/@superInterfaces.1">
<superInterfaces type="//@ownedElements.1/@ownedPackages.0/@ownedElements.4"/>
</ownedElements>
<ownedElements xsi:type="java:InterfaceDeclaration" name="Flushable" proxy="true" usagesInTypeAccess="//@ownedElements.1/@ownedPackages.1/@ownedElements.3/@superInterfaces.1"/>
</ownedPackages>
</ownedElements>
<orphanTypes xsi:type="java:PrimitiveTypeInt" name="int" usagesInTypeAccess="//@orphanTypes.9/@elementType"/>
<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.2/@returnType //@ownedElements.0/@ownedElements.0/@bodyDeclarations.3/@returnType"/>
<orphanTypes xsi:type="java:PrimitiveTypeChar" name="char"/>
<orphanTypes xsi:type="java:PrimitiveTypeShort" name="short"/>
<orphanTypes xsi:type="java:PrimitiveTypeByte" name="byte"/>
<orphanTypes xsi:type="java:ArrayType" name="int[]" usagesInTypeAccess="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@returnType" dimensions="1">
<elementType type="//@orphanTypes.0"/>
</orphanTypes>
<orphanTypes xsi:type="java:ArrayType" name="java.lang.String[]" usagesInTypeAccess="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.1/@returnType //@ownedElements.0/@ownedElements.0/@bodyDeclarations.1/@body/@statements.1/@expression/@type" dimensions="1">
<elementType type="//@ownedElements.1/@ownedPackages.0/@ownedElements.1"/>
</orphanTypes>
<compilationUnits name="ReturnEmptyArrayRatherThanNull.java" originalFilePath="D:\Documents\Cours\M2-ALMA\Gerson\test-projet\src\ReturnEmptyArrayRatherThanNull.java" commentList="//@ownedElements.0/@ownedElements.0/@bodyDeclarations.0/@comments.0 //@ownedElements.0/@ownedElements.0/@bodyDeclarations.1/@comments.0" types="//@ownedElements.0/@ownedElements.0">
<imports originalCompilationUnit="//@compilationUnits.0" static="true" importedElement="//@ownedElements.1/@ownedPackages.0/@ownedElements.0/@bodyDeclarations.0/@fragments.0"/>
</compilationUnits>
</java:Model>
......@@ -38,7 +38,7 @@ helper def: allMeasures(project : java!Model): Set(smm!Measure) =
-- Multithreading rules
--
thisModule.dontCallThreadRun(),
--thisModule.avoidThreadGroup(),
thisModule.avoidThreadGroup(),
thisModule.useNotifyAllInsteadOfNotify(),
-- Code Style rules
......@@ -46,13 +46,13 @@ helper def: allMeasures(project : java!Model): Set(smm!Measure) =
thisModule.shortMethodName(),
thisModule.tooManyStaticImports(),
thisModule.AvoidDollarSigns() ,
thisModule.avoidFieldNameMatchingMethodName(),
-- Design rules
--
thisModule.tooManyFields(),
thisModule.tooManyMethods(),
thisModule.returnFromFinallyBlock(),
thisModule.returnEmptyArrayRatherThanNull(),
thisModule.excessiveParameterList(),
-- Performance rules
......@@ -314,6 +314,7 @@ rule MesureTooManyMethods(class : java!ClassDeclaration) {
}
}
-- A Measure instance if the class violates the rule ReturnFromFinallyBlock.
rule MesureReturnFromFinallyBlock(method : java!MethodDeclaration) {
to
om: smm!ObservedMeasure (
......@@ -377,7 +378,7 @@ rule measureAvoidThreadGroup(variable : java!VariableDeclarationFragment) {
measure <- noc,
measurements <- measurement
),
noc: smm!DimensionalMeasure (
noc: smm!DimnsionalMeasure (
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.'
),
......@@ -390,7 +391,25 @@ rule measureAvoidThreadGroup(variable : java!VariableDeclarationFragment) {
}
}
--------------------------------------------- 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) {
......@@ -406,7 +425,6 @@ rule MesureExcessiveParameterList(method : java!MethodDeclaration) {
measurement: smm!DirectMeasurement (
error<-'The method '+ method.name + ' in the class ' + method.originalCompilationUnit.name + ' has an excessive parameter list.'
)
do {
noc;
}
......@@ -426,7 +444,6 @@ rule MesureAvoidFieldNameMatchingMethodName(class : java!ClassDeclaration, metho
measurement: smm!DirectMeasurement (
error <- 'In the ' + class.name + ' class you have an field and an method with the same name : '+ method.name
)
do {
noc;
}
......
......@@ -48,6 +48,18 @@ helper def: returnFromFinallyBlock() : Set(smm!Measure) =
endif
);
--------------------------------------------- returnEmptyArrayRatherThanNull ---------------------------------------------
-- Helper for issue ReturnEmptyArrayRatherThanNull : returns a Measure for each method that returns an array rather than null
helper def: returnEmptyArrayRatherThanNull() : Set(smm!Measure) =
java!MethodDeclaration.allInstances()
-> select (method | method.returnType <> OclUndefined and method.body <> OclUndefined)
-> select (method | method.returnType.type.oclIsTypeOf(java!ArrayType))
-> collect(method | method.body.statements)
-> iterate(statements; statementRes : Set(smm!Measure) = Set{} |
statements
-> select (statement | statement.oclIsTypeOf(java!ReturnStatement) and statement.expression.oclIsTypeOf(java!NullLiteral))
-> collect(statement | thisModule.MesureReturnEmptyArrayRatherThanNull(statement))
);
--------------------------------------------- ExcessiveParameterList ---------------------------------------------
-- Helper for issue ExcessiveParameterList : return a Measure for each method that has too many parameters.
......
Supports Markdown
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