analysis.atl 63.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
-- @nsURI smm=http://www.eclipse.org/MoDisco/SMM/1.0.Beta2/smm
-- @nsURI java=http://www.eclipse.org/MoDisco/Java/0.2.incubation/java


module analysis;
create OUT: smm from IN: java;

uses design;
uses codestyle;
uses multithreading;
uses performance;
uses bestPractices;
uses documentation;
uses errorProne;

 
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)
		)
}

helper def: allMeasures(project : java!Model): Set(smm!Measure) =

	Set{
		-- Example rule
		--
		thisModule.numberOfClasses(),
		
		-- Multithreading rules
		--
		thisModule.avoidThreadGroup(),
		thisModule.useNotifyAllInsteadOfNotify(),
42
		thisModule.dontCallThreadRun(),
43
44
45
46
		
		
		-- Code Style rules
		--
47
		thisModule.avoidDollarSigns(),
48
		thisModule.avoidPrefixingMethodParameters(),
49
		thisModule.extendsObject(),
50
		thisModule.fieldDeclarationsShouldBeAtStartOfClass(),
51
52
53
54
55
56
57
58
59
60
61
62
		thisModule.genericsNaming(),
		thisModule.longVariable(),
		thisModule.misLeadingVariableName(),
		thisModule.noPackageDeclaration(),
		thisModule.shortClassName(),
		thisModule.shortMethodName(),
		thisModule.shortVariableName(),
		thisModule.tooManyStaticImports(),
		thisModule.unnecessaryReturn(),

		-- Design rules
		--
Gerson Sunyé's avatar
Gerson Sunyé committed
63
		thisModule.abstractClassWithoutAnyMethod(),
64
		thisModule.avoidThrowingNullPointerException(),
65
		thisModule.ExcessiveClassLength(),
Gerson Sunyé's avatar
Gerson Sunyé committed
66
		thisModule.excessiveImports(),
67
		thisModule.excessiveParameterList(),
68
		thisModule.excessivePublicCount(),
69
		thisModule.finalFieldCouldBeStatic(),
Gerson Sunyé's avatar
Gerson Sunyé committed
70
		thisModule.IfBraces(),
71
72
73
74
75
76
		thisModule.longInstantiation(),
		thisModule.returnFromFinallyBlock(),
		thisModule.shortInstantiation(),
		thisModule.signatureDeclareThrowsException(),
		thisModule.tooManyFields(),
		thisModule.tooManyMethods(),
77
		thisModule.SimplifyBooleanAssertion(),
78
79
80

		-- Performance rules
		--
81
		thisModule.addEmptyString(),
82
83
84
85
		thisModule.avoidPrintStackTrace(),
		thisModule.avoidRethrowingException(),
		thisModule.avoidUsingShortType(),
		thisModule.emptyStatementBlock(),
86
		-- #FIXME:
Gerson Sunyé's avatar
Gerson Sunyé committed
87
		-- thisModule.insufficientStringBufferDeclaration(),
88
		thisModule.integerInstantiation(),
89
		-- #FIXME:
Gerson Sunyé's avatar
Gerson Sunyé committed
90
91
		-- thisModule.startsWith(),
		thisModule.tooFewBranchesForASwitchStatement(),
Gerson Sunyé's avatar
Gerson Sunyé committed
92
		-- #FIXME: thisModule.useArraysAsList(),
93
94
95
96
97
98
		thisModule.useIndexOfChar(),
		thisModule.uselessStringValueOf(),
		
		-- Documentation rules
		--
		thisModule.commentContent(),
99
		thisModule.commentRequired(),
100
101
102
103
104
105
106
107

		-- Error prone rules
		--
		thisModule.avoidCallingFinalize(),
		thisModule.AvoidCatchingNPE(),
		thisModule.avoidCatchingThrowable(),
		thisModule.AvoidEnumAsIdentifier(),
		thisModule.CloneMethodMustBePublic(),
108
		thisModule.detachedTestCase(),
109
		thisModule.doNotCallGarbageCollectionExplicitly(),
110
		thisModule.doNotCallSystemExit(),
111
112
113
114
115
116
117
118
		thisModule.doNotExtendJavaLangError(),
		thisModule.doNotExtendJavaLangThrowable(),
		thisModule.dontImportSun(),
		thisModule.emptyCatchBlock(),
		thisModule.EmptyInitializer(),	
		thisModule.emptySwitchStatement(),
		thisModule.emptySynchronizedBlock(),
		thisModule.emptyTryBlock(),
Oussama EL KOURRI's avatar
Oussama EL KOURRI committed
119
120
		thisModule.emptyWhileStmt(),
		thisModule.finalizeShouldBeProtected(),
121
122
		thisModule.importFromSamePackage(),
		thisModule.missingBreakInSwitch(),
123
		thisModule.nullAssignment(),
124
		thisModule.suspiciousEqualsMethodName(),
125
		thisModule.testClassWithoutTest(),
126
127
128
129
		thisModule.UnconditionalIfStatement(),
		thisModule.UseProperClassLoader(),
		
		-- Best practices rules
Arthur Liégeois's avatar
Arthur Liégeois committed
130
		thisModule.avoidReassigningParameters(),
Oussama EL KOURRI's avatar
Oussama EL KOURRI committed
131
		thisModule.avoidStringBufferField(),
132
		thisModule.forLoopVariableCount(),
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
		thisModule.switchDensity(),
		thisModule.useAssertSameInsteadOfAssertTrue(),
		thisModule.useAssertTrueInsteadOfAssertEquals()
		
		-- Bugged rules:
		--
	    -- thisModule.UseArrayListInsteadOfVector(),
		-- thisModule.compareObjectsWithEquals(),
		-- thisModule.emptyFinallyBlock(),
		-- thisModule.emptyfinalizeMethod(),
		-- thisModule.doNotThrowExceptionInFinally(),
		-- thisModule.returnEmptyArrayRatherThanNull(),
		-- thisModule.replaceVectorToList()
		-- thisModule.unusedPrivateMethod ()
		-- thisModule.avoidThrowingNewInstanceOfSameException(),
		-- thisModule.stringToString(),
		-- thisModule.methodWithSameNameAsEnclosingClass(),
		-- thisModule.dontUseFloatTypeForLoopIndices(),
		-- thisModule.methodWithSameNameAsEnclosingClass(),
		
		
};


157

158
159
160
161
--- Creates an instance of Measure for the switch statement missing one or more break statements
-- To test, use input model : missing-break-in-switch.xmi
-- #TODO: rename rule
rule createMeasureForMissingBreakInSwitch(ss: java!SwitchStatement) {
162
163
	to
		om: smm!ObservedMeasure (
164
			measure <- missingBreakInSwitch,
165
166
			measurements <- measurement
		),
167
168
169
		missingBreakInSwitch: smm!DimensionalMeasure (
			name <- 'Missing break in Switch',
			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.'
170
		),
171
172
173
174
175
		measurement: smm!DirectMeasurement (
			error <- 'Missing breaks in Switch in Class : ' + ss.originalCompilationUnit.name + '',
			-- Indicates the number of breaks missing in the switch statement
			value <- (thisModule.nbBranchesOfASwitchStatement(ss) - thisModule.nbIntentionalFallThroughOfASwitchStatement(ss)) - thisModule.nbBreakStatementOfASwitchStatement(ss)
		)
176
	do {
177
		missingBreakInSwitch; 
178
179
180
	}
}

181
182
183
-- ------------------------------------------- AbstractClassWithoutAnyMethod ---------------------------------------------
---  creates a new Measure when an abstract class does not provides any methods.
rule MeasureAbstractClassWithoutAnyMethod(i : java!ClassDeclaration) {
184
185
186
187
188
189
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
190
191
			name <- 'AbstractClassWithoutAnyMethod',
			shortDescription <- 'If an abstract class does not provides any methods, it may be acting as a simple data containerth...'		
192
		),
193
194
		measurement: smm!DirectMeasurement (			
			error<-'The class anstract' + i.name + ' has not method.'
195
196
197
198
199
200
		)
	do {
		noc; 
	}
}

201
202
203
-- ------------------------------------------- AvoidCallingFinalize  ---------------------------------------------
--- A Measure instance if the class violates the rule LongVariable.
rule MeasureAvoidCallingFinalize(methode : java!MethodInvocation) {
204
205
206
207
208
209
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
210
211
			name <- 'AvoidCallingFinalize',
			shortDescription <- ': The method Object.finalize() is called by the garbage collector on an object when garbage collect... '
212
213
		),
		measurement: smm!DirectMeasurement (
214
			error <- 'finalize() is called in class' + methode.originalCompilationUnit.name 
215
216
217
218
219
220
		)
	do {
		noc; 
	}
}

221
222
--- A Measure instance if the class violates the rule AvoidCatchingNPE.
rule MeasureAvoidCatchingNPE(w: java!CatchClause) {
223
224
225
226
227
228
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
229
230
			name <- 'AvoidCatchingNPE',
			shortDescription <- ': Avoid Catching NullPointerExceptions'
231
232
		),
		measurement: smm!DirectMeasurement (
233
234
235
			error <- ' class '+w.originalCompilationUnit.name+ ' has a Code that should never
			throw NullPointerExceptions under normal circumstances. A catch block may hide the
			original error, causing other, more subtle problems later on.'
236
237
238
239
240
241
		)
	do {
		noc; 
	}
}

242
243
244
-- -----------------------------------------AvoidCatchingThrowable----------------------------------------------
--- A Measure instance if the class violate the rule MisLeadingVariableName
rule MeasureAvoidCatchingThrowable(catch :java!CatchClause) {
245
246
247
248
249
250
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
251
252
			name <- 'AvoidCatchingThrowable',
			shortDescription <- 'Catching Throwable errors is not recommended since its scope is very broad. It includes runtime issues such as OutOfMemoryError that should be exposed and managed separately.'
253
254
		),
		measurement: smm!DirectMeasurement (
255
			error<- 'Throwable ' + catch.exception.name + ' should not be catched.'
256
257
		)
	do {
258
		noc;
259
260
261
	}
}

262
263
--- A Measure instance if the class violates the rule AvoidEnumAsIdentifier.
rule MeasureAvoidEnumAsIdentifier(w: java!VariableDeclaration) {
264
265
266
267
268
269
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
270
271
			name <- 'AvoidEnumAsIdentifier',
			shortDescription <- ': Avoid Enum As Identifier'
272
273
		),
		measurement: smm!DirectMeasurement (
274
			error <- ' class '+w.originalCompilationUnit.name+ ' has a variable named to enum witch is a reserved name'
275
276
277
278
279
280
		)
	do {
		noc; 
	}
}

281
282
283
-- ----------------------------------------- AvoidPrefixingMethodParameters----------------------------------------------
--- A Measure instance if the class violates the rule AvoidPrefixingMethodParameters.
rule MeasureAvoidPrefixingMethodParameters(method: java!MethodDeclaration) {
284
285
286
287
288
289
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
290
291
			name <- 'AvoidPrefixingMethodParameters',
			shortDescription <- 'Prefixing parameters by ‘in’ or ‘out’ pollutes the name of the parameters and reduces code readability.'
292
293
		),
		measurement: smm!DirectMeasurement (			
294
			error<- 'Bad parameters : ' + method.getIncorrectParameters() + ', for the method ' + method.name + ' defined in the file ' + method.originalCompilationUnit.name
295
296
297
298
299
300
		)
	do {
		noc; 
	}
}

301
302
303
--- creates a new Measure when the method printStackTrace is used
rule MeasureAvoidPrintStackTrace(method : java!MethodInvocation) {
		to
304
305
306
307
308
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
309
310
			name <- 'Avoid print stack trace',
			shortDescription <- 'Avoid printStackTrace(); use a logger call instead.'		
311
		),
312
313
		measurement: smm!DirectMeasurement (			
			error<- 'The class '+ method.originalCompilationUnit.name + ' violates the rule avoid print stack trace.'
314
315
316
317
318
319
		)
	do {
		noc; 
	}
}

320
321
322
-- ----------------------------------------- AvoidReassigningParameters ----------------------------------------------
--- A Measure instance if the class violates the rule AvoidReassigningParameters.
rule MeasureAvoidReassigningParameters(assignment: java!SingleVariableAccess) {
323
324
325
326
327
328
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
329
330
			name <- 'AvoidReassigningParameters',
			shortDescription <- 'Reassigning values to incoming parameters is not recommended. Use temporary local variables instead.'
331
332
		),
		measurement: smm!DirectMeasurement (			
333
			error<- assignment.leftHandSide.variable.name + ' should not be reassigned'
334
335
336
337
338
339
		)
	do {
		noc; 
	}
}

340
341
342
343
-- ------------------------------------------- AvoidRethrowingException  ---------------------------------------------
---A Measure instance if the class violates the rule AvoidRethrowingException.
rule MeasureAvoidRethrowingException(statement : java!TryStatement) {
 		to
344
345
346
347
348
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
349
350
351
352
			
			name <- 'AvoidRethrowingException ',
			shortDescription <- 'Avoid merely rethrowing an exception.'
		
353
		),
354
355
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ statement.originalCompilationUnit.name + ' an exception was caught and merely rethrown.'
356
357
358
359
		)
	do {
		noc; 
	}
360
361
362
363
364
}	 
	
-- ------------------------------------------- AvoidStringBufferField  ---------------------------------------------
--- A Measure instance if the class violates AvoidStringBufferField .
rule MeasureAvoidStringBufferField(declaration : java!FieldDeclaration) {
365
366
	to
		om: smm!ObservedMeasure (
367
			measure <- noc,
368
369
			measurements <- measurement
		),
370
371
372
		noc: smm!DimensionalMeasure (
			name <- 'AvoidStringBufferField',
			shortDescription <- ': StringBuffers/StringBuilders can grow considerably, and so may become a source of memory leaksif ...'
373
374
		),
		measurement: smm!DirectMeasurement (
375
			error <- 'AvoidStringBufferField is detected in ' + declaration.originalCompilationUnit.name 
376
377
		)
	do {
378
		noc; 
379
380
381
	}
}

382
383
--- creates a new Measure when Thread.run() is used instead of Thread.start()
rule measureAvoidThreadGroup(variable : java!VariableDeclarationStatement) {
384
385
386
387
388
389
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
390
391
			name <- 'Avoid Thread Group',
			shortDescription <- 'Avoid using java.lang.ThreadGroup; although it is intended to be used in a threaded environment it contains methods that are not thread-safe.'		
392
393
		),
		measurement: smm!DirectMeasurement (			
394
			error<-'The class '+ variable.originalCompilationUnit.name + ' violates the rule avoid thread group.'
395
396
397
398
399
400
401
		)
		
	do {
		noc; 
	}
}

402
403
404
405
-- ------------------------------------------- AvoidThrowingNewInstanceOfSameException ---------------------------------------------
--- A Measure instance if the class violates the rule 'AvoidThrowingNewInstanceOfSameException'.
rule MeasureAvoidThrowingNewInstanceOfSameException(catch : java!CatchClause) {
    to
406
407
408
409
410
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
411
412
			name <- 'AvoidThrowingNewInstanceOfSameException',
			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.'		
413
414
		),
		measurement: smm!DirectMeasurement (			
415
			error <-'The class '+ catch.originalCompilationUnit.name + ' has a method that rethrows a caught exception wrapped inside a new instance of the same type.'
416
417
418
419
420
421
		)
	do {
		noc; 
	}
}

422
423
424
-- ------------------- AvoidThrowingNullPointerException----------------------------------
--- A Measure instance if the class violates AvoidThrowingNullPointerException .
rule MeasureAvoidThrowingNullPointerException(c : java!ClassInstanceCreation) {
425
426
427
428
429
430
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
431
432
			name <- 'AvoidThrowingNullPointerException',
			shortDescription <- 'Avoid throwing NullPointerExceptions manually. These are confusing because most people will assume that the virtual machine threw it'
433
		),
434
435
		measurement: smm!DirectMeasurement (
			error <- 'AvoidThrowingNullPointerException is detected in ' + c.originalCompilationUnit.name
436
437
438
439
440
441
		)
	do {
		noc; 
	}
}

442
443
--- A Measure instance if the class violates the rule 'AvoidUsingShortType'
rule MeasureAvoidUsingShortType(typeShort : java!VariableDeclarationStatement) {
444
445
	to
		om: smm!ObservedMeasure (
446
			measure <- noc,
447
448
			measurements <- measurement
		),
449
450
451
452
453
454
455
		noc: smm!DimensionalMeasure (
			name <- 'Avoid using short type',
			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.'
456
457
		),
		measurement: smm!DirectMeasurement (
458
				error <- 'The class ' + typeShort.originalCompilationUnit.name + ' has \'short\' type variable.'
459
460
		)
	do {
461
		noc;
462
463
464
	}
}

465
466
--- A Measure instance if the class violates the rule CloneMethodMustBePublic.
rule MeasureCloneMethodMustBePublic(w: java!MethodDeclaration) {
467
468
469
470
471
472
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
473
474
			name <- 'CloneMethodMustBePublic',
			shortDescription <- ': Clone Method Must Be Public'
475
476
		),
		measurement: smm!DirectMeasurement (
477
			error <- ' class '+w.originalCompilationUnit.name+ ' has a clone methode witch need to be public '
478
479
480
481
482
483
		)
	do {
		noc; 
	}
}

484
485
--- Creates a measure instance when a bad word is found in a comment
rule MeasureCommentContent(element: Sequence(String)){
486
487
	to
		om: smm!ObservedMeasure (
488
			measure <- commentContent,
489
490
			measurements <- measurement
		),
491
492
493
		commentContent: smm!DimensionalMeasure (
			name <- 'CommentContent',
			shortDescription <- 'A rule for the politically correct… we don’t want to offend anyone.'
494
495
		),
		measurement: smm!DirectMeasurement (
496
			error <- 'The words ' + element +' were found in a comment '	
497
		)
498
499
500
		do {
			commentContent;
		}
501
502
}

503
504
--- Creates a measure instance for each element that violates the rule : CommentRequired
rule MeasureCommentRequired(element: java!BodyDeclaration, violatedProperties: Set(String)) {
505
506
	to
		om: smm!ObservedMeasure (
507
			measure <- commentRequired,
508
509
			measurements <- measurement
		),
510
511
512
		commentRequired: smm!DimensionalMeasure (
			name <- 'CommentRequired',
			shortDescription <- 'Denotes whether comments are required (or unwanted) for specific language elements.'
513
514
		),
		measurement: smm!DirectMeasurement (
515
			error <- 'Violated the properties  ' + violatedProperties + ' in Class: ' + element.originalCompilationUnit.name + ' -> ' + element.oclType().name + ': ' + element.modifier.visibility + ' ' + element.getBodyDeclarationName()
516
		)
517
518
519
520
521
522
523
524
525
		do {
		commentRequired; 
		}
}

-- ------------------------------------------- MeasureCompareObjectsWithEquals  ---------------------------------------------
--- A measure instance if the class violates the rule MeasureCompareObjectsWithEquals.
rule MeasureCompareObjectsWithEquals(expression : java!InfixExpression) {
	to
526
527
528
529
530
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
531
532
533
			name <- 'CompareObjectsWithEquals',
			shortDescription <- 'Use equals() to compare object references; avoid comparing them with ==.'
		
534
535
		),
		measurement: smm!DirectMeasurement (			
536
			error<-'The Class '+ expression.originalCompilationUnit.name + ' is using == instead of equals() to compare objects.'
537
		)
538
		
539
540
541
	do {
		noc; 
	}
542
}	 
543

544
545
546
-- -----------------------------------------DoNotCallGarbageCollectionExplicitly----------------------------------------------
--- A Measure instance if the class violate the rule DoNotCallGarbageCollectionExplicitly
rule MeasureDoNotCallGarbageCollectionExplicitly(method : java!MethodInvocation) {
547
548
549
550
551
552
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
553
554
			name <- 'DoNotCallGarbageCollectionExplicitly',
			shortDescription <- 'Calls to System.gc(), Runtime.getRuntime().gc(), and System.runFinalization() are not advised.'
555
		),
556
557
		measurement: smm!DirectMeasurement (
			error<- 'Garbage collector is called explicitly in ' + method.originalCompilationUnit.name
558
559
		)
	do {
560
		noc;
561
562
563
	}
}

564
565
566
567
-- ----------------------------------------- DoNotCallSystemExit----------------------------------------------
--- A Measure instance if the class violates the rule DoNotCallSystemExit.
rule MeasureDoNotCallSystemExit(invocation : java!MethodInvocation) {
	to
568
569
570
571
572
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
573
574
575
			name <- 'DoNotCallSystemExit',
			shortDescription <- 'Applications should not call System.exit(), since only the web container or the application server should stop the JVM'
		
576
577
		),
		measurement: smm!DirectMeasurement (			
578
			error<- 'Do not call ' + invocation.method.getMethodClassName() + '.' + invocation.method.name + ' in the file ' + invocation.originalCompilationUnit.name
579
580
581
582
583
584
		)
	do {
		noc; 
	}
}

585
586
587
588
-- ------------------------------------------- DoNotExtendJavaLangError  ---------------------------------------------
--- A Measure instance if the class violates the rule DoNotExtendJavaLangError.
rule MeasureDoNotExtendJavaLangError(variable : java!ClassDeclaration) {
	to
589
590
591
592
593
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
594
595
596
			name <- 'DoNotExtendJavaLangError ',
			shortDescription <- 'Errors are system exceptions. Do not extend them.'
		
597
		),
598
599
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ variable.name + ' Do not extend Error, Errors are system exceptions.'
600
		)
601
		
602
603
604
605
606
	do {
		noc; 
	}
}

607
608
609
-- ------------------------------------------- DoNotExtendJavaLangThrowable  ---------------------------------------------
--- A Measure instance if the class violates the rule DoNotExtendJavaLangThrowable.
rule MeasureDoNotExtendJavaLangThrowable(variable : java!ClassDeclaration) {
610
611
612
613
614
615
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
616
617
618
			name <- 'DoNotExtendJavaLangThrowable ',
			shortDescription <- 'Extend Exception or RuntimeException instead of Throwable.'
		
619
620
		),
		measurement: smm!DirectMeasurement (			
621
			error<-'In the Class '+ variable.name + ' should not extend Throwable but RuntimeException or Exception .'
622
		)
623
		
624
625
626
627
628
	do {
		noc; 
	}
}

629
630
--- creates a new Measure when Thread.run() is used instead of Thread.start()
rule MeasureDontCallThreadRun(method : java!MethodDeclaration) {
631
632
633
634
635
636
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
637
638
			name <- 'Don t call Thread.run()',
			shortDescription <- 'Explicitly calling Thread.run() method will execute in the caller s thread of control. Instead, call Thread.start() for the intended behavior.'		
639
		),
640
641
		measurement: smm!DirectMeasurement (			
			error<-'The class '+ method.originalCompilationUnit.name + ' violates the rule don t call Thread.run().'
642
643
644
645
646
647
		)
	do {
		noc; 
	}
}

648
649
650
-- ----------------------------------------- MeasureDontImportSun----------------------------------------------
--- A Measure instance if the class violate the rule DontImportSun
rule MeasureDontImportSun(p : java!CompilationUnit) {
651
652
	to
		om: smm!ObservedMeasure (
653
654
655
656
657
658
659
660
661
662
				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)
			)
663
	do {
664
		noc; 
665
666
667
	}
}

668
669
--- Creates a measure instance when a for loop uses a float as loop indice 
rule MeasureDontUseFloatTypeForLoopIndices(){
670
671
	to
		om: smm!ObservedMeasure (
672
			measure <- dontUseFloatTypeForLoopIndices,
673
674
			measurements <- measurement
		),
675
676
677
		dontUseFloatTypeForLoopIndices: smm!DimensionalMeasure (
			name <- 'DontUseFloatTypeForLoopIndices()',
			shortDescription <- 'Don’t use floating point for loop indices.'
678
679
		),
		measurement: smm!DirectMeasurement (
680
			error <- 'Use integer instead of floats as loop indice'	
681
682
		)
		do {
683
			dontUseFloatTypeForLoopIndices;
684
		}
685
	
686
}
687
688
689
690

-- -----------------------------------------EmptyCatchBlock----------------------------------------------
--- A Measure instance if the class violate the rule EmptyCatchBlock
rule MeasureEmptyCatchBlock(catch : java!CatchClause) {
691
692
	to
		om: smm!ObservedMeasure (
693
			measure <- noc,
694
695
			measurements <- measurement
		),
696
697
698
		noc: smm!DimensionalMeasure (
			name <- 'EmptyCatchBlock',
			shortDescription <- 'Empty Catch Block finds instances where an exception is caught, but nothing is done. In most circumstances, this swallows an exception which should either be acted on or reported.'
699
700
		),
		measurement: smm!DirectMeasurement (
701
			error<- 'Empty catch block in ' + catch.originalCompilationUnit.name
702
		)
703
704
705
	do {
		noc;
	}
706
707
}

708
709
710
-- ------------------- EmptyFinalizer----------------------------------
--- A measure instance if the class violates the rule EmptyFinalizer.
rule MeasureEmptyFinalizer(finalizeMethod : java!MethodDeclaration) {
711
712
	to
		om: smm!ObservedMeasure (
713
			measure <- noc,
714
715
			measurements <- measurement
		),
716
717
718
		noc: smm!DimensionalMeasure (
			name <- 'EmptyFinalizer',
			shortDescription <- ': Avoid empty Finalizer  - what s the point?'
719
720
		),
		measurement: smm!DirectMeasurement (
721
			error <- 'EmptyFinalizer is detected in ' + finalizeMethod.originalCompilationUnit.name
722
		)
723
724
725
	do {
		noc; 
	}
726
727
}

728
729
730
-- ------------------- EmptyFinallyBlock----------------------------------
--- A measure instance if the class violates the rule EmptyFinallyBlock.
rule MeasureEmptyFinallyBlock(finallyBlock : java!TryStatement) {
731
732
733
734
735
736
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
737
738
			name <- 'EmptyFinallyBlock',
			shortDescription <- ': Avoid empty Finally blocks - what s the point?'
739
740
		),
		measurement: smm!DirectMeasurement (
741
			error <- 'EmptyFinallyBlock is detected in ' + finallyBlock.originalCompilationUnit.name
742
743
		)
	do {
744
		noc; 
745
746
747
	}
}

748
749
--- A Measure instance if the class violates the rule EmptyInitializer.
rule MeasureEmptyInitializer(w: java!Initializer) {
750
751
752
753
754
755
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
756
757
			name <- 'EmptyInitializer',
			shortDescription <- ': EmptyInitializer'
758
759
		),
		measurement: smm!DirectMeasurement (
760
			error <- ' class '+w.originalCompilationUnit.name +' hase an empty Initializer! do not declare an EmptyInitializer, EmptyInitializer! this block need to be deleted'
761
762
		)
	do {
763
		noc; 
764
765
766
	}
}

767
768

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

787
788
789
-- ---------------------EmptySwitchStatement---------------------------------------------
--- A Measure instance if the class violates the rule 'EmptySwitchStatement'
rule MeasureEmptySwitchStatement(switchStatement: java!SwitchStatement) {
790
791
792
793
794
795
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
796
797
			name <- 'Empty Switch Statement ',
			shortDescription <- 'Empty Switch statements serve no purpose and should be removed.'
798
		),
799
800
		measurement: smm!DirectMeasurement (
				error <- 'EmptyswitchStatement is detected in ' + switchStatement.originalCompilationUnit.name
801
802
		)
	do {
803
		noc;
804
805
806
	}
}

807
808
809
-- ------------------------------EmptySynchronizedBlock---------------------------------------------
--- A Measure instance if the class violates the rule 'EmptySynchronizedBlock'
rule MeasureEmptySynchronizedBlock(synchronizedBlock: java!SynchronizedStatement) {
810
811
812
813
814
815
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
816
817
			name <- 'Empty Synchronized Block ',
			shortDescription <- 'Empty Synchronized Block serve no purpose and should be removed.'
818
		),
819
820
		measurement: smm!DirectMeasurement (
				error <- 'EmptySynchronizedBlock is detected in ' + synchronizedBlock.originalCompilationUnit.name
821
822
		)
	do {
823
		noc;
824
825
826
	}
}

827
828
829
-- ------------------- EmptyTryBlock----------------------------------
--- A measure instance if the class violates the rule EmptyTryBlock.
rule MeasureEmptyTryBlock(t : java!TryStatement) {
830
831
832
833
834
835
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
836
837
			name <- 'EmptyTryBlock',
			shortDescription <- ': Avoid empty try blocks - what s the point?'
838
		),
839
840
		measurement: smm!DirectMeasurement (
			error <- 'EmptyTryBlock is detected in ' + t.originalCompilationUnit.name
841
842
843
844
845
846
		)
	do {
		noc; 
	}
}

847
848
849
-- -------------------EmptyWhileStmt----------------------------------
--- A measure instance if the class violates the rule EmptyWhileStmt.
rule MeasureEmptyWhileStmt(w : java!WhileStatement) {
850
851
852
853
854
855
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
856
857
			name <- 'EmptyWhileStmt',
			shortDescription <- ': Empty While Statement finds all instances where a while statement does nothing.'
858
		),
859
860
		measurement: smm!DirectMeasurement (
			error <- 'EmptyWhileStmt is detected in  ' + w.originalCompilationUnit.name
861
862
863
864
		)
	do {
		noc; 
	}
865
866
867
868
}

--- A Measure instance if the class violates the rule ExcessiveClassLength.
rule MeasureExcessiveClassLength(w: java!MethodDeclaration) {
869
870
871
872
873
874
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
875
876
			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'
877
		),
878
879
		measurement: smm!DirectMeasurement (
			error <- ' class '+w.originalCompilationUnit.name+ ' has a block with more than 1000 line of code per a method it may need a separation in the code'
880
881
882
883
		)
	do {
		noc; 
	}
884
}
885

886
887
888
-- ------------------------------------------- ExcessiveImports ---------------------------------------------
--- creates a new Measure when a class has more than 4 imports
rule MeasureExcessiveImports(i : java!CompilationUnit) {
889
890
891
892
893
894
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
895
896
			name <- 'ExcessiveImports',
			shortDescription <- 'A high number of imports can indicate a high degree of coupling within an object. This rule counts the number of unique imports and reports a violation if the count is above the user-specified threshold.'		
897
898
		),
		measurement: smm!DirectMeasurement (			
899
900
			error<-'The class '+ i.name + ' has an excessive imports.',
			value<- i.imports.size()
901
902
903
904
905
906
		)
	do {
		noc; 
	}
}

907
908
909
-- ------------------------------------------- MeasureExtendsObject  ---------------------------------------------
--- A Measure instance if the class violates the rule ExtendsObject.
rule MeasureExtendsObject(variable : java!ClassDeclaration) {
910
911
912
913
914
915
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
916
917
			name <- 'ExtendsObject',
			shortDescription <- 'No need to explicitly extend Object.'
918
919
920
		
		),
		measurement: smm!DirectMeasurement (			
921
			error<-'In the Class '+ variable.name + ' No need to explicitly extend Object.'
922
923
924
925
926
		)
		
	do {
		noc; 
	}
927
}
928

929
930
931
-- ----------------------------------------- FieldDeclarationsShouldBeAtStartOfClass----------------------------------------------
--- A Measure instance if the class violates the rule FieldDeclarationsShouldBeAtStartOfClass.
rule MeasureFieldDeclarationsShouldBeAtStartOfClass(class: java!ClassDeclaration) {
932
933
934
935
936
937
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
938
939
			name <- 'FieldDeclarationsShouldBeAtStartOfClass',
			shortDescription <- 'Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes.'
940
		),
941
942
		measurement: smm!DirectMeasurement (			
			error<- 'Some of the fields of the class ' + class.name + ' are not declared at the top'
943
944
945
946
947
		)
	do {
		noc; 
	}
}
948
949
950
951
952

-- ------------------------------------------- MeasureFinalFieldCouldBeStatic  ---------------------------------------------
--- A Measure instance if the class violates the rule MeasureFinalFieldCouldBeStatic.
rule MeasureFinalFieldCouldBeStatic(field : java!FieldDeclaration) {
	to
953
954
955
956
957
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
958
959
			name <- 'FinalFieldCouldBeStatic',
			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.'
960
961
962
		
		),
		measurement: smm!DirectMeasurement (			
963
			error<-'The field '+ field.fragments->collect(i | i.name)->first() + ' could be static in the class '  + field.originalCompilationUnit.name +'.'
964
		)
965
		
966
967
968
	do {
		noc; 
	}
969
970
971
972
973
}

-- ----------------------------------------- ForLoopVariableCount----------------------------------------------
--- A Measure instance if the class violates the rule ForLoopVariableCount.
rule MeasureForLoopVariableCount(forStatement: java!ForStatement) {
974
975
976
977
978
979
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
980
981
982
			name <- 'ForLoopVariableCount',
			shortDescription <- 'Having a lot of control variables in a "for" loop makes it harder to see what range of values the loop iterates over.'

983
984
		),
		measurement: smm!DirectMeasurement (			
985
			error<- 'A "for" loop use more than one local variable in the file ' + forStatement.originalCompilationUnit.name
986
987
988
989
990
991
		)
	do {
		noc; 
	}
}

992
993
994
-- -----------------------------------------GenericsNaming----------------------------------------------
--- A Measure instance if the class violate the rule GenericsNaming
rule MeasureGenericsNaming(type :java!TypeParameter) {
995
996
997
998
999
1000
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (