analysis.atl 39.2 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)
		)
}

E19C506H's avatar
E19C506H committed
31
32
helper def: allMeasures(project: java!Model): Set(smm!Measure) =
	Set{-- Example rule
33
34
		--
		thisModule.numberOfClasses(),
E19C506H's avatar
E19C506H committed
35
			-- Multithreading rules
36
37
		--
		thisModule.dontCallThreadRun(),
E19C506H's avatar
E19C506H committed
38
39
40
			thisModule.avoidThreadGroup(),
			thisModule.useNotifyAllInsteadOfNotify(),
			-- Code Style rules
41
42
		--
		thisModule.shortMethodName(),
E19C506H's avatar
E19C506H committed
43
44
45
46
47
48
49
50
			thisModule.tooManyStaticImports(),
			thisModule.avoidDollarSigns(),
			thisModule.shortClassName(),
			thisModule.extendsObject(),
			thisModule.unnecessaryReturn(),
			thisModule.longVariable(),
			
			thisModule.noPackageDeclaration(),
E19C506H's avatar
E19C506H committed
51
			thisModule.UnconditionalIfStatement(),
E19C506H's avatar
E19C506H committed
52
			thisModule.EmptyInitializer(),
E19C506H's avatar
E19C506H committed
53
			thisModule.ExcessiveClassLength(),
E19C506H's avatar
E19C506H committed
54
			thisModule.CloneMethodMustBePublic(),
E19C506H's avatar
E19C506H committed
55
			-- Design rules
56
57
		--
		thisModule.tooManyFields(),
E19C506H's avatar
E19C506H committed
58
59
60
61
62
			thisModule.tooManyMethods(),
			thisModule.returnFromFinallyBlock(),
			thisModule.longInstantiation(),
			thisModule.shortInstantiation(),
			--thisModule.returnEmptyArrayRatherThanNull(),
63
		thisModule.excessiveParameterList(),
E19C506H's avatar
E19C506H committed
64
65
66
67
			thisModule.finalFieldCouldBeStatic(),
			thisModule.signatureDeclareThrowsException(),
			thisModule.avoidThrowingNullPointerException(),
			-- Performance rules
68
		--
Raphael PAGE's avatar
Raphael PAGE committed
69
		thisModule.uselessStringValueOf(),
E19C506H's avatar
E19C506H committed
70
71
72
73
74
75
76
77
			thisModule.tooFewBranchesForASwitchStatement(),
			thisModule.useIndexOfChar(),
			thisModule.avoidPrintStackTrace(),
			thisModule.avoidUsingShortType(),
			thisModule.emptyStatementBlock(),
			thisModule.avoidRethrowingException(),
			thisModule.integerInstantiation(),
			-- Documentation rules
Roxane MARECHAL's avatar
Roxane MARECHAL committed
78
		--
Ronan GUEGUEN's avatar
Ronan GUEGUEN committed
79
		thisModule.commentContent(),
E19C506H's avatar
E19C506H committed
80
81
			thisModule.commentRequired(),
			-- Error prone rules
82
		--
83
		thisModule.missingBreakInSwitch(),
E19C506H's avatar
E19C506H committed
84
85
86
87
88
89
90
91
92
			thisModule.suspiciousEqualsMethodName(),
			thisModule.doNotExtendJavaLangThrowable(),
			thisModule.doNotExtendJavaLangError(),
			thisModule.compareObjectsWithEquals(),
			thisModule.avoidCallingFinalize(),
			thisModule.emptyTryBlock(),
			thisModule.emptyWhileStmt(),
			thisModule.dontImportSun(),
			--thisModule.finalizeShouldBeProtected(),
93
		
94
95
		-- Best practices rules
		thisModule.avoidThrowingNewInstanceOfSameException(),
E19C506H's avatar
E19C506H committed
96
97
			thisModule.switchDensity() --thisModule.avoidStringBufferField()
		};
Raphael PAGE's avatar
Raphael PAGE committed
98
99

-- creates a new Measure when String.valueOf is called to append its argument to a string
E19C506H's avatar
E19C506H committed
100
rule MeasureUselessStringValueOf(method: java!MethodInvocation) {
Raphael PAGE's avatar
Raphael PAGE committed
101
102
103
104
105
106
107
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Useless string value of',
E19C506H's avatar
E19C506H committed
108
109
			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
110
		),
E19C506H's avatar
E19C506H committed
111
112
113
114
		measurement: smm!DirectMeasurement (
			error <- 'The class ' + method.originalCompilationUnit.name + ' violates the'
					+ ' rule useless string value of.'
		)
Raphael PAGE's avatar
Raphael PAGE committed
115
116
117
118
119
120
	do {
		noc; 
	}
}

------------------------------------------------------------------------------------------
Yannis LE BARS's avatar
Yannis LE BARS committed
121
-- A Measure instance if the class violates the rule 'AvoidDollarSigns'.
E19C506H's avatar
E19C506H committed
122
rule MesureAvoidDollarSigns(node: java!ASTNode) {
Yannis LE BARS's avatar
Yannis LE BARS committed
123
124
125
126
127
128
129
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'AvoidDollarSigns',
E19C506H's avatar
E19C506H committed
130
131
			shortDescription <- 'Avoid using dollar signs in'
					+ ' variable/method/class/interface names.'
Yannis LE BARS's avatar
Yannis LE BARS committed
132
133
134
135
136
137
138
139
140
		),
		measurement: smm!DirectMeasurement (
			error <- node.name + ' has dollar in ' + node.originalCompilationUnit.name
		)
	do {
		noc; 
	}
}

Yannis LE BARS's avatar
Yannis LE BARS committed
141
-- A Measure instance if the class violates the rule 'ShortMethodName'.
E19C506H's avatar
E19C506H committed
142
rule MesureShortMethodName(method: java!MethodDeclaration) {
Yannis LE BARS's avatar
Yannis LE BARS committed
143
144
145
146
147
148
149
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'ShortMethodName',
E19C506H's avatar
E19C506H committed
150
151
			shortDescription <- 'Method names names that are very short are not helpful'
					+ ' to the reader.'
Yannis LE BARS's avatar
Yannis LE BARS committed
152
153
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
154
155
			error <- method.name + ' is too short in ' + method.originalCompilationUnit.
					name
Yannis LE BARS's avatar
Yannis LE BARS committed
156
157
158
159
160
		)
	do {
		noc; 
	}
}
Raphael PAGE's avatar
Raphael PAGE committed
161

Marion HUNAULT's avatar
Marion HUNAULT committed
162
-- A Measure instance if the class violates the rule 'ShortClassName'.
E19C506H's avatar
E19C506H committed
163
rule MesureShortClassName(class: java!ClassDeclaration) {
Marion HUNAULT's avatar
Marion HUNAULT committed
164
165
166
167
168
169
170
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'ShortClassName',
E19C506H's avatar
E19C506H committed
171
172
			shortDescription <- 'Short Classnames with fewer than e.g. five characters'
					+ ' are not recommended.'
Marion HUNAULT's avatar
Marion HUNAULT committed
173
174
175
176
177
178
179
180
181
		),
		measurement: smm!DirectMeasurement (
			error <- 'The Class ' + class.name + ' is too short.'
		)
	do {
		noc; 
	}
}

Raphael's avatar
Raphael committed
182
-- creates a new Measure when Thread.run() is used instead of Thread.start()
E19C506H's avatar
E19C506H committed
183
rule MeasureDontCallThreadRun(method: java!MethodInvocation) {
Raphael's avatar
Raphael committed
184
185
186
187
188
189
190
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Don t call Thread.run()',
E19C506H's avatar
E19C506H committed
191
192
193
			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
194
		),
E19C506H's avatar
E19C506H committed
195
196
197
		measurement: smm!DirectMeasurement (
			error <- 'The class ' + method.originalCompilationUnit.name + ' violates the'
					+ ' rule don t call Thread.run().'
Raphael's avatar
Raphael committed
198
		)
Raphael's avatar
Raphael committed
199
200
201
202
203
	do {
		noc; 
	}
}

Astlo's avatar
Astlo committed
204
-- A Measure instance if the class violates the rule 'TooManyFields'.
E19C506H's avatar
E19C506H committed
205
rule MesureTooManyFields(class: java!ClassDeclaration) {
Gerson Sunyé's avatar
Gerson Sunyé committed
206
207
208
209
210
211
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
Astlo's avatar
Astlo committed
212
			name <- 'TooManyFields',
E19C506H's avatar
E19C506H committed
213
214
			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
215
216
		),
		measurement: smm!DirectMeasurement (
Astlo's avatar
Astlo committed
217
			error <- class.originalCompilationUnit.name + ' have too many fields'
Gerson Sunyé's avatar
Gerson Sunyé committed
218
		)
Raphael's avatar
Raphael committed
219
220
221
222
223
	do {
		noc; 
	}
}

E19C506H's avatar
E19C506H committed
224
225
226
-- 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
227
228
229
230
231
232
233
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Use index of char',
E19C506H's avatar
E19C506H committed
234
235
			shortDescription <- 'Use String.indexOf(char) when checking for the index of'
					+ ' a single character; it executes faster.'
Raphael's avatar
Raphael committed
236
		),
E19C506H's avatar
E19C506H committed
237
238
239
		measurement: smm!DirectMeasurement (
			error <- 'The class ' + method.originalCompilationUnit.name + ' violates the'
					+ ' rule index of char.'
Raphael's avatar
Raphael committed
240
241
242
243
244
		)
	do {
		noc; 
	}
}
Gerson Sunyé's avatar
Gerson Sunyé committed
245

Raphael PAGE's avatar
Raphael PAGE committed
246
------------------------------------------------------------------------------------------
Gerson Sunyé's avatar
Gerson Sunyé committed
247
248
249
250
251
252
253
254
255
256
rule numberOfClasses() {
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Number of Classes'
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
257
258
			value <- java!ClassDeclaration.allInstances() -> reject(each | each.
					isProxy()) -> size()
Gerson Sunyé's avatar
Gerson Sunyé committed
259
		)
Gerson Sunyé's avatar
Gerson Sunyé committed
260

Gerson Sunyé's avatar
Gerson Sunyé committed
261
262
263
264
	do {
		noc; 
	}
}
265

E19C506H's avatar
E19C506H committed
266
267
-- Rule that creates an instance of Measure for the switch statement with too few
		-- branches passed in parameter
268
rule MeasureTooFewBranchesForASwitchStatement(switchStatement: java!SwitchStatement) {
269
270
271
272
273
274
	to
		om: smm!ObservedMeasure (
			measure <- tooFewBranchesForASwitchStatement,
			measurements <- measurement
		),
		tooFewBranchesForASwitchStatement: smm!DimensionalMeasure (
275
			name <- 'TooFewBranchesForASwitchStatement',
E19C506H's avatar
E19C506H committed
276
277
278
279
280
			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.'
281
282
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
283
284
			error <- 'Too few branches for SwitchStatement in Class : ' + switchStatement.
					originalCompilationUnit.name,
285
286
287
288
289
290
			value <- thisModule.nbBranchesOfASwitchStatement(switchStatement)
		)
	do {
		tooFewBranchesForASwitchStatement; 
	}
}
291

E19C506H's avatar
E19C506H committed
292
293
--------------------------------------------- ShortInstantiation
--- ---------------------------------------------
294
-- A Measure instance if the class violates the rule 'ShortInstantiation'.
E19C506H's avatar
E19C506H committed
295
rule MeasureShortInstantiation(variable: java!CompilationUnit) {
296
297
298
299
300
301
302
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'ShortInstantiation',
E19C506H's avatar
E19C506H committed
303
304
305
306
307
			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.'
308
		),
E19C506H's avatar
E19C506H committed
309
310
311
		measurement: smm!DirectMeasurement (
			error <- 'In the Class ' + variable.name + ' an instantiation of Short must'
					+ ' be Short.ValueOf().'
312
313
314
315
316
317
318
		)
		
	do {
		noc; 
	}
}

E19C506H's avatar
E19C506H committed
319
320
--------------------------------------------- LongInstantiation
--- ---------------------------------------------
321
-- A Measure instance if the class violates the rule 'LongInstantiation'.
E19C506H's avatar
E19C506H committed
322
rule MeasureLongInstantiation(variable: java!CompilationUnit) {
323
324
325
326
327
328
329
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'LongInstantiation',
E19C506H's avatar
E19C506H committed
330
331
332
333
334
			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.'
335
		),
E19C506H's avatar
E19C506H committed
336
337
338
		measurement: smm!DirectMeasurement (
			error <- 'In the Class ' + variable.name + ' an instantiation of Long must be'
					+ ' Long.ValueOf().'
339
340
341
342
343
344
345
		)
		
	do {
		noc; 
	}
}

E19C506H's avatar
E19C506H committed
346
347
--------------------------------------------- DoNotExtendJavaLangThrowable 
--- ---------------------------------------------
348
-- A Measure instance if the class violates the rule DoNotExtendJavaLangThrowable.
E19C506H's avatar
E19C506H committed
349
rule MeasureDoNotExtendJavaLangThrowable(variable: java!ClassDeclaration) {
350
351
352
353
354
355
356
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'DoNotExtendJavaLangThrowable ',
E19C506H's avatar
E19C506H committed
357
358
			shortDescription <- 'Extend Exception or RuntimeException instead of'
					+ ' Throwable.'
359
		),
E19C506H's avatar
E19C506H committed
360
361
362
		measurement: smm!DirectMeasurement (
			error <- 'In the Class ' + variable.name + ' should not extend Throwable but'
					+ ' RuntimeException or Exception .'
363
364
365
366
367
368
		)
		
	do {
		noc; 
	}
}
E19C506H's avatar
E19C506H committed
369

370
-- Returns the number of branches in the switch statement passed in parameter
E19C506H's avatar
E19C506H committed
371
372
helper def: nbBranchesOfASwitchStatement(switchStatement: java!SwitchStatement): Integer =
	switchStatement.statements -> select(each | each.oclIsTypeOf(java!SwitchCase)).size();
373

374
-- Returns the number of Fields in Class
E19C506H's avatar
E19C506H committed
375
helper def: numberFieldsInClasse(s: java!ClassDeclaration): Integer =
376
	-- Return the number of FieldDeclaration in a class.
E19C506H's avatar
E19C506H committed
377
	s.bodyDeclarations -> select(r | r.oclIsTypeOf(java!FieldDeclaration)) -> size();
Martin's avatar
Martin committed
378

379
-- Returns the number of breaks of the switch statement passed in parameter
E19C506H's avatar
E19C506H committed
380
381
helper def: nbBreakStatementOfASwitchStatement(ss: java!SwitchStatement): Integer =
	ss.statements -> select(each | each.oclIsTypeOf(java!BreakStatement)).size();
382
383

-- Returns the number of expressions of the switch statement passed in parameter
E19C506H's avatar
E19C506H committed
384
385
386
387
388
389
390
391
392
393
394
395
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
396
397
398
399
400
401
402
403
404
-- 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',
E19C506H's avatar
E19C506H committed
405
406
407
			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.'
408
409
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
410
411
			error <- 'Missing breaks in Switch in Class : ' + ss.originalCompilationUnit.
					name + '',
412
			-- Indicates the number of breaks missing in the switch statement
E19C506H's avatar
E19C506H committed
413
414
415
			value <- (thisModule.nbBranchesOfASwitchStatement(ss) - thisModule.
					nbIntentionalFallThroughOfASwitchStatement(ss)) - thisModule.
					nbBreakStatementOfASwitchStatement(ss)
416
417
418
419
420
421
		)
	do {
		missingBreakInSwitch; 
	}
}

Martin's avatar
Martin committed
422
-- A Measure instance if the class violates the rule 'TooManyMethods'.
E19C506H's avatar
E19C506H committed
423
rule MesureTooManyMethods(class: java!ClassDeclaration) {
Martin's avatar
Martin committed
424
425
426
427
428
429
430
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'TooManyMethods',
E19C506H's avatar
E19C506H committed
431
432
433
			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
434
435
		),
		measurement: smm!DirectMeasurement (
Martin ARS's avatar
Martin ARS committed
436
			error <- class.originalCompilationUnit.name + ' has too many methods'
Martin's avatar
Martin committed
437
438
439
440
441
442
		)

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

444
-- A Measure instance if the class violates the rule ReturnFromFinallyBlock.
E19C506H's avatar
E19C506H committed
445
rule MesureReturnFromFinallyBlock(method: java!MethodDeclaration) {
446
447
448
449
450
451
452
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'returnFromFinallyBlock',
E19C506H's avatar
E19C506H committed
453
454
			shortDescription <- 'Avoid returning from a finally block, this can discard'
					+ ' exceptions.'
455
456
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
457
458
459
			error <- 'The method ' + method.name + ' in the class ' + method.
					originalCompilationUnit.name + ' has a return statement in a finally'
					+ ' block.'
460
461
462
463
464
		)
	do {
		noc; 
	}
}
Martin ARS's avatar
Martin ARS committed
465
466

-- A Measure instance if the class violates the rule 'TooManyStaticImports'.
E19C506H's avatar
E19C506H committed
467
rule MesureTooManyStaticImports(class: java!CompilationUnit) {
Martin ARS's avatar
Martin ARS committed
468
469
470
471
472
473
474
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'TooManyStaticImports',
E19C506H's avatar
E19C506H committed
475
476
477
478
479
480
			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
481
482
483
484
485
486
487
		),
		measurement: smm!DirectMeasurement (
			error <- class.name + ' has too many static imports'
		)
	do {
		noc; 
	}
Raphael's avatar
Raphael committed
488
489
}

Raphael PAGE's avatar
Raphael PAGE committed
490
-- creates a new Measure when the method printStackTrace is used
E19C506H's avatar
E19C506H committed
491
rule MeasureAvoidPrintStackTrace(method: java!MethodInvocation) {
Raphael PAGE's avatar
Raphael PAGE committed
492
493
494
495
496
497
498
		to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Avoid print stack trace',
E19C506H's avatar
E19C506H committed
499
			shortDescription <- 'Avoid printStackTrace(); use a logger call instead.'
Raphael PAGE's avatar
Raphael PAGE committed
500
		),
E19C506H's avatar
E19C506H committed
501
502
503
		measurement: smm!DirectMeasurement (
			error <- 'The class ' + method.originalCompilationUnit.name + ' violates the'
					+ ' rule avoid print stack trace.'
Raphael PAGE's avatar
Raphael PAGE committed
504
505
506
507
508
		)
	do {
		noc; 
	}
}
Raphael's avatar
Raphael committed
509
510

-- creates a new Measure when Thread.run() is used instead of Thread.start()
E19C506H's avatar
E19C506H committed
511
rule measureAvoidThreadGroup(variable: java!VariableDeclarationFragment) {
Raphael's avatar
Raphael committed
512
513
514
515
516
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
517
		noc: smm!DimensionalMeasure (
Raphael's avatar
Raphael committed
518
			name <- 'Avoid Thread Group',
E19C506H's avatar
E19C506H committed
519
520
521
			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
522
		),
E19C506H's avatar
E19C506H committed
523
524
525
		measurement: smm!DirectMeasurement (
			error <- 'The class ' + variable.originalCompilationUnit.name + ' violates'
					+ ' the rule avoid thread group.'
Raphael's avatar
Raphael committed
526
527
		)
		
Martin ARS's avatar
Martin ARS committed
528
529
530
	do {
		noc; 
	}
Raphael PAGE's avatar
Raphael PAGE committed
531
}
532

E19C506H's avatar
E19C506H committed
533
534
535
536
537
--------------------------------------------- AvoidThrowingNewInstanceOfSameException
--- ---------------------------------------------
-- A Measure instance if the class violates the rule
		-- 'AvoidThrowingNewInstanceOfSameException'.
rule MeasureAvoidThrowingNewInstanceOfSameException(catch: java!CatchClause) {
538
539
540
541
542
543
544
    to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'AvoidThrowingNewInstanceOfSameException',
E19C506H's avatar
E19C506H committed
545
546
547
			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.'
548
		),
E19C506H's avatar
E19C506H committed
549
550
551
552
		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.'
553
554
555
556
557
558
		)
	do {
		noc; 
	}
}

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

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

605
-- A Measure instance if the class violates the rule 'AvoidFieldNameMatchingMethodName'.
E19C506H's avatar
E19C506H committed
606
607
rule MesureAvoidFieldNameMatchingMethodName(class: java!ClassDeclaration, method:
		java!MethodDeclaration) {
608
609
610
611
612
613
614
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'AvoidFieldNameMatchingMethodName',
E19C506H's avatar
E19C506H committed
615
616
617
618
619
			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.'
620
621
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
622
623
			error <- 'In the ' + class.name + ' class you have an field and an method'
					+ ' with the same name : ' + method.name
624
625
626
627
628
		)
	do {
		noc; 
	}
}
629
630
631
632
633
634
635
636
637
638

-- 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',
E19C506H's avatar
E19C506H committed
639
640
641
642
			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.'
643
644
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
645
646
			error <- 'Used notify() instead of notifyAll() in Class : ' + method.
					originalCompilationUnit.name
647
648
649
650
651
		)
	do {
		useNotifyAllInsteadOfNotify; 
	}
}
Roxane MARECHAL's avatar
Roxane MARECHAL committed
652

653
--- Creates a measure instance for each element that violates the rule : CommentRequired
E19C506H's avatar
E19C506H committed
654
655
rule MeasureCommentRequired(element: java!BodyDeclaration, violatedProperties:
		Set(String)) {
Roxane MARECHAL's avatar
Roxane MARECHAL committed
656
657
658
659
660
661
662
	to
		om: smm!ObservedMeasure (
			measure <- commentRequired,
			measurements <- measurement
		),
		commentRequired: smm!DimensionalMeasure (
			name <- 'CommentRequired',
E19C506H's avatar
E19C506H committed
663
664
			shortDescription <- 'Denotes whether comments are required (or unwanted) for'
					+ ' specific language elements.'
Roxane MARECHAL's avatar
Roxane MARECHAL committed
665
666
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
667
668
669
670
			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
671
672
673
		)
		do {
		commentRequired; 
E19C506H's avatar
E19C506H committed
674
	}
Roxane MARECHAL's avatar
Roxane MARECHAL committed
675
676
}

Ronan GUEGUEN's avatar
Ronan GUEGUEN committed
677
678
679
680
681
682
683
684
rule MeasureCommentContent(element: Sequence(String)){
	to
		om: smm!ObservedMeasure (
			measure <- commentContent,
			measurements <- measurement
		),
		commentContent: smm!DimensionalMeasure (
			name <- 'CommentContent',
E19C506H's avatar
E19C506H committed
685
686
			shortDescription <- 'A rule for the politically correct… we don’t want to'
					+ ' offend anyone.'
Ronan GUEGUEN's avatar
Ronan GUEGUEN committed
687
688
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
689
			error <- 'The words ' + element + ' were found in a comment '
Ronan GUEGUEN's avatar
Ronan GUEGUEN committed
690
691
		)
		do {
E19C506H's avatar
E19C506H committed
692
693
		commentContent; 
	}
Ronan GUEGUEN's avatar
Ronan GUEGUEN committed
694
695
696
	
}

697
--- Returns the name of a BodyDeclaration
E19C506H's avatar
E19C506H committed
698
699
helper context java!BodyDeclaration def: getBodyDeclarationName(): String =
	self.name;
700

E19C506H's avatar
E19C506H committed
701
702
703
704
--- 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
705

706
--- Returns the AnnotationTypeDeclaration corresponding to the given BodyDeclaration
Roxane MARECHAL's avatar
Roxane MARECHAL committed
707
-- This is necessary because BodyDeclaration.annotations returns Sequence(!IN<unamed>)
E19C506H's avatar
E19C506H committed
708
709
710
711
712
713
714
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
715

716
-- A Measure instance if the class violates the rule 'SuspiciousEqualsMethodName'
E19C506H's avatar
E19C506H committed
717
rule MeasureSuspiciousEqualsMethodName(method: java!MethodDeclaration) {
718
719
720
721
722
723
724
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Suspicious Equals Method Name',
E19C506H's avatar
E19C506H committed
725
726
727
			shortDescription <- 'The method name and parameter number are suspiciously'
					+ ' close to equals(Object), which can denote an intention to'
					+ ' override the equals(Object) method.'
728
729
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
730
731
			error <- 'The class ' + method.originalCompilationUnit.name + ' has a'
					+ ' suspicious \'equals\' method name : ' + method.toString()
732
733
		)
	do {
E19C506H's avatar
E19C506H committed
734
		noc; 
735
736
737
	}
}

Glenn PLOUHINEC's avatar
Glenn PLOUHINEC committed
738
-- A Measure instance if the class violates the rule 'AvoidUsingShortType'
E19C506H's avatar
E19C506H committed
739
rule MeasureAvoidUsingShortType(typeShort: java!VariableDeclarationStatement) {
Glenn PLOUHINEC's avatar
Glenn PLOUHINEC committed
740
741
742
743
744
745
746
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Avoid using short type',
E19C506H's avatar
E19C506H committed
747
748
749
750
751
752
753
			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
754
755
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
756
757
			error <- 'The class ' + typeShort.originalCompilationUnit.name + ' has'
					+ ' \'short\' type variable.'
Glenn PLOUHINEC's avatar
Glenn PLOUHINEC committed
758
759
		)
	do {
E19C506H's avatar
E19C506H committed
760
		noc; 
Glenn PLOUHINEC's avatar
Glenn PLOUHINEC committed
761
762
	}
}
763
764

-- A Measure instance if the class violates the rule 'EmptyStatementBlock'
E19C506H's avatar
E19C506H committed
765
rule MeasureEmptyStatementBlock(block: java!Block) {
766
767
768
769
770
771
772
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'Empty Statement Block',
E19C506H's avatar
E19C506H committed
773
774
			shortDescription <- 'Empty block statements serve no purpose and should be'
					+ ' removed.'
775
776
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
777
778
			error <- 'The class ' + block.originalCompilationUnit.name + ' has an empty'
					+ ' statement block.'
779
780
		)
	do {
E19C506H's avatar
E19C506H committed
781
		noc; 
782
783
	}
}
784

E19C506H's avatar
E19C506H committed
785
786
--------------------------------------------- DoNotExtendJavaLangError 
--- ---------------------------------------------
787
-- A Measure instance if the class violates the rule DoNotExtendJavaLangError.
E19C506H's avatar
E19C506H committed
788
rule MeasureDoNotExtendJavaLangError(variable: java!ClassDeclaration) {
789
790
791
792
793
794
795
796
797
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'DoNotExtendJavaLangError ',
			shortDescription <- 'Errors are system exceptions. Do not extend them.'
		),
E19C506H's avatar
E19C506H committed
798
799
800
		measurement: smm!DirectMeasurement (
			error <- 'In the Class ' + variable.name + ' Do not extend Error, Errors are'
					+ ' system exceptions.'
801
802
803
804
805
806
		)
		
	do {
		noc; 
	}
}
807

E19C506H's avatar
E19C506H committed
808
809
--------------------------------------------- MeasureFinalFieldCouldBeStatic 
--- ---------------------------------------------
810
-- A Measure instance if the class violates the rule MeasureFinalFieldCouldBeStatic.
E19C506H's avatar
E19C506H committed
811
rule MeasureFinalFieldCouldBeStatic(field: java!FieldDeclaration) {
812
813
814
815
816
817
818
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'FinalFieldCouldBeStatic',
E19C506H's avatar
E19C506H committed
819
820
821
			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.'
822
		),
E19C506H's avatar
E19C506H committed
823
824
825
826
		measurement: smm!DirectMeasurement (
			error <- 'The field ' + field.fragments -> collect(i | i.name) -> first() + ''
					+ ' could be static in the class ' + field.originalCompilationUnit.
					name + '.'
827
828
829
830
831
832
		)
		
	do {
		noc; 
	}
}
Louis QUESTEL's avatar
Louis QUESTEL committed
833

E19C506H's avatar
E19C506H committed
834
835
--------------------------------------------- MeasureExtendsObject 
--- ---------------------------------------------
Louis QUESTEL's avatar
Louis QUESTEL committed
836
-- A Measure instance if the class violates the rule ExtendsObject.
E19C506H's avatar
E19C506H committed
837
rule MeasureExtendsObject(variable: java!ClassDeclaration) {
Louis QUESTEL's avatar
Louis QUESTEL committed
838
839
840
841
842
843
844
845
846
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'ExtendsObject',
			shortDescription <- 'No need to explicitly extend Object.'
		),
E19C506H's avatar
E19C506H committed
847
848
849
		measurement: smm!DirectMeasurement (
			error <- 'In the Class ' + variable.name + ' No need to explicitly extend'
					+ ' Object.'
Louis QUESTEL's avatar
Louis QUESTEL committed
850
851
852
853
854
855
		)
		
	do {
		noc; 
	}
}
856

E19C506H's avatar
E19C506H committed
857
858
--------------------------------------------- SwitchDensity 
--- ---------------------------------------------
859
-- A Measure instance if the class violates the rule SwitchDensity.
E19C506H's avatar
E19C506H committed
860
rule MeasureSwitchDensity(switch: java!SwitchStatement) {
861
862
863
864
865
866
867
868
869
870
	
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'SwitchDensity ',
			shortDescription <- 'Statement to label ratio is too high (> 10)'
		),
E19C506H's avatar
E19C506H committed
871
872
873
		measurement: smm!DirectMeasurement (
			error <- 'In the Class ' + switch.originalCompilationUnit.name + ' a switch'
					+ ' case contains too many statements.'
874
875
876
877
		)
	do {
		noc; 
	}
E19C506H's avatar
E19C506H committed
878
879
880
881
}

--------------------------------------------- SignatureDeclareThrowsException 
--- ---------------------------------------------
882
-- A Measure instance if the class violates the rule SignatureDeclareThrowsException.
E19C506H's avatar
E19C506H committed
883
rule MeasureSignatureDeclareThrowsException(class: java!ClassDeclaration) {
884
885
886
887
888
889
890
891
	
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'SignatureDeclareThrowsException ',
E19C506H's avatar
E19C506H committed
892
893
			shortDescription <- 'A method/constructor should not explicitly throw the'
					+ ' generic java.lang.Exception'
894
		),
E19C506H's avatar
E19C506H committed
895
896
897
		measurement: smm!DirectMeasurement (
			error <- 'In the Class ' + class.name + ' a method/constructor explicitly'
					+ ' throws the generic java.lang.Exception.'
898
899
900
901
		)
	do {
		noc; 
	}
E19C506H's avatar
E19C506H committed
902
}
903

E19C506H's avatar
E19C506H committed
904
905
--------------------------------------------- UnnecessaryReturn 
--- ---------------------------------------------
906
-- A Measure instance if the class violates the rule UnnecessaryReturn.
E19C506H's avatar
E19C506H committed
907
rule MeasureUnnecessaryReturn(state: java!ReturnStatement) {
908
909
910
911
912
913
914
915
916
917
	
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'UnnecessaryReturn ',
			shortDescription <- 'Avoid the use of unnecessary return statements.'
		),
E19C506H's avatar
E19C506H committed
918
919
920
		measurement: smm!DirectMeasurement (
			error <- 'In the Class ' + state.originalCompilationUnit.name + ' an'
					+ ' unnecessary return was used.'
921
922
923
924
		)
	do {
		noc; 
	}
925
926
}

E19C506H's avatar
E19C506H committed
927
928
--------------------------------------------- MeasureCompareObjectsWithEquals 
--- ---------------------------------------------
929
--A measure instance if the class violates the rule MeasureCompareObjectsWithEquals.
E19C506H's avatar
E19C506H committed
930
rule MeasureCompareObjectsWithEquals(expression: java!InfixExpression) {
931
932
933
934
935
936
937
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'CompareObjectsWithEquals',
E19C506H's avatar
E19C506H committed
938
939
			shortDescription <- 'Use equals() to compare object references; avoid'
					+ ' comparing them with ==.'
940
		),
E19C506H's avatar
E19C506H committed
941
942
943
		measurement: smm!DirectMeasurement (
			error <- 'The Class ' + expression.originalCompilationUnit.name + ' is using'
					+ ' == instead of equals() to compare objects.'
944
945
946
947
948
		)
		
	do {
		noc; 
	}
E19C506H's avatar
E19C506H committed
949
}
950

E19C506H's avatar
E19C506H committed
951
952
953
954
--------------------------------------------- AvoidRethrowingException 
--- ---------------------------------------------
--A Measure instance if the class violates the rule AvoidRethrowingException.
rule MeasureAvoidRethrowingException(statement: java!TryStatement) {
955
956
957
958
959
960
961
962
963
 		to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'AvoidRethrowingException ',
			shortDescription <- 'Avoid merely rethrowing an exception.'
		),
E19C506H's avatar
E19C506H committed
964
965
966
		measurement: smm!DirectMeasurement (
			error <- 'In the Class ' + statement.originalCompilationUnit.name + ' an'
					+ ' exception was caught and merely rethrown.'
967
968
969
970
		)
	do {
		noc; 
	}
E19C506H's avatar
E19C506H committed
971
972
973
974
}

--------------------------------------------- IntegerInstantiation
--- ---------------------------------------------
Alexis Pineau's avatar
Alexis Pineau committed
975
-- A Measure instance if the class violates the rule 'IntegerInstantiation'.
E19C506H's avatar
E19C506H committed
976
rule MeasureIntegerInstantiation(variable: java!CompilationUnit) {
Alexis Pineau's avatar
Alexis Pineau committed
977
978
979
980
981
982
983
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'IntegerInstantiation',
E19C506H's avatar
E19C506H committed
984
985
986
987
988
			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
989
		),
E19C506H's avatar
E19C506H committed
990
991
992
		measurement: smm!DirectMeasurement (
			error <- 'In the Class ' + variable.name + ' an instantiation of Integer must'
					+ ' be Integer.ValueOf().'
Alexis Pineau's avatar
Alexis Pineau committed
993
994
995
996
997
998
999
		)
		
	do {
		noc; 
	}
}

E19C506H's avatar
E19C506H committed
1000
1001
--------------------------------------------- LongVariable 
--- ---------------------------------------------
1002
-- A Measure instance if the variable violates the rule LongVariable.
E19C506H's avatar
E19C506H committed
1003
rule MeasureLongVariable(variable: java!VariableDeclarationFragment) {
1004
1005
1006
1007
1008
1009
1010
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'LongVariable',
E19C506H's avatar
E19C506H committed
1011
1012
			shortDescription <- ': Fields, formal arguments, or local variable names that'
					+ ' are too long can make the code difficult '
1013
1014
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
1015
			error <- variable.name + ' is too Long '
1016
1017
1018
1019
1020
1021
		)
	do {
		noc; 
	}
}

E19C506H's avatar
E19C506H committed
1022
1023
--------------------------------------------- AvoidCallingFinalize 
--- ---------------------------------------------
1024
-- A Measure instance if the class violates the rule LongVariable.
E19C506H's avatar
E19C506H committed
1025
rule MeasureAvoidCallingFinalize(methode: java!MethodInvocation) {
1026
1027
1028
1029
1030
1031
1032
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'AvoidCallingFinalize',
E19C506H's avatar
E19C506H committed
1033
1034
			shortDescription <- ': The method Object.finalize() is called by the garbage'
					+ ' collector on an object when garbage collect... '
1035
1036
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
1037
1038
			error <- 'finalize() is called in class' + methode.originalCompilationUnit.
					name
1039
1040
1041
1042
1043
1044
		)
	do {
		noc; 
	}
}

E19C506H's avatar
E19C506H committed
1045
1046
--------------------------------------------- AvoidStringBufferField 
--- ---------------------------------------------
1047
-- A Measure instance if the class violates AvoidStringBufferField .
E19C506H's avatar
E19C506H committed
1048
rule MeasureAvoidStringBufferField(declaration: java!VariableDeclaration) {
1049
1050
1051
1052
1053
1054
1055
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'AvoidStringBufferField',
E19C506H's avatar
E19C506H committed
1056
1057
			shortDescription <- ': StringBuffers/StringBuilders can grow considerably,'
					+ ' and so may become a source of memory leaksif ...'
1058
1059
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
1060
1061
			error <- 'AvoidStringBufferField is detected in ' + declaration.
					originalCompilationUnit.name
1062
1063
1064
1065
1066
1067
1068
1069
		)
	do {
		noc; 
	}
}

--------------------- AvoidThrowingNullPointerException----------------------------------
-- A Measure instance if the class violates AvoidThrowingNullPointerException .
E19C506H's avatar
E19C506H committed
1070
rule MeasureAvoidThrowingNullPointerException(c: java!ClassInstanceCreation) {
1071
1072
1073
1074
1075
1076
1077
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'AvoidThrowingNullPointerException',
E19C506H's avatar
E19C506H committed
1078
1079
1080
			shortDescription <- 'Avoid throwing NullPointerExceptions manually. These are'
					+ ' confusing because most people will assume that the virtual'
					+ ' machine threw it'
1081
1082
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
1083
1084
			error <- 'AvoidThrowingNullPointerException is detected in ' + c.
					originalCompilationUnit.name
1085
1086
1087
1088
1089
1090
1091
1092
		)
	do {
		noc; 
	}
}

--------------------- EmptyTryBlock----------------------------------
--A measure instance if the class violates the rule EmptyTryBlock.
E19C506H's avatar
E19C506H committed
1093
rule MeasureEmptyTryBlock(t: java!TryStatement) {
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
	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.
E19C506H's avatar
E19C506H committed
1113
rule MeasureEmptyWhileStmt(w: java!TryStatement) {
1114
1115
1116
1117
1118
1119
1120
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'EmptyWhileStmt',
E19C506H's avatar
E19C506H committed
1121
1122
			shortDescription <- ': Empty While Statement finds all instances where a'
					+ ' while statement does nothing.'
1123
1124
1125
1126
1127
1128
1129
1130
1131
		),
		measurement: smm!DirectMeasurement (
			error <- 'EmptyWhileStmt is detected in  ' + w.originalCompilationUnit.name
		)
	do {
		noc; 
	}
}

E19C506H's avatar
E19C506H committed
1132
1133
-------------------------------------------
--- MeasureDontImportSun----------------------------------------------
1134
-- A Measure instance if the class violate the rule DontImportSun
E19C506H's avatar
E19C506H committed
1135
rule MeasureDontImportSun(p: java!CompilationUnit) {
1136
1137
	to
		om: smm!ObservedMeasure (
E19C506H's avatar
E19C506H committed
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
			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)
		)
1148
1149
1150
1151
1152
	do {
		noc; 
	}
}

E19C506H's avatar
E19C506H committed
1153
1154
-------------------------------------------
--- FinalizeShouldBeProtected----------------------------------------------
1155
-- A Measure instance if the class violate the rule FinalizeShouldBeProtected
E19C506H's avatar
E19C506H committed
1156
rule MesureFinalizeShouldBeProtected(m: java!MethodDeclaration) {
1157
1158
	to
		om: smm!ObservedMeasure (
E19C506H's avatar
E19C506H committed
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
			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
		)
1171
1172
1173
1174
1175
	do {
		noc; 
	}
}

E19C506H's avatar
E19C506H committed
1176
-- A Measure instance if the class violates the rule AvoidNoPackageDeclaration.
E19C506H's avatar
E19C506H committed
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
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 (
			error <- 'In the ' + class.name + ' class have no package declaration'
		)
1190

E19C506H's avatar
E19C506H committed
1191
1192
1193
1194
	do {
		noc; 
	}
}
E19C506H's avatar
E19C506H committed
1195

E19C506H's avatar
E19C506H committed
1196
-- A Measure instance if the class violates the rule UnconditionalIfStatement.
E19C506H's avatar
E19C506H committed
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
rule MeasureUnconditionalIfStatement(w: java!IfStatement) {
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'UnconditionalIfStatement',
			shortDescription <- ': UnconditionalIfStatement finds all instances where a'
					+ ' UnconditionalIfStatement statement does nothing.'
		),
		measurement: smm!DirectMeasurement (
			error <- 'UnconditionalIfStatement is detected in  ' + w.originalCompilationUnit.name
		)
	do {
		noc; 
	}
E19C506H's avatar
E19C506H committed
1214
1215
}

E19C506H's avatar
E19C506H committed
1216
-- A Measure instance if the class violates the rule EmptyInitializer.
E19C506H's avatar
E19C506H committed
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
rule MeasureEmptyInitializer(w: java!Initializer) {
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'EmptyInitializer',
			shortDescription <- ': EmptyInitializer finds '
		),
		measurement: smm!DirectMeasurement (
			error <- 'do not declare an EmptyInitializer, EmptyInitializer is detected in  ' + w.originalCompilationUnit.name + ' this block need to be deleted'
		)
	do {
		noc; 
	}
E19C506H's avatar
E19C506H committed
1233
1234
}

E19C506H's avatar
E19C506H committed
1235
1236
-- A Measure instance if the class violates the rule ExcessiveClassLength.
rule MeasureExcessiveClassLength(w: java!MethodDeclaration) {
E19C506H's avatar
E19C506H committed
1237
1238
1239
1240
1241
1242
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
E19C506H's avatar
E19C506H committed
1243
1244
			name <- 'ExcessiveClassLength',
			shortDescription <- ': class file lengths are usually indications that the class may be burdened with excessive responsibilities that could be provided by external classes or functions'
E19C506H's avatar
E19C506H committed
1245
1246
		),
		measurement: smm!DirectMeasurement (
E19C506H's avatar
E19C506H committed
1247
			error <- w.originalCompilationUnit.name+ 'has a block with more than 1000 line of code per a method it may need a separation in the code'
E19C506H's avatar
E19C506H committed
1248
1249
1250
1251
		)
	do {
		noc; 
	}
E19C506H's avatar
E19C506H committed
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
}

-- A Measure instance if the class violates the rule CloneMethodMustBePublic.
rule MeasureCloneMethodMustBePublic(w: java!MethodDeclaration) {
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'CloneMethodMustBePublic',
			shortDescription <- 'CloneMethodMustBePublic'
		),
		measurement: smm!DirectMeasurement (
			error <- w.originalCompilationUnit.name+ 'the clone methode in here need to be public '
		)
	do {
		noc; 
	}
E19C506H's avatar
E19C506H committed
1271
}