bestPractices.atl 6.15 KB
Newer Older
Raphael PAGE's avatar
Raphael PAGE committed
1
2
3
4
5
6
7
library bestPractices;

--------------------------------------------- AvoidPrintStackTrace ---------------------------------------------

--Goes through all the methods to check if the following rule is followed:
--Avoid printStackTrace()
helper def: avoidPrintStackTrace() : Set(smm!Measure) =
8
9
10
11
	java!MethodInvocation.allInstances()
		-> select (m | m.method.name = 'printStackTrace')
		-> collect (m | thisModule.MeasureAvoidPrintStackTrace(m))
;
12
13
14
15
16
17
18

--------------------------------------------- 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{} |
19
		-- Foreach FieldDeclaration, check all methods
20
21
		i.bodyDeclarations->iterate(field; resIter : Set(smm!Measure) = Set{} | 
		if field.oclIsTypeOf(java!FieldDeclaration)
22
23
24
25
		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))
26
27
28
		else res
		endif
	)
29
30
31
32
33
34
35
36
37
38
);

--------------------------------------------- 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));
39
40
41
42
43
44
45
46
47
48
49
50

--------------------------------------------- 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))
	);
51
52
53
54
55
56

--------------------------------------------- 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
57
58
		->select(assert | assert.method.name = 'assertEquals')
		->select(assert | thisModule.isWrongUseAssertTrueInsteadOfAssertEquals(assert))
59
60
61
62
63
64
		->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();
65
	
66
67
68
69
70
71
72
73
74
75
76
77
	 --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';

78
79
80
81
82

--------------------------------------------- AvoidStringBufferField  ---------------------------------------------
-- Rule for metrics AvoidStringBufferField
helper def: avoidStringBufferField() : Set(smm!Measure) =
	java!FieldDeclaration.allInstances()
Oussama EL KOURRI's avatar
Oussama EL KOURRI committed
83
84
		->select(dec | dec.type <> OclUndefined )
		->select(dec | ( dec.type.type.name = 'StringBuffer' or dec.type.type.name = 'StringBuilder'))
85
		->collect(dec | thisModule.MeasureAvoidStringBufferField(dec));
86
87
88
89
90
91
92
93
94
95
96
97
---------------------------------------------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());
Hanane HADJI's avatar
Hanane HADJI committed
98
	
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
--------------------------------------------- ForLoopVariableCount ---------------------------------------------

-- Rule for metrics ForLoopVariableCount
helper def: forLoopVariableCount(): Set(smm!Measure) =
	java!ForStatement.allInstances()->select(forStatement |
		forStatement.nbLocalVariableDeclarations() > 1
	)->collect(forStatement | thisModule.MeasureForLoopVariableCount(forStatement));

-- Returns the number of declared local variables in the for loop
helper context java!ForStatement def: nbLocalVariableDeclarations(): Integer =
	self.initializers->iterate(expression; acc: Integer = 0 | 
		acc + expression.nbLocalVariableDeclarations()
	);

-- A loop initializer can contains any Expression but we care about only VariableDeclarationExpression
helper context java!Expression def: nbLocalVariableDeclarations(): Integer =
	0;

helper context java!VariableDeclarationExpression def: nbLocalVariableDeclarations(): Integer =
	self.fragments.size(); -- The fragments collection contains all the variable declarations of an initializer*
						   -- Initializer* : for(int x = 0; ...), "int x = 0" is the initializer part of the for loop