analysis.atl 44.9 KB
Newer Older
Gerson Sunyé's avatar
Gerson Sunyé committed
1
2
3
-- @nsURI smm=http://www.eclipse.org/MoDisco/SMM/1.0.Beta2/smm
-- @nsURI java=http://www.eclipse.org/MoDisco/Java/0.2.incubation/java

Gerson Sunyé's avatar
Gerson Sunyé committed
4
5

module analysis;
Gerson Sunyé's avatar
Gerson Sunyé committed
6
7
create OUT: smm from IN: java;

8
uses design;
9
uses codestyle;
Gerson Sunyé's avatar
Gerson Sunyé committed
10
uses multithreading;
11
uses performance;
12
uses bestPractices;
Roxane MARECHAL's avatar
Roxane MARECHAL committed
13
uses documentation;
14
uses errorProne;
15

Roxane MARECHAL's avatar
Roxane MARECHAL committed
16

Gerson Sunyé's avatar
Gerson Sunyé committed
17
18
19
20
21
22
23
24
25
26
27
28
29
30
rule Java2SMM {
	from
		project: java!Model
	to
		model: smm!SmmModel (
			name <- project.name,
			librairies <- lib
		),
		lib: smm!MeasureLibrary (
			name <- 'Java metrics',
			measureElements <- thisModule.allMeasures(project)
		)
}

31
32
33
34
helper def: allMeasures(project : java!Model): Set(smm!Measure) =

	Set{
		-- Example rule
35
36
		--
		thisModule.numberOfClasses(),
37
38
		
		-- Multithreading rules
39
		--
40
41
42
		thisModule.useNotifyAllInsteadOfNotify(),
		
		-- Code Style rules
43
44
		--
		thisModule.shortMethodName(),
45
46
		thisModule.tooManyStaticImports(),
		thisModule.shortClassName(),
47
		thisModule.shortVariableName(),
48
49
50
51
52
53
		thisModule.extendsObject(),
		thisModule.unnecessaryReturn(),
		thisModule.longVariable(),
		thisModule.noPackageDeclaration(),

		-- Design rules
54
55
		--
		thisModule.tooManyFields(),
56
57
58
59
		thisModule.tooManyMethods(),
		thisModule.returnFromFinallyBlock(),
		thisModule.longInstantiation(),
		thisModule.shortInstantiation(),
60
		thisModule.excessiveParameterList(),
61
62
63
64
65
		thisModule.finalFieldCouldBeStatic(),
		thisModule.signatureDeclareThrowsException(),
		thisModule.ExcessiveClassLength(),

		-- Performance rules
66
		--
Raphael PAGE's avatar
Raphael PAGE committed
67
		thisModule.uselessStringValueOf(),
68
69
70
71
72
73
74
75
76
		thisModule.tooFewBranchesForASwitchStatement(),
		thisModule.useIndexOfChar(),
		thisModule.avoidPrintStackTrace(),
		thisModule.avoidUsingShortType(),
		thisModule.emptyStatementBlock(),
		thisModule.avoidRethrowingException(),
		thisModule.integerInstantiation(),
		
		-- Documentation rules
Roxane MARECHAL's avatar
Roxane MARECHAL committed
77
		--
Ronan GUEGUEN's avatar
Ronan GUEGUEN committed
78
		thisModule.commentContent(),
79
80
81
		

		-- Error prone rules
82
		--
83
		thisModule.missingBreakInSwitch(),
84
85
86
87
88
89
		thisModule.suspiciousEqualsMethodName(),
		thisModule.doNotExtendJavaLangThrowable(),
		thisModule.doNotExtendJavaLangError(),
		thisModule.avoidCallingFinalize(),
		thisModule.emptyTryBlock(),
		thisModule.dontImportSun(),
Hanane HADJI's avatar
Hanane HADJI committed
90
91
92
		thisModule.emptySwitchStatement(),
		thisModule.emptySynchronizedBlock(),
		thisModule.emptyFinallyBlock(),
93
		--thisModule.emptyfinalizeMethod(),
Hanane HADJI's avatar
Hanane HADJI committed
94
95
		--thisModule.doNotThrowExceptionInFinally(),
	
96
97
98
99
100
101
102
		--thisModule.finalizeShouldBeProtected(),
		thisModule.UnconditionalIfStatement(),
		thisModule.EmptyInitializer(),	
		thisModule.CloneMethodMustBePublic(),
		thisModule.AvoidEnumAsIdentifier(),
		thisModule.AvoidCatchingNPE(),
		thisModule.UseProperClassLoader(),
103
		
104
		-- Best practices rules
105
106
		thisModule.useAssertTrueInsteadOfAssertEquals(),
		thisModule.useAssertSameInsteadOfAssertTrue(),
107
		thisModule.switchDensity()
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
		
		
		-- Bugged rules:
		--
		-- thisModule.avoidThrowingNullPointerException(),
	    -- thisModule.UseArrayListInsteadOfVector(),
		-- thisModule.commentRequired(),
		-- thisModule.compareObjectsWithEquals(),
		-- thisModule.emptyWhileStmt(),
		-- thisModule.emptyFinallyBlock(),
		-- thisModule.emptyfinalizeMethod(),
		-- thisModule.doNotThrowExceptionInFinally(),
		-- thisModule.finalizeShouldBeProtected(),
		-- thisModule.avoidDollarSigns(),
		-- thisModule.avoidThreadGroup(),
		-- thisModule.dontCallThreadRun(),
		-- thisModule.returnEmptyArrayRatherThanNull(),
		-- thisModule.replaceVectorToList()
		-- thisModule.unusedPrivateMethod ()
		-- thisModule.avoidStringBufferField()
		-- thisModule.avoidThrowingNewInstanceOfSameException(),
	
130
131
};

Raphael PAGE's avatar
Raphael PAGE committed
132
133

-- creates a new Measure when String.valueOf is called to append its argument to a string
134
rule MeasureUselessStringValueOf(method : java!MethodInvocation) {
Raphael PAGE's avatar
Raphael PAGE committed
135
136
137
138
139
140
141
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Useless string value of',
142
			shortDescription <- 'No need to call String.valueOf to append to a string; just use the valueOf() argument directly.'		
Raphael PAGE's avatar
Raphael PAGE committed
143
		),
144
145
146
		measurement: smm!DirectMeasurement (			
			error<- 'The class '+ method.originalCompilationUnit.name + ' violates the rule useless string value of.'
			)
Raphael PAGE's avatar
Raphael PAGE committed
147
148
149
150
151
152
	do {
		noc; 
	}
}

------------------------------------------------------------------------------------------
153

Yannis LE BARS's avatar
Yannis LE BARS committed
154
-- A Measure instance if the class violates the rule 'AvoidDollarSigns'.
155
rule MesureAvoidDollarSigns(node : java!ASTNode) {
Yannis LE BARS's avatar
Yannis LE BARS committed
156
157
158
159
160
161
162
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'AvoidDollarSigns',
163
			shortDescription <- 'Avoid using dollar signs in variable/method/class/interface names.'
Yannis LE BARS's avatar
Yannis LE BARS committed
164
165
166
167
168
169
170
171
172
		),
		measurement: smm!DirectMeasurement (
			error <- node.name + ' has dollar in ' + node.originalCompilationUnit.name
		)
	do {
		noc; 
	}
}

173
174


Yannis LE BARS's avatar
Yannis LE BARS committed
175
-- A Measure instance if the class violates the rule 'ShortMethodName'.
176
rule MesureShortMethodName(method : java!MethodDeclaration) {
Yannis LE BARS's avatar
Yannis LE BARS committed
177
178
179
180
181
182
183
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'ShortMethodName',
184
			shortDescription <- 'Method names names that are very short are not helpful to the reader.'
Yannis LE BARS's avatar
Yannis LE BARS committed
185
186
		),
		measurement: smm!DirectMeasurement (
187
			error <- method.name + ' is too short in ' + method.originalCompilationUnit.name
Yannis LE BARS's avatar
Yannis LE BARS committed
188
189
190
191
192
		)
	do {
		noc; 
	}
}
Raphael PAGE's avatar
Raphael PAGE committed
193

194

Marion HUNAULT's avatar
Marion HUNAULT committed
195
-- A Measure instance if the class violates the rule 'ShortClassName'.
196
rule MesureShortClassName(class : java!ClassDeclaration) {
Marion HUNAULT's avatar
Marion HUNAULT committed
197
198
199
200
201
202
203
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'ShortClassName',
204
			shortDescription <- 'Short Classnames with fewer than e.g. five characters are not recommended.'
Marion HUNAULT's avatar
Marion HUNAULT committed
205
206
207
208
209
210
211
212
213
		),
		measurement: smm!DirectMeasurement (
			error <- 'The Class ' + class.name + ' is too short.'
		)
	do {
		noc; 
	}
}

214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
-- A Measure instance if the variable violates the rule 'ShortVariableName'.
rule MesureShortVariableName(variable : java!VariableDeclaration) {
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'ShortVariableName',
			shortDescription <- 'Short Variable names with fewer than e.g. three characters are not recommended.'
		),
		measurement: smm!DirectMeasurement (
			error <- 'The Variable ' + variable.name + ' is too short.'
		)
	do {
		noc; 
	}
}


234

Raphael's avatar
Raphael committed
235
-- creates a new Measure when Thread.run() is used instead of Thread.start()
236
rule MeasureDontCallThreadRun(method : java!MethodInvocation) {
Raphael's avatar
Raphael committed
237
238
239
240
241
242
243
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Don t call Thread.run()',
244
			shortDescription <- 'Explicitly calling Thread.run() method will execute in the caller s thread of control. Instead, call Thread.start() for the intended behavior.'		
Raphael's avatar
Raphael committed
245
		),
246
247
		measurement: smm!DirectMeasurement (			
			error<-'The class '+ method.originalCompilationUnit.name + ' violates the rule don t call Thread.run().'
Raphael's avatar
Raphael committed
248
		)
Raphael's avatar
Raphael committed
249
250
251
252
253
	do {
		noc; 
	}
}

254

Astlo's avatar
Astlo committed
255
-- A Measure instance if the class violates the rule 'TooManyFields'.
256
rule MesureTooManyFields(class : java!ClassDeclaration) {
Gerson Sunyé's avatar
Gerson Sunyé committed
257
258
259
260
261
262
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
Astlo's avatar
Astlo committed
263
			name <- 'TooManyFields',
264
			shortDescription <- 'Classes that have too many fields can become unwieldy and could be redesigned to have fewer field.'
Gerson Sunyé's avatar
Gerson Sunyé committed
265
266
		),
		measurement: smm!DirectMeasurement (
Astlo's avatar
Astlo committed
267
			error <- class.originalCompilationUnit.name + ' have too many fields'
Gerson Sunyé's avatar
Gerson Sunyé committed
268
		)
Raphael's avatar
Raphael committed
269
270
271
272
273
	do {
		noc; 
	}
}

274
275
276

-- creates a new Measure when the parameter of String.indexOf(char) is not of type char when checking for the index of a single character
rule MeasureUseIndexOfChar(method : java!MethodInvocation) {
Raphael's avatar
Raphael committed
277
278
279
280
281
282
283
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Use index of char',
284
			shortDescription <- 'Use String.indexOf(char) when checking for the index of a single character; it executes faster.'		
Raphael's avatar
Raphael committed
285
		),
286
287
		measurement: smm!DirectMeasurement (			
			error<- 'The class '+ method.originalCompilationUnit.name + ' violates the rule index of char.'
Raphael's avatar
Raphael committed
288
289
290
291
292
		)
	do {
		noc; 
	}
}
Gerson Sunyé's avatar
Gerson Sunyé committed
293

Raphael PAGE's avatar
Raphael PAGE committed
294
------------------------------------------------------------------------------------------
295

Gerson Sunyé's avatar
Gerson Sunyé committed
296
297
298
299
300
301
302
303
304
305
rule numberOfClasses() {
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Number of Classes'
		),
		measurement: smm!DirectMeasurement (
306
			value <- java!ClassDeclaration.allInstances() -> reject(each | each.isProxy()) -> size()
Gerson Sunyé's avatar
Gerson Sunyé committed
307
		)
Gerson Sunyé's avatar
Gerson Sunyé committed
308

Gerson Sunyé's avatar
Gerson Sunyé committed
309
310
311
312
	do {
		noc; 
	}
}
313

314
315

-- Rule that creates an instance of Measure for the switch statement with too few branches passed in parameter  
316
rule MeasureTooFewBranchesForASwitchStatement(switchStatement: java!SwitchStatement) {
317
318
319
320
321
322
	to
		om: smm!ObservedMeasure (
			measure <- tooFewBranchesForASwitchStatement,
			measurements <- measurement
		),
		tooFewBranchesForASwitchStatement: smm!DimensionalMeasure (
323
			name <- 'TooFewBranchesForASwitchStatement',
324
			shortDescription <- 'Switch statements are intended to be used to support complex branching behaviour. Using a switch for only a few cases is ill-advised, since switches are not as easy to understand as if-then statements. In these cases use the if-then statement to increase code readability.'
325
326
		),
		measurement: smm!DirectMeasurement (
327
			error <- 'Too few branches for SwitchStatement in Class : ' + switchStatement.originalCompilationUnit.name,
328
329
330
331
332
333
			value <- thisModule.nbBranchesOfASwitchStatement(switchStatement)
		)
	do {
		tooFewBranchesForASwitchStatement; 
	}
}
334

335
--------------------------------------------- ShortInstantiation ---------------------------------------------
336
-- A Measure instance if the class violates the rule 'ShortInstantiation'.
337
rule MeasureShortInstantiation(variable : java!CompilationUnit) {
338
339
340
341
342
343
344
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'ShortInstantiation',
345
			shortDescription <- 'Calling new Short() causes memory allocation that can be avoided by the static Short.valueOf(). It makes use of an internal cache that recycles earlier instances making it more memory efficient. Note that new Short() is deprecated since JDK 9 for that reason.'		
346
		),
347
348
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ variable.name + ' an instantiation of Short must be Short.ValueOf().'
349
350
351
352
353
354
355
		)
		
	do {
		noc; 
	}
}

356
357

--------------------------------------------- LongInstantiation ---------------------------------------------
358
-- A Measure instance if the class violates the rule 'LongInstantiation'.
359
rule MeasureLongInstantiation(variable : java!CompilationUnit) {
360
361
362
363
364
365
366
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'LongInstantiation',
367
			shortDescription <- 'Calling new Long() causes memory allocation that can be avoided by the static Long.valueOf(). It makes use of an internal cache that recycles earlier instances making it more memory efficient. Note that new Long() is deprecated since JDK 9 for that reason.'		
368
		),
369
370
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ variable.name + ' an instantiation of Long must be Long.ValueOf().'
371
372
373
374
375
376
377
		)
		
	do {
		noc; 
	}
}

378
--------------------------------------------- DoNotExtendJavaLangThrowable  ---------------------------------------------
379
-- A Measure instance if the class violates the rule DoNotExtendJavaLangThrowable.
380
rule MeasureDoNotExtendJavaLangThrowable(variable : java!ClassDeclaration) {
381
382
383
384
385
386
387
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'DoNotExtendJavaLangThrowable ',
388
389
			shortDescription <- 'Extend Exception or RuntimeException instead of Throwable.'
		
390
		),
391
392
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ variable.name + ' should not extend Throwable but RuntimeException or Exception .'
393
394
395
396
397
398
		)
		
	do {
		noc; 
	}
}
399
	
400
-- Returns the number of branches in the switch statement passed in parameter
401
402
403
helper def: nbBranchesOfASwitchStatement(switchStatement:java!SwitchStatement) : Integer =
	switchStatement.statements->select(each | each.oclIsTypeOf(java!SwitchCase)).size()
;
404

405
-- Returns the number of Fields in Class
406
helper def: numberFieldsInClasse(s:java!ClassDeclaration) : Integer =
407
	-- Return the number of FieldDeclaration in a class.
408
	s.bodyDeclarations-> select(r | r.oclIsTypeOf(java!FieldDeclaration))->size();
Martin's avatar
Martin committed
409

410
-- Returns the number of breaks of the switch statement passed in parameter
411
412
413
helper def: nbBreakStatementOfASwitchStatement(ss:java!SwitchStatement) : Integer =
    ss.statements->select(each | each.oclIsTypeOf(java!BreakStatement)).size()
;
414
415

-- Returns the number of expressions of the switch statement passed in parameter
416
417
418
419
420
421
422
423
424
425
helper def: nbExpressionsStatementOfASwitchStatement(ss:java!SwitchStatement) : Integer =
    ss.statements->select(each | each.oclIsTypeOf(java!ExpressionStatement)).size()
;

-- Returns the number of intentional fall-through (empty switch cases) of a switchStatement
helper def: nbIntentionalFallThroughOfASwitchStatement(ss:java!SwitchStatement) : Integer =
    thisModule.nbBranchesOfASwitchStatement(ss) - thisModule.nbExpressionsStatementOfASwitchStatement(ss)
;

-- Creates an instance of Measure for the switch statement missing one or more break statements
426
427
428
429
430
431
432
433
434
-- To test, use input model : missing-break-in-switch.xmi
rule createMeasureForMissingBreakInSwitch(ss: java!SwitchStatement) {
	to
		om: smm!ObservedMeasure (
			measure <- missingBreakInSwitch,
			measurements <- measurement
		),
		missingBreakInSwitch: smm!DimensionalMeasure (
			name <- 'Missing break in Switch',
435
			shortDescription <- 'Switch statements without break or return statements for each case option may indicate problematic behaviour. Empty cases are ignored as these indicate an intentional fall-through.'
436
437
		),
		measurement: smm!DirectMeasurement (
438
			error <- 'Missing breaks in Switch in Class : ' + ss.originalCompilationUnit.name + '',
439
			-- Indicates the number of breaks missing in the switch statement
440
			value <- (thisModule.nbBranchesOfASwitchStatement(ss) - thisModule.nbIntentionalFallThroughOfASwitchStatement(ss)) - thisModule.nbBreakStatementOfASwitchStatement(ss)
441
442
443
444
445
446
		)
	do {
		missingBreakInSwitch; 
	}
}

Martin's avatar
Martin committed
447
-- A Measure instance if the class violates the rule 'TooManyMethods'.
448
rule MesureTooManyMethods(class : java!ClassDeclaration) {
Martin's avatar
Martin committed
449
450
451
452
453
454
455
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'TooManyMethods',
456
			shortDescription <- 'A class with too many methods is probably a good suspect for refactoring, in order to reduce its complexity and find a way to have more fine grained objects.'
Martin's avatar
Martin committed
457
458
		),
		measurement: smm!DirectMeasurement (
Martin ARS's avatar
Martin ARS committed
459
			error <- class.originalCompilationUnit.name + ' has too many methods'
Martin's avatar
Martin committed
460
461
462
463
464
465
		)

	do {
		noc; 
	}
}
Martin ARS's avatar
Martin ARS committed
466

467
-- A Measure instance if the class violates the rule ReturnFromFinallyBlock.
468
rule MesureReturnFromFinallyBlock(method : java!MethodDeclaration) {
469
470
471
472
473
474
475
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'returnFromFinallyBlock',
476
			shortDescription <- 'Avoid returning from a finally block, this can discard exceptions.'
477
478
		),
		measurement: smm!DirectMeasurement (
479
			error <- 'The method ' + method.name + ' in the class ' + method.originalCompilationUnit.name + ' has a return statement in a finally block.'
480
481
482
483
484
		)
	do {
		noc; 
	}
}
Martin ARS's avatar
Martin ARS committed
485
486

-- A Measure instance if the class violates the rule 'TooManyStaticImports'.
487
rule MesureTooManyStaticImports(class : java!CompilationUnit) {
Martin ARS's avatar
Martin ARS committed
488
489
490
491
492
493
494
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'TooManyStaticImports',
495
			shortDescription <- 'If you overuse the static import feature, it can make your program unreadable and unmaintainable, polluting its namespace with all the static members you import. Readers of your code (including you, a few months after you wrote it) will not know which class a static member comes from (Sun 1.5 Language Guide).'
Martin ARS's avatar
Martin ARS committed
496
497
498
499
500
501
502
		),
		measurement: smm!DirectMeasurement (
			error <- class.name + ' has too many static imports'
		)
	do {
		noc; 
	}
Raphael's avatar
Raphael committed
503
504
}

Raphael PAGE's avatar
Raphael PAGE committed
505
-- creates a new Measure when the method printStackTrace is used
506
rule MeasureAvoidPrintStackTrace(method : java!MethodInvocation) {
Raphael PAGE's avatar
Raphael PAGE committed
507
508
509
510
511
512
513
		to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Avoid print stack trace',
514
			shortDescription <- 'Avoid printStackTrace(); use a logger call instead.'		
Raphael PAGE's avatar
Raphael PAGE committed
515
		),
516
517
		measurement: smm!DirectMeasurement (			
			error<- 'The class '+ method.originalCompilationUnit.name + ' violates the rule avoid print stack trace.'
Raphael PAGE's avatar
Raphael PAGE committed
518
519
520
521
522
		)
	do {
		noc; 
	}
}
Raphael's avatar
Raphael committed
523
524

-- creates a new Measure when Thread.run() is used instead of Thread.start()
525
rule measureAvoidThreadGroup(variable : java!VariableDeclarationFragment) {
Raphael's avatar
Raphael committed
526
527
528
529
530
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
531
		noc: smm!DimensionalMeasure (
Raphael's avatar
Raphael committed
532
			name <- 'Avoid Thread Group',
533
			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.'		
Raphael's avatar
Raphael committed
534
		),
535
536
		measurement: smm!DirectMeasurement (			
			error<-'The class '+ variable.originalCompilationUnit.name + ' violates the rule avoid thread group.'
Raphael's avatar
Raphael committed
537
538
		)
		
Martin ARS's avatar
Martin ARS committed
539
540
541
	do {
		noc; 
	}
Raphael PAGE's avatar
Raphael PAGE committed
542
}
543

544
545
546
--------------------------------------------- AvoidThrowingNewInstanceOfSameException ---------------------------------------------
-- A Measure instance if the class violates the rule 'AvoidThrowingNewInstanceOfSameException'.
rule MeasureAvoidThrowingNewInstanceOfSameException(catch : java!CatchClause) {
547
548
549
550
551
552
553
    to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'AvoidThrowingNewInstanceOfSameException',
554
			shortDescription <- 'Catch blocks that merely rethrow a caught exception wrapped inside a new instance of the same type only add to code size and runtime complexity.'		
555
		),
556
557
		measurement: smm!DirectMeasurement (			
			error <-'The class '+ catch.originalCompilationUnit.name + ' has a method that rethrows a caught exception wrapped inside a new instance of the same type.'
558
559
560
561
562
563
		)
	do {
		noc; 
	}
}

564
--------------------------------------------- ReturnEmptyArrayRatherThanNull ---------------------------------------------	
565
-- creates a new Measure when a method returns an empty method rather than null
566
rule MesureReturnEmptyArrayRatherThanNull(method : java!ReturnStatement) {
567
568
569
570
571
572
573
    to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'ReturnEmptyArrayRatherThanNull',
574
			shortDescription <- 'For any method that returns an array, it is a better to return an empty array rather than a null reference.'
575
576
		),
		measurement: smm!DirectMeasurement (
577
			error <- 'A method in the class ' + method.originalCompilationUnit.name + ' returns null instead of an empty array.'
578
579
580
581
582
		)
	do {
		noc; 
	}
}
583

584
--------------------------------------------- ExcessiveParameterList ---------------------------------------------
585
-- creates a new Measure when a method has more than 10 parameters
586
rule MesureExcessiveParameterList(method : java!MethodDeclaration) {
587
588
589
590
591
592
593
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'ExcessiveParameterList',
594
			shortDescription <- 'Methods with numerous parameters are a challenge to maintain, especially if most of them share the same datatype.'		
595
		),
596
597
		measurement: smm!DirectMeasurement (			
			error<-'The method '+ method.name + ' in the class ' + method.originalCompilationUnit.name + ' has an excessive parameter list.'
598
599
600
601
602
603
		)
	do {
		noc; 
	}
}

604
-- A Measure instance if the class violates the rule 'AvoidFieldNameMatchingMethodName'.
605
rule MesureAvoidFieldNameMatchingMethodName(class : java!ClassDeclaration, method : java!MethodDeclaration) {
606
607
608
609
610
611
612
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'AvoidFieldNameMatchingMethodName',
613
			shortDescription <- 'It can be confusing to have a field name with the same name as a method. While this is permitted, having information (field) and actions (method) is not clear naming. Developers versed in Smalltalk often prefer this approach as the methods denote accessor methods.'
614
615
		),
		measurement: smm!DirectMeasurement (
616
			error <- 'In the ' + class.name + ' class you have an field and an method with the same name : '+ method.name
617
618
619
620
621
		)
	do {
		noc; 
	}
}
622
623
624
625
626
627
628
629
630
631

-- Creates a measure instance when rule 'UseNotifyAllInsteadOfNotify' is violated
rule MeasureUseNotifyAllInsteadOfNotify(method: java!MethodInvocation) {
	to
		om: smm!ObservedMeasure (
			measure <- useNotifyAllInsteadOfNotify,
			measurements <- measurement
		),
		useNotifyAllInsteadOfNotify: smm!DimensionalMeasure (
			name <- 'UseNotifyAllInsteadOfNotify',
632
			shortDescription <- 'Thread.notify() awakens a thread monitoring the object. If more than one thread is monitoring, then only one is chosen. The thread chosen is arbitrary; thus its usually safer to call notifyAll() instead.'
633
634
		),
		measurement: smm!DirectMeasurement (
635
			error <- 'Used notify() instead of notifyAll() in Class : ' + method.originalCompilationUnit.name
636
637
638
639
640
		)
	do {
		useNotifyAllInsteadOfNotify; 
	}
}
Roxane MARECHAL's avatar
Roxane MARECHAL committed
641

642
--- Creates a measure instance for each element that violates the rule : CommentRequired
643
rule MeasureCommentRequired(element: java!BodyDeclaration, violatedProperties: Set(String)) {
Roxane MARECHAL's avatar
Roxane MARECHAL committed
644
645
646
647
648
649
650
	to
		om: smm!ObservedMeasure (
			measure <- commentRequired,
			measurements <- measurement
		),
		commentRequired: smm!DimensionalMeasure (
			name <- 'CommentRequired',
651
			shortDescription <- 'Denotes whether comments are required (or unwanted) for specific language elements.'
Roxane MARECHAL's avatar
Roxane MARECHAL committed
652
653
		),
		measurement: smm!DirectMeasurement (
654
			error <- 'Violated the properties  ' + violatedProperties + ' in Class: ' + element.originalCompilationUnit.name + ' -> ' + element.oclType().name + ': ' + element.modifier.visibility + ' ' + element.getBodyDeclarationName()
Roxane MARECHAL's avatar
Roxane MARECHAL committed
655
656
657
		)
		do {
		commentRequired; 
658
		}
Roxane MARECHAL's avatar
Roxane MARECHAL committed
659
660
}

Ronan GUEGUEN's avatar
Ronan GUEGUEN committed
661
662
663
664
665
666
667
668
rule MeasureCommentContent(element: Sequence(String)){
	to
		om: smm!ObservedMeasure (
			measure <- commentContent,
			measurements <- measurement
		),
		commentContent: smm!DimensionalMeasure (
			name <- 'CommentContent',
669
			shortDescription <- 'A rule for the politically correct… we don’t want to offend anyone.'
Ronan GUEGUEN's avatar
Ronan GUEGUEN committed
670
671
		),
		measurement: smm!DirectMeasurement (
672
			error <- 'The words ' + element +' were found in a comment '	
Ronan GUEGUEN's avatar
Ronan GUEGUEN committed
673
674
		)
		do {
675
676
			commentContent;
		}
Ronan GUEGUEN's avatar
Ronan GUEGUEN committed
677
678
679
	
}

680
--- Returns the name of a BodyDeclaration
681
682
helper context java!BodyDeclaration def: getBodyDeclarationName() : String =
    self.name;
683

684
685
686
--- In FielDeclaration, the attribute 'name' is NULL, this information is contained in "fragments" instead
helper context java!FieldDeclaration def: getBodyDeclarationName() : String =
    self.fragments.first().name;
Roxane MARECHAL's avatar
Roxane MARECHAL committed
687

688
--- Returns the AnnotationTypeDeclaration corresponding to the given BodyDeclaration
Roxane MARECHAL's avatar
Roxane MARECHAL committed
689
-- This is necessary because BodyDeclaration.annotations returns Sequence(!IN<unamed>)
690
691
692
693
694
695
696
697
698
helper def: getAnnotationTypeDeclarationsFromBodyDeclaration(elem: java!BodyDeclaration): Set(java!AnnotationTypeDeclaration) =
	java!AnnotationTypeDeclaration.allInstances()
	->select(annotTypeDec | 
		annotTypeDec.usagesInTypeAccess->exists(usage | 
			(usage.eContainer().eContainer().name = elem.name)
			.and(usage.eContainer().eContainer().modifier.visibility = elem.modifier.visibility)
			.and(usage.eContainer().eContainer().originalCompilationUnit.name = elem.originalCompilationUnit.name))
	)
;
Glenn PLOUHINEC's avatar
Glenn PLOUHINEC committed
699

700
-- A Measure instance if the class violates the rule 'SuspiciousEqualsMethodName'
701
rule MeasureSuspiciousEqualsMethodName(method : java!MethodDeclaration) {
702
703
704
705
706
707
708
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Suspicious Equals Method Name',
709
			shortDescription <- 'The method name and parameter number are suspiciously close to equals(Object), which can denote an intention to override the equals(Object) method.'
710
711
		),
		measurement: smm!DirectMeasurement (
712
				error <- 'The class ' + method.originalCompilationUnit.name + ' has a suspicious \'equals\' method name : ' + method.toString()
713
714
		)
	do {
715
		noc;
716
717
718
	}
}

Glenn PLOUHINEC's avatar
Glenn PLOUHINEC committed
719
-- A Measure instance if the class violates the rule 'AvoidUsingShortType'
720
rule MeasureAvoidUsingShortType(typeShort : java!VariableDeclarationStatement) {
Glenn PLOUHINEC's avatar
Glenn PLOUHINEC committed
721
722
723
724
725
726
727
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Avoid using short type',
728
729
730
731
732
			shortDescription <- 'Java uses the \'short\' type to reduce memory usage, not to optimize calculation.' 
								+ ' In fact, the JVM does not have any arithmetic capabilities for the short type:' 
								+ ' the JVM must convert the short into an int, do the proper calculation and convert' 
								+ ' the int back to a short. Thus any storage gains found through use of the \'short\' type' 
								+ ' may be offset by adverse impacts on performance.'
Glenn PLOUHINEC's avatar
Glenn PLOUHINEC committed
733
734
		),
		measurement: smm!DirectMeasurement (
735
				error <- 'The class ' + typeShort.originalCompilationUnit.name + ' has \'short\' type variable.'
Glenn PLOUHINEC's avatar
Glenn PLOUHINEC committed
736
737
		)
	do {
738
		noc;
Glenn PLOUHINEC's avatar
Glenn PLOUHINEC committed
739
740
	}
}
741
742

-- A Measure instance if the class violates the rule 'EmptyStatementBlock'
743
rule MeasureEmptyStatementBlock(block : java!Block) {
744
745
746
747
748
749
750
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Empty Statement Block',
751
			shortDescription <- 'Empty block statements serve no purpose and should be removed.'
752
753
		),
		measurement: smm!DirectMeasurement (
754
				error <- 'The class ' + block.originalCompilationUnit.name + ' has an empty statement block.'
755
756
		)
	do {
757
		noc;
758
759
	}
}
760

761
--------------------------------------------- DoNotExtendJavaLangError  ---------------------------------------------
762
-- A Measure instance if the class violates the rule DoNotExtendJavaLangError.
763
rule MeasureDoNotExtendJavaLangError(variable : java!ClassDeclaration) {
764
765
766
767
768
769
770
771
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'DoNotExtendJavaLangError ',
			shortDescription <- 'Errors are system exceptions. Do not extend them.'
772
		
773
		),
774
775
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ variable.name + ' Do not extend Error, Errors are system exceptions.'
776
777
778
779
780
781
		)
		
	do {
		noc; 
	}
}
782

783
--------------------------------------------- MeasureFinalFieldCouldBeStatic  ---------------------------------------------
784
-- A Measure instance if the class violates the rule MeasureFinalFieldCouldBeStatic.
785
rule MeasureFinalFieldCouldBeStatic(field : java!FieldDeclaration) {
786
787
788
789
790
791
792
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'FinalFieldCouldBeStatic',
793
794
			shortDescription <- 'If a final field is assigned to a compile-time constant, it could be made static, thus saving overhead in each object at runtime.'
		
795
		),
796
797
		measurement: smm!DirectMeasurement (			
			error<-'The field '+ field.fragments->collect(i | i.name)->first() + ' could be static in the class '  + field.originalCompilationUnit.name +'.'
798
799
800
801
802
803
		)
		
	do {
		noc; 
	}
}
Louis QUESTEL's avatar
Louis QUESTEL committed
804

805
806

--------------------------------------------- MeasureExtendsObject  ---------------------------------------------
Louis QUESTEL's avatar
Louis QUESTEL committed
807
-- A Measure instance if the class violates the rule ExtendsObject.
808
rule MeasureExtendsObject(variable : java!ClassDeclaration) {
Louis QUESTEL's avatar
Louis QUESTEL committed
809
810
811
812
813
814
815
816
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'ExtendsObject',
			shortDescription <- 'No need to explicitly extend Object.'
817
		
Louis QUESTEL's avatar
Louis QUESTEL committed
818
		),
819
820
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ variable.name + ' No need to explicitly extend Object.'
Louis QUESTEL's avatar
Louis QUESTEL committed
821
822
823
824
825
826
		)
		
	do {
		noc; 
	}
}
827

828
--------------------------------------------- SwitchDensity  ---------------------------------------------
829
-- A Measure instance if the class violates the rule SwitchDensity.
830
rule MeasureSwitchDensity(switch : java!SwitchStatement) {
831
832
833
834
835
836
837
	
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
838
			
839
840
			name <- 'SwitchDensity ',
			shortDescription <- 'Statement to label ratio is too high (> 10)'
841
		
842
		),
843
844
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ switch.originalCompilationUnit.name + ' a switch case contains too many statements.'
845
846
847
848
		)
	do {
		noc; 
	}
849
850
}	 
--------------------------------------------- SignatureDeclareThrowsException  ---------------------------------------------
851
-- A Measure instance if the class violates the rule SignatureDeclareThrowsException.
852
rule MeasureSignatureDeclareThrowsException(class : java!ClassDeclaration) {
853
854
855
856
857
858
859
	
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
860
			
861
			name <- 'SignatureDeclareThrowsException ',
862
863
			shortDescription <- 'A method/constructor should not explicitly throw the generic java.lang.Exception'
		
864
		),
865
866
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ class.name + ' a method/constructor explicitly throws the generic java.lang.Exception.'
867
868
869
870
		)
	do {
		noc; 
	}
871
}	 
872

873
--------------------------------------------- UnnecessaryReturn  ---------------------------------------------
874
-- A Measure instance if the class violates the rule UnnecessaryReturn.
875
rule MeasureUnnecessaryReturn(state : java!ReturnStatement) {
876
877
878
879
880
881
882
	
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
883
			
884
885
			name <- 'UnnecessaryReturn ',
			shortDescription <- 'Avoid the use of unnecessary return statements.'
886
		
887
		),
888
889
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ state.originalCompilationUnit.name + ' an unnecessary return was used.'
890
891
892
893
		)
	do {
		noc; 
	}
894
895
}

896
897

--------------------------------------------- MeasureCompareObjectsWithEquals  ---------------------------------------------
898
--A measure instance if the class violates the rule MeasureCompareObjectsWithEquals.
899
rule MeasureCompareObjectsWithEquals(expression : java!InfixExpression) {
900
901
902
903
904
905
906
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'CompareObjectsWithEquals',
907
908
			shortDescription <- 'Use equals() to compare object references; avoid comparing them with ==.'
		
909
		),
910
911
		measurement: smm!DirectMeasurement (			
			error<-'The Class '+ expression.originalCompilationUnit.name + ' is using == instead of equals() to compare objects.'
912
913
914
915
916
		)
		
	do {
		noc; 
	}
917
918
}	 

919

920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
--------------------------------------------- UseAssertTrueInsteadOfAssertEquals  ---------------------------------------------
-- A Measure instance if the class violates the rule UseAssertTrueInsteadOfAssertEquals.
rule MesureUseAssertTrueInsteadOfAssertEquals(class : java!MethodInvocation) {
	
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'UseAssertTrueInsteadOfAssertEquals',
			shortDescription <- 'Use AssertTrue instead of AssertEquals' 
		),
		measurement: smm!DirectMeasurement (
			error <- class.originalCompilationUnit.name + ' Use AssertTrue instead of AssertEquals ' 
		)

	do {
		noc; 
	}
}
941
942
943
944
945
946
947
948
949
--------------------------------------------- AvoidRethrowingException  ---------------------------------------------
 --A Measure instance if the class violates the rule AvoidRethrowingException.
rule MeasureAvoidRethrowingException(statement : java!TryStatement) {
 		to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
950
			
951
952
			name <- 'AvoidRethrowingException ',
			shortDescription <- 'Avoid merely rethrowing an exception.'
953
		
954
		),
955
956
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ statement.originalCompilationUnit.name + ' an exception was caught and merely rethrown.'
957
958
959
960
		)
	do {
		noc; 
	}
961
962
963
}	 
	
--------------------------------------------- IntegerInstantiation ---------------------------------------------
Alexis Pineau's avatar
Alexis Pineau committed
964
-- A Measure instance if the class violates the rule 'IntegerInstantiation'.
965
rule MeasureIntegerInstantiation(variable : java!CompilationUnit) {
Alexis Pineau's avatar
Alexis Pineau committed
966
967
968
969
970
971
972
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'IntegerInstantiation',
973
			shortDescription <- 'Calling new Integer() causes memory allocation that can be avoided by the static Integer.valueOf(). It makes use of an internal cache that recycles earlier instances making it more memory efficient. Note that new Integer() is deprecated since JDK 9 for that reason.'		
Alexis Pineau's avatar
Alexis Pineau committed
974
		),
975
976
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ variable.name + ' an instantiation of Integer must be Integer.ValueOf().'
Alexis Pineau's avatar
Alexis Pineau committed
977
978
979
980
981
982
983
		)
		
	do {
		noc; 
	}
}

984
--------------------------------------------- LongVariable  ---------------------------------------------
985
-- A Measure instance if the variable violates the rule LongVariable.
986
rule MeasureLongVariable(variable : java!VariableDeclarationFragment) {
987
988
989
990
991
992
993
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'LongVariable',
994
			shortDescription <- ': Fields, formal arguments, or local variable names that are too long can make the code difficult '
995
996
		),
		measurement: smm!DirectMeasurement (
997
			error <- variable.name + ' is too Long ' 
998
999
1000
1001
1002
1003
		)
	do {
		noc; 
	}
}

1004
--------------------------------------------- AvoidCallingFinalize  ---------------------------------------------
1005
-- A Measure instance if the class violates the rule LongVariable.
1006
rule MeasureAvoidCallingFinalize(methode : java!MethodInvocation) {
1007
1008
1009
1010
1011
1012
1013
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'AvoidCallingFinalize',
1014
			shortDescription <- ': The method Object.finalize() is called by the garbage collector on an object when garbage collect... '
1015
1016
		),
		measurement: smm!DirectMeasurement (
1017
			error <- 'finalize() is called in class' + methode.originalCompilationUnit.name 
1018
1019
1020
1021
1022
1023
		)
	do {
		noc; 
	}
}

1024
--------------------------------------------- AvoidStringBufferField  ---------------------------------------------
1025
-- A Measure instance if the class violates AvoidStringBufferField .
1026
rule MeasureAvoidStringBufferField(declaration : java!VariableDeclaration) {
1027
1028
1029
1030
1031
1032
1033
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'AvoidStringBufferField',
1034
			shortDescription <- ': StringBuffers/StringBuilders can grow considerably, and so may become a source of memory leaksif ...'
1035
1036
		),
		measurement: smm!DirectMeasurement (
1037
			error <- 'AvoidStringBufferField is detected in ' + declaration.originalCompilationUnit.name 
1038
1039
1040
1041
1042
1043
1044
1045
		)
	do {
		noc; 
	}
}

--------------------- AvoidThrowingNullPointerException----------------------------------
-- A Measure instance if the class violates AvoidThrowingNullPointerException .
1046
rule MeasureAvoidThrowingNullPointerException(c : java!ClassInstanceCreation) {
1047
1048
1049
1050
1051
1052
1053
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'AvoidThrowingNullPointerException',
1054
			shortDescription <- 'Avoid throwing NullPointerExceptions manually. These are confusing because most people will assume that the virtual machine threw it'
1055
1056
		),
		measurement: smm!DirectMeasurement (
1057
			error <- 'AvoidThrowingNullPointerException is detected in ' + c.originalCompilationUnit.name
1058
1059
1060
1061
1062
1063
		)
	do {
		noc; 
	}
}

1064

1065
1066
--------------------- EmptyTryBlock----------------------------------
--A measure instance if the class violates the rule EmptyTryBlock.
1067
rule MeasureEmptyTryBlock(t : java!TryStatement) {
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'EmptyTryBlock',
			shortDescription <- ': Avoid empty try blocks - what s the point?'
		),
		measurement: smm!DirectMeasurement (
			error <- 'EmptyTryBlock is detected in ' + t.originalCompilationUnit.name
		)
	do {
		noc; 
	}
}

---------------------EmptyWhileStmt----------------------------------
--A measure instance if the class violates the rule EmptyWhileStmt.
1087
rule MeasureEmptyWhileStmt(w : java!TryStatement) {
1088
1089
1090
1091
1092
1093
1094
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'EmptyWhileStmt',
1095
			shortDescription <- ': Empty While Statement finds all instances where a while statement does nothing.'
1096
1097
1098
1099
1100
1101
1102
1103
1104
		),
		measurement: smm!DirectMeasurement (
			error <- 'EmptyWhileStmt is detected in  ' + w.originalCompilationUnit.name
		)
	do {
		noc; 
	}
}

1105
------------------------------------------- MeasureDontImportSun----------------------------------------------
1106
-- A Measure instance if the class violate the rule DontImportSun
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
rule MeasureDontImportSun(p : java!CompilationUnit) {
	to
		om: smm!ObservedMeasure (
				measure <- noc,
				measurements <- measurement
			),
			noc: smm!DimensionalMeasure (
				name <- 'DontImportSun',
				shortDescription <- ' : Avoid importing anything from the sun. packages.'
			),
			measurement: smm!DirectMeasurement (
				error <- ' Import Sun. , is detected in '+ p -> collect(i | i.name)
			)
	do {
		noc; 
	}
}

------------------------------------------- FinalizeShouldBeProtected----------------------------------------------
-- A Measure instance if the class violate the rule FinalizeShouldBeProtected
rule MesureFinalizeShouldBeProtected(m : java!MethodDeclaration) {
	to
		om: smm!ObservedMeasure (
				measure <- noc,
				measurements <- measurement
			),
			noc: smm!DimensionalMeasure (
				name <- 'FinalizeShouldBeProtected',
				shortDescription <- ' : When overriding the finalize(), the new method should be set as protected.  '
			),
			measurement: smm!DirectMeasurement (
				error <- 'Finalize is not protected in class : ' + m.originalCompilationUnit.name
			)
	do {
		noc; 
	}
}
Hanane HADJI's avatar
Hanane HADJI committed
1144
-----------------------EmptySwitchStatement---------------------------------------------
1145

Hanane HADJI's avatar
Hanane HADJI committed
1146
1147
-- A Measure instance if the class violates the rule 'EmptySwitchStatement'
rule MeasureEmptySwitchStatement(switchStatement: java!SwitchStatement) {
1148
1149
	to
		om: smm!ObservedMeasure (
E19C506H's avatar
E19C506H committed
1150
1151
1152
			measure <- noc,
			measurements <- measurement
		),
Hanane HADJI's avatar
Hanane HADJI committed
1153
1154
1155
		noc: smm!DimensionalMeasure (
			name <- 'Empty Switch Statement ',
			shortDescription <- 'Empty Switch statements serve no purpose and should be removed.'
E19C506H's avatar
E19C506H committed
1156
1157
		),
		measurement: smm!DirectMeasurement (
Hanane HADJI's avatar
Hanane HADJI committed
1158
				error <- 'EmptyswitchStatement is detected in ' + switchStatement.originalCompilationUnit.name
E19C506H's avatar
E19C506H committed
1159
		)
1160
	do {
1161
		noc;
1162
1163
	}
}
Hanane HADJI's avatar
Hanane HADJI committed
1164
--------------------------------EmptySynchronizedBlock---------------------------------------------
1165

Hanane HADJI's avatar
Hanane HADJI committed
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
-- A Measure instance if the class violates the rule 'EmptySynchronizedBlock'
rule MeasureEmptySynchronizedBlock(synchronizedBlock: java!SynchronizedStatement) {
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Empty Synchronized Block ',
			shortDescription <- 'Empty Synchronized Block serve no purpose and should be removed.'
		),
		measurement: smm!DirectMeasurement (
				error <- 'EmptySynchronizedBlock is detected in ' + synchronizedBlock.originalCompilationUnit.name
		)
	do {
		noc;
	}
}
--------------------- EmptyFinallyBlock----------------------------------
--A measure instance if the class violates the rule EmptyFinallyBlock.
rule MeasureEmptyFinallyBlock(finallyBlock : java!TryStatement) {
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'EmptyFinallyBlock',
			shortDescription <- ': Avoid empty Finally blocks - what s the point?'
		),
		measurement: smm!DirectMeasurement (
			error <- 'EmptyFinallyBlock is detected in ' + finallyBlock.originalCompilationUnit.name
		)
	do {
		noc; 
	}
}
1203

Hanane HADJI's avatar
Hanane HADJI committed
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
--------------------- EmptyFinalizer----------------------------------
--A measure instance if the class violates the rule EmptyFinalizer.
rule MeasureEmptyFinalizer(finalizeMethod : java!MethodDeclaration) {
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'EmptyFinalizer',
			shortDescription <- ': Avoid empty Finalizer  - what s the point?'
		),
		measurement: smm!DirectMeasurement (
			error <- 'EmptyFinalizer is detected in ' + finalizeMethod.originalCompilationUnit.name
		)
	do {
		noc; 
	}
}
1223
1224
1225
-------------------------------------------UseAssertSameInsteadOfAssertTrue----------------------------------------------
-- A Measure instance if the class violate the rule AssertSameInsteadOfAssertTrue
rule MesureUseAssertSameInsteadOfAssertTrue(tab :java!Package) {
1226
1227
	to
		om: smm!ObservedMeasure (
E19C506H's avatar
E19C506H committed
1228
1229
1230
			measure <- noc,
			measurements <- measurement
		),
1231
1232
1233
	noc: smm!DimensionalMeasure (
			name <- 'Use AssertSame Instead Of AssertTrue',
			shortDescription <- 'Use AssertSame Instead Of AssertTrue'
E19C506H's avatar
E19C506H committed
1234
1235
		),
		measurement: smm!DirectMeasurement (
1236
			error<- 'Use AssertSame Instead Of AssertTrue.'
E19C506H's avatar
E19C506H committed
1237
		)
1238
	do {
1239
		noc;
1240
1241
1242
	}
}

E19C506H's avatar
E19C506H committed
1243
-- A Measure instance if the class violates the rule AvoidNoPackageDeclaration.
E19C506H's avatar
E19C506H committed
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
rule MesureAvoidNoPackageDeclaration(class : java!CompilationUnit) {
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'AvoidNoPackageDeclaration',
			shortDescription <- 'you need to declare some package.'
		),
		measurement: smm!DirectMeasurement (
1255
			error <- class.name + ' class have no package declaration'
E19C506H's avatar
E19C506H committed
1256
		)
1257

E19C506H's avatar
E19C506H committed
1258
1259
1260
1261
	do {
		noc; 
	}
}