analysis.atl 67.4 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(),
Gerson Sunyé's avatar
Gerson Sunyé committed
82
		-- #FIXME: thisModule.avoidInstantiatingObjectsInLoops(),
83
84
85
86
		thisModule.avoidPrintStackTrace(),
		thisModule.avoidRethrowingException(),
		thisModule.avoidUsingShortType(),
		thisModule.emptyStatementBlock(),
87
88
		thisModule.inefficientEmptyStringCheck(),
		thisModule.inefficientEmptyStringCheck2(),
89
		-- #FIXME:
Gerson Sunyé's avatar
Gerson Sunyé committed
90
		-- thisModule.insufficientStringBufferDeclaration(),
91
		thisModule.integerInstantiation(),
92
		-- #FIXME:
Gerson Sunyé's avatar
Gerson Sunyé committed
93
94
		-- thisModule.startsWith(),
		thisModule.tooFewBranchesForASwitchStatement(),
Gerson Sunyé's avatar
Gerson Sunyé committed
95
		-- #FIXME: thisModule.useArraysAsList(),
96
97
98
99
100
101
		thisModule.useIndexOfChar(),
		thisModule.uselessStringValueOf(),
		
		-- Documentation rules
		--
		thisModule.commentContent(),
102
		thisModule.commentRequired(),
103
104
105
106
107
108
109
110

		-- Error prone rules
		--
		thisModule.avoidCallingFinalize(),
		thisModule.AvoidCatchingNPE(),
		thisModule.avoidCatchingThrowable(),
		thisModule.AvoidEnumAsIdentifier(),
		thisModule.CloneMethodMustBePublic(),
111
		thisModule.detachedTestCase(),
112
		thisModule.doNotCallGarbageCollectionExplicitly(),
113
		thisModule.doNotCallSystemExit(),
114
115
116
117
118
119
120
121
		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
122
123
		thisModule.emptyWhileStmt(),
		thisModule.finalizeShouldBeProtected(),
124
125
		thisModule.importFromSamePackage(),
		thisModule.missingBreakInSwitch(),
126
		thisModule.nullAssignment(),
127
		thisModule.suspiciousEqualsMethodName(),
128
		thisModule.suspiciousHashcodeMethodName(),
129
		thisModule.testClassWithoutTest(),
130
131
132
133
		thisModule.UnconditionalIfStatement(),
		thisModule.UseProperClassLoader(),
		
		-- Best practices rules
Gerson Sunyé's avatar
Gerson Sunyé committed
134
		-- #FIXME: thisModule.arrayIsStoredDirectly(),
Arthur Liégeois's avatar
Arthur Liégeois committed
135
		thisModule.avoidReassigningParameters(),
Oussama EL KOURRI's avatar
Oussama EL KOURRI committed
136
		thisModule.avoidStringBufferField(),
137
		thisModule.forLoopVariableCount(),
138
		thisModule.oneDeclarationPerLine(),
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
		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(),
		
		
};


163

164
165
166
167
--- 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) {
168
169
	to
		om: smm!ObservedMeasure (
170
			measure <- missingBreakInSwitch,
171
172
			measurements <- measurement
		),
173
174
175
		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.'
176
		),
177
178
179
180
181
		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)
		)
182
	do {
183
		missingBreakInSwitch; 
184
185
186
	}
}

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

207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
-- ------------------------------------------- ArrayIsStoredDirectly ---------------------------------------------
--- creates a measure when an array parameter of a method is directly used as a reference instead of storing it first
rule MeasureArrayIsStoredDirectly(s: java!MethodDeclaration){
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'ArrayIsStoredDirectly',
  			shortDescription <- 'Constructors and methods receiving arrays should clone objects and store the copy'
		),
		measurement: smm!DirectMeasurement (
			error <- s.name + ' has an array parameter that is not cloned before use'
		)
	do {
		noc;
	}
}

227
228
229
-- ------------------------------------------- AvoidCallingFinalize  ---------------------------------------------
--- A Measure instance if the class violates the rule LongVariable.
rule MeasureAvoidCallingFinalize(methode : java!MethodInvocation) {
230
231
232
233
234
235
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
236
237
			name <- 'AvoidCallingFinalize',
			shortDescription <- ': The method Object.finalize() is called by the garbage collector on an object when garbage collect... '
238
239
		),
		measurement: smm!DirectMeasurement (
240
			error <- 'finalize() is called in class' + methode.originalCompilationUnit.name 
241
242
243
244
245
246
		)
	do {
		noc; 
	}
}

247
248
--- A Measure instance if the class violates the rule AvoidCatchingNPE.
rule MeasureAvoidCatchingNPE(w: java!CatchClause) {
249
250
251
252
253
254
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
255
256
			name <- 'AvoidCatchingNPE',
			shortDescription <- ': Avoid Catching NullPointerExceptions'
257
258
		),
		measurement: smm!DirectMeasurement (
259
260
261
			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.'
262
263
264
265
266
267
		)
	do {
		noc; 
	}
}

268
269
270
-- -----------------------------------------AvoidCatchingThrowable----------------------------------------------
--- A Measure instance if the class violate the rule MisLeadingVariableName
rule MeasureAvoidCatchingThrowable(catch :java!CatchClause) {
271
272
273
274
275
276
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
277
278
			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.'
279
280
		),
		measurement: smm!DirectMeasurement (
281
			error<- 'Throwable ' + catch.exception.name + ' should not be catched.'
282
283
		)
	do {
284
		noc;
285
286
287
	}
}

288
289
--- A Measure instance if the class violates the rule AvoidEnumAsIdentifier.
rule MeasureAvoidEnumAsIdentifier(w: java!VariableDeclaration) {
290
291
292
293
294
295
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
296
297
			name <- 'AvoidEnumAsIdentifier',
			shortDescription <- ': Avoid Enum As Identifier'
298
299
		),
		measurement: smm!DirectMeasurement (
300
			error <- ' class '+w.originalCompilationUnit.name+ ' has a variable named to enum witch is a reserved name'
301
302
303
304
305
306
		)
	do {
		noc; 
	}
}

307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
-- ------------------------------------------- AvoidInstantiatingObjectInLoops ---------------------------------------------
--- creates a measure when an object is instantiated in a loop
rule MeasureAvoidInstantiatingObjectInLoops(s: java!Statement){
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'AvoidInstantiatingObjectsInLoops',
  			shortDescription <- 'New objects created within loops should be checked to see if they can created outside them and reused'
		),
		measurement: smm!DirectMeasurement (
			error <- s.originalCompilationUnit.name + ' has a loop with object instantiation inside'
		)
	do {
		noc;
	}
}

327
328
329
-- ----------------------------------------- AvoidPrefixingMethodParameters----------------------------------------------
--- A Measure instance if the class violates the rule AvoidPrefixingMethodParameters.
rule MeasureAvoidPrefixingMethodParameters(method: java!MethodDeclaration) {
330
331
332
333
334
335
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
336
337
			name <- 'AvoidPrefixingMethodParameters',
			shortDescription <- 'Prefixing parameters by ‘in’ or ‘out’ pollutes the name of the parameters and reduces code readability.'
338
339
		),
		measurement: smm!DirectMeasurement (			
340
			error<- 'Bad parameters : ' + method.getIncorrectParameters() + ', for the method ' + method.name + ' defined in the file ' + method.originalCompilationUnit.name
341
342
343
344
345
346
		)
	do {
		noc; 
	}
}

347
348
349
--- creates a new Measure when the method printStackTrace is used
rule MeasureAvoidPrintStackTrace(method : java!MethodInvocation) {
		to
350
351
352
353
354
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
355
356
			name <- 'Avoid print stack trace',
			shortDescription <- 'Avoid printStackTrace(); use a logger call instead.'		
357
		),
358
359
		measurement: smm!DirectMeasurement (			
			error<- 'The class '+ method.originalCompilationUnit.name + ' violates the rule avoid print stack trace.'
360
361
362
363
364
365
		)
	do {
		noc; 
	}
}

366
367
368
-- ----------------------------------------- AvoidReassigningParameters ----------------------------------------------
--- A Measure instance if the class violates the rule AvoidReassigningParameters.
rule MeasureAvoidReassigningParameters(assignment: java!SingleVariableAccess) {
369
370
371
372
373
374
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
375
376
			name <- 'AvoidReassigningParameters',
			shortDescription <- 'Reassigning values to incoming parameters is not recommended. Use temporary local variables instead.'
377
378
		),
		measurement: smm!DirectMeasurement (			
379
			error<- assignment.leftHandSide.variable.name + ' should not be reassigned'
380
381
382
383
384
385
		)
	do {
		noc; 
	}
}

386
387
388
389
-- ------------------------------------------- AvoidRethrowingException  ---------------------------------------------
---A Measure instance if the class violates the rule AvoidRethrowingException.
rule MeasureAvoidRethrowingException(statement : java!TryStatement) {
 		to
390
391
392
393
394
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
395
396
397
398
			
			name <- 'AvoidRethrowingException ',
			shortDescription <- 'Avoid merely rethrowing an exception.'
		
399
		),
400
401
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ statement.originalCompilationUnit.name + ' an exception was caught and merely rethrown.'
402
403
404
405
		)
	do {
		noc; 
	}
406
407
408
409
410
}	 
	
-- ------------------------------------------- AvoidStringBufferField  ---------------------------------------------
--- A Measure instance if the class violates AvoidStringBufferField .
rule MeasureAvoidStringBufferField(declaration : java!FieldDeclaration) {
411
412
	to
		om: smm!ObservedMeasure (
413
			measure <- noc,
414
415
			measurements <- measurement
		),
416
417
418
		noc: smm!DimensionalMeasure (
			name <- 'AvoidStringBufferField',
			shortDescription <- ': StringBuffers/StringBuilders can grow considerably, and so may become a source of memory leaksif ...'
419
420
		),
		measurement: smm!DirectMeasurement (
421
			error <- 'AvoidStringBufferField is detected in ' + declaration.originalCompilationUnit.name 
422
423
		)
	do {
424
		noc; 
425
426
427
	}
}

428
429
--- creates a new Measure when Thread.run() is used instead of Thread.start()
rule measureAvoidThreadGroup(variable : java!VariableDeclarationStatement) {
430
431
432
433
434
435
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
436
437
			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.'		
438
439
		),
		measurement: smm!DirectMeasurement (			
440
			error<-'The class '+ variable.originalCompilationUnit.name + ' violates the rule avoid thread group.'
441
442
443
444
445
446
447
		)
		
	do {
		noc; 
	}
}

448
449
450
451
-- ------------------------------------------- AvoidThrowingNewInstanceOfSameException ---------------------------------------------
--- A Measure instance if the class violates the rule 'AvoidThrowingNewInstanceOfSameException'.
rule MeasureAvoidThrowingNewInstanceOfSameException(catch : java!CatchClause) {
    to
452
453
454
455
456
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
457
458
			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.'		
459
460
		),
		measurement: smm!DirectMeasurement (			
461
			error <-'The class '+ catch.originalCompilationUnit.name + ' has a method that rethrows a caught exception wrapped inside a new instance of the same type.'
462
463
464
465
466
467
		)
	do {
		noc; 
	}
}

468
469
470
-- ------------------- AvoidThrowingNullPointerException----------------------------------
--- A Measure instance if the class violates AvoidThrowingNullPointerException .
rule MeasureAvoidThrowingNullPointerException(c : java!ClassInstanceCreation) {
471
472
473
474
475
476
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
477
478
			name <- 'AvoidThrowingNullPointerException',
			shortDescription <- 'Avoid throwing NullPointerExceptions manually. These are confusing because most people will assume that the virtual machine threw it'
479
		),
480
481
		measurement: smm!DirectMeasurement (
			error <- 'AvoidThrowingNullPointerException is detected in ' + c.originalCompilationUnit.name
482
483
484
485
486
487
		)
	do {
		noc; 
	}
}

488
489
--- A Measure instance if the class violates the rule 'AvoidUsingShortType'
rule MeasureAvoidUsingShortType(typeShort : java!VariableDeclarationStatement) {
490
491
	to
		om: smm!ObservedMeasure (
492
			measure <- noc,
493
494
			measurements <- measurement
		),
495
496
497
498
499
500
501
		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.'
502
503
		),
		measurement: smm!DirectMeasurement (
504
				error <- 'The class ' + typeShort.originalCompilationUnit.name + ' has \'short\' type variable.'
505
506
		)
	do {
507
		noc;
508
509
510
	}
}

511
512
--- A Measure instance if the class violates the rule CloneMethodMustBePublic.
rule MeasureCloneMethodMustBePublic(w: java!MethodDeclaration) {
513
514
515
516
517
518
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
519
520
			name <- 'CloneMethodMustBePublic',
			shortDescription <- ': Clone Method Must Be Public'
521
522
		),
		measurement: smm!DirectMeasurement (
523
			error <- ' class '+w.originalCompilationUnit.name+ ' has a clone methode witch need to be public '
524
525
526
527
528
529
		)
	do {
		noc; 
	}
}

530
531
--- Creates a measure instance when a bad word is found in a comment
rule MeasureCommentContent(element: Sequence(String)){
532
533
	to
		om: smm!ObservedMeasure (
534
			measure <- commentContent,
535
536
			measurements <- measurement
		),
537
538
539
		commentContent: smm!DimensionalMeasure (
			name <- 'CommentContent',
			shortDescription <- 'A rule for the politically correct… we don’t want to offend anyone.'
540
541
		),
		measurement: smm!DirectMeasurement (
542
			error <- 'The words ' + element +' were found in a comment '	
543
		)
544
545
546
		do {
			commentContent;
		}
547
548
}

549
550
--- Creates a measure instance for each element that violates the rule : CommentRequired
rule MeasureCommentRequired(element: java!BodyDeclaration, violatedProperties: Set(String)) {
551
552
	to
		om: smm!ObservedMeasure (
553
			measure <- commentRequired,
554
555
			measurements <- measurement
		),
556
557
558
		commentRequired: smm!DimensionalMeasure (
			name <- 'CommentRequired',
			shortDescription <- 'Denotes whether comments are required (or unwanted) for specific language elements.'
559
560
		),
		measurement: smm!DirectMeasurement (
561
			error <- 'Violated the properties  ' + violatedProperties + ' in Class: ' + element.originalCompilationUnit.name + ' -> ' + element.oclType().name + ': ' + element.modifier.visibility + ' ' + element.getBodyDeclarationName()
562
		)
563
564
565
566
567
568
569
570
571
		do {
		commentRequired; 
		}
}

-- ------------------------------------------- MeasureCompareObjectsWithEquals  ---------------------------------------------
--- A measure instance if the class violates the rule MeasureCompareObjectsWithEquals.
rule MeasureCompareObjectsWithEquals(expression : java!InfixExpression) {
	to
572
573
574
575
576
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
577
578
579
			name <- 'CompareObjectsWithEquals',
			shortDescription <- 'Use equals() to compare object references; avoid comparing them with ==.'
		
580
581
		),
		measurement: smm!DirectMeasurement (			
582
			error<-'The Class '+ expression.originalCompilationUnit.name + ' is using == instead of equals() to compare objects.'
583
		)
584
		
585
586
587
	do {
		noc; 
	}
588
}	 
589

590
591
592
-- -----------------------------------------DoNotCallGarbageCollectionExplicitly----------------------------------------------
--- A Measure instance if the class violate the rule DoNotCallGarbageCollectionExplicitly
rule MeasureDoNotCallGarbageCollectionExplicitly(method : java!MethodInvocation) {
593
594
595
596
597
598
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
599
600
			name <- 'DoNotCallGarbageCollectionExplicitly',
			shortDescription <- 'Calls to System.gc(), Runtime.getRuntime().gc(), and System.runFinalization() are not advised.'
601
		),
602
603
		measurement: smm!DirectMeasurement (
			error<- 'Garbage collector is called explicitly in ' + method.originalCompilationUnit.name
604
605
		)
	do {
606
		noc;
607
608
609
	}
}

610
611
612
613
-- ----------------------------------------- DoNotCallSystemExit----------------------------------------------
--- A Measure instance if the class violates the rule DoNotCallSystemExit.
rule MeasureDoNotCallSystemExit(invocation : java!MethodInvocation) {
	to
614
615
616
617
618
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
619
620
621
			name <- 'DoNotCallSystemExit',
			shortDescription <- 'Applications should not call System.exit(), since only the web container or the application server should stop the JVM'
		
622
623
		),
		measurement: smm!DirectMeasurement (			
624
			error<- 'Do not call ' + invocation.method.getMethodClassName() + '.' + invocation.method.name + ' in the file ' + invocation.originalCompilationUnit.name
625
626
627
628
629
630
		)
	do {
		noc; 
	}
}

631
632
633
634
-- ------------------------------------------- DoNotExtendJavaLangError  ---------------------------------------------
--- A Measure instance if the class violates the rule DoNotExtendJavaLangError.
rule MeasureDoNotExtendJavaLangError(variable : java!ClassDeclaration) {
	to
635
636
637
638
639
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
640
641
642
			name <- 'DoNotExtendJavaLangError ',
			shortDescription <- 'Errors are system exceptions. Do not extend them.'
		
643
		),
644
645
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ variable.name + ' Do not extend Error, Errors are system exceptions.'
646
		)
647
		
648
649
650
651
652
	do {
		noc; 
	}
}

653
654
655
-- ------------------------------------------- DoNotExtendJavaLangThrowable  ---------------------------------------------
--- A Measure instance if the class violates the rule DoNotExtendJavaLangThrowable.
rule MeasureDoNotExtendJavaLangThrowable(variable : java!ClassDeclaration) {
656
657
658
659
660
661
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
662
663
664
			name <- 'DoNotExtendJavaLangThrowable ',
			shortDescription <- 'Extend Exception or RuntimeException instead of Throwable.'
		
665
666
		),
		measurement: smm!DirectMeasurement (			
667
			error<-'In the Class '+ variable.name + ' should not extend Throwable but RuntimeException or Exception .'
668
		)
669
		
670
671
672
673
674
	do {
		noc; 
	}
}

675
676
--- creates a new Measure when Thread.run() is used instead of Thread.start()
rule MeasureDontCallThreadRun(method : java!MethodDeclaration) {
677
678
679
680
681
682
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
683
684
			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.'		
685
		),
686
687
		measurement: smm!DirectMeasurement (			
			error<-'The class '+ method.originalCompilationUnit.name + ' violates the rule don t call Thread.run().'
688
689
690
691
692
693
		)
	do {
		noc; 
	}
}

694
695
696
-- ----------------------------------------- MeasureDontImportSun----------------------------------------------
--- A Measure instance if the class violate the rule DontImportSun
rule MeasureDontImportSun(p : java!CompilationUnit) {
697
698
	to
		om: smm!ObservedMeasure (
699
700
701
702
703
704
705
706
707
708
				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)
			)
709
	do {
710
		noc; 
711
712
713
	}
}

714
715
--- Creates a measure instance when a for loop uses a float as loop indice 
rule MeasureDontUseFloatTypeForLoopIndices(){
716
717
	to
		om: smm!ObservedMeasure (
718
			measure <- dontUseFloatTypeForLoopIndices,
719
720
			measurements <- measurement
		),
721
722
723
		dontUseFloatTypeForLoopIndices: smm!DimensionalMeasure (
			name <- 'DontUseFloatTypeForLoopIndices()',
			shortDescription <- 'Don’t use floating point for loop indices.'
724
725
		),
		measurement: smm!DirectMeasurement (
726
			error <- 'Use integer instead of floats as loop indice'	
727
728
		)
		do {
729
			dontUseFloatTypeForLoopIndices;
730
		}
731
	
732
}
733
734
735
736

-- -----------------------------------------EmptyCatchBlock----------------------------------------------
--- A Measure instance if the class violate the rule EmptyCatchBlock
rule MeasureEmptyCatchBlock(catch : java!CatchClause) {
737
738
	to
		om: smm!ObservedMeasure (
739
			measure <- noc,
740
741
			measurements <- measurement
		),
742
743
744
		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.'
745
746
		),
		measurement: smm!DirectMeasurement (
747
			error<- 'Empty catch block in ' + catch.originalCompilationUnit.name
748
		)
749
750
751
	do {
		noc;
	}
752
753
}

754
755
756
-- ------------------- EmptyFinalizer----------------------------------
--- A measure instance if the class violates the rule EmptyFinalizer.
rule MeasureEmptyFinalizer(finalizeMethod : java!MethodDeclaration) {
757
758
	to
		om: smm!ObservedMeasure (
759
			measure <- noc,
760
761
			measurements <- measurement
		),
762
763
764
		noc: smm!DimensionalMeasure (
			name <- 'EmptyFinalizer',
			shortDescription <- ': Avoid empty Finalizer  - what s the point?'
765
766
		),
		measurement: smm!DirectMeasurement (
767
			error <- 'EmptyFinalizer is detected in ' + finalizeMethod.originalCompilationUnit.name
768
		)
769
770
771
	do {
		noc; 
	}
772
773
}

774
775
776
-- ------------------- EmptyFinallyBlock----------------------------------
--- A measure instance if the class violates the rule EmptyFinallyBlock.
rule MeasureEmptyFinallyBlock(finallyBlock : java!TryStatement) {
777
778
779
780
781
782
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
783
784
			name <- 'EmptyFinallyBlock',
			shortDescription <- ': Avoid empty Finally blocks - what s the point?'
785
786
		),
		measurement: smm!DirectMeasurement (
787
			error <- 'EmptyFinallyBlock is detected in ' + finallyBlock.originalCompilationUnit.name
788
789
		)
	do {
790
		noc; 
791
792
793
	}
}

794
795
--- A Measure instance if the class violates the rule EmptyInitializer.
rule MeasureEmptyInitializer(w: java!Initializer) {
796
797
798
799
800
801
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
802
803
			name <- 'EmptyInitializer',
			shortDescription <- ': EmptyInitializer'
804
805
		),
		measurement: smm!DirectMeasurement (
806
			error <- ' class '+w.originalCompilationUnit.name +' hase an empty Initializer! do not declare an EmptyInitializer, EmptyInitializer! this block need to be deleted'
807
808
		)
	do {
809
		noc; 
810
811
812
	}
}

813
814

--- A Measure instance if the class violates the rule 'EmptyStatementBlock'
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
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;
	}
}

833
834
835
-- ---------------------EmptySwitchStatement---------------------------------------------
--- A Measure instance if the class violates the rule 'EmptySwitchStatement'
rule MeasureEmptySwitchStatement(switchStatement: java!SwitchStatement) {
836
837
838
839
840
841
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
842
843
			name <- 'Empty Switch Statement ',
			shortDescription <- 'Empty Switch statements serve no purpose and should be removed.'
844
		),
845
846
		measurement: smm!DirectMeasurement (
				error <- 'EmptyswitchStatement is detected in ' + switchStatement.originalCompilationUnit.name
847
848
		)
	do {
849
		noc;
850
851
852
	}
}

853
854
855
-- ------------------------------EmptySynchronizedBlock---------------------------------------------
--- A Measure instance if the class violates the rule 'EmptySynchronizedBlock'
rule MeasureEmptySynchronizedBlock(synchronizedBlock: java!SynchronizedStatement) {
856
857
858
859
860
861
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
862
863
			name <- 'Empty Synchronized Block ',
			shortDescription <- 'Empty Synchronized Block serve no purpose and should be removed.'
864
		),
865
866
		measurement: smm!DirectMeasurement (
				error <- 'EmptySynchronizedBlock is detected in ' + synchronizedBlock.originalCompilationUnit.name
867
868
		)
	do {
869
		noc;
870
871
872
	}
}

873
874
875
-- ------------------- EmptyTryBlock----------------------------------
--- A measure instance if the class violates the rule EmptyTryBlock.
rule MeasureEmptyTryBlock(t : java!TryStatement) {
876
877
878
879
880
881
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
882
883
			name <- 'EmptyTryBlock',
			shortDescription <- ': Avoid empty try blocks - what s the point?'
884
		),
885
886
		measurement: smm!DirectMeasurement (
			error <- 'EmptyTryBlock is detected in ' + t.originalCompilationUnit.name
887
888
889
890
891
892
		)
	do {
		noc; 
	}
}

893
894
895
-- -------------------EmptyWhileStmt----------------------------------
--- A measure instance if the class violates the rule EmptyWhileStmt.
rule MeasureEmptyWhileStmt(w : java!WhileStatement) {
896
897
898
899
900
901
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
902
903
			name <- 'EmptyWhileStmt',
			shortDescription <- ': Empty While Statement finds all instances where a while statement does nothing.'
904
		),
905
906
		measurement: smm!DirectMeasurement (
			error <- 'EmptyWhileStmt is detected in  ' + w.originalCompilationUnit.name
907
908
909
910
		)
	do {
		noc; 
	}
911
912
913
914
}

--- A Measure instance if the class violates the rule ExcessiveClassLength.
rule MeasureExcessiveClassLength(w: java!MethodDeclaration) {
915
916
917
918
919
920
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
921
922
			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'
923
		),
924
925
		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'
926
927
928
929
		)
	do {
		noc; 
	}
930
}
931

932
933
934
-- ------------------------------------------- ExcessiveImports ---------------------------------------------
--- creates a new Measure when a class has more than 4 imports
rule MeasureExcessiveImports(i : java!CompilationUnit) {
935
936
937
938
939
940
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
941
942
			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.'		
943
944
		),
		measurement: smm!DirectMeasurement (			
945
946
			error<-'The class '+ i.name + ' has an excessive imports.',
			value<- i.imports.size()
947
948
949
950
951
952
		)
	do {
		noc; 
	}
}

953
954
955
-- ------------------------------------------- MeasureExtendsObject  ---------------------------------------------
--- A Measure instance if the class violates the rule ExtendsObject.
rule MeasureExtendsObject(variable : java!ClassDeclaration) {
956
957
958
959
960
961
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
962
963
			name <- 'ExtendsObject',
			shortDescription <- 'No need to explicitly extend Object.'
964
965
966
		
		),
		measurement: smm!DirectMeasurement (			
967
			error<-'In the Class '+ variable.name + ' No need to explicitly extend Object.'
968
969
970
971
972
		)
		
	do {
		noc; 
	}
973
}
974

975
976
977
-- ----------------------------------------- FieldDeclarationsShouldBeAtStartOfClass----------------------------------------------
--- A Measure instance if the class violates the rule FieldDeclarationsShouldBeAtStartOfClass.
rule MeasureFieldDeclarationsShouldBeAtStartOfClass(class: java!ClassDeclaration) {
978
979
980
981
982
983
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
984
985
			name <- 'FieldDeclarationsShouldBeAtStartOfClass',
			shortDescription <- 'Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes.'
986
		),
987
988
		measurement: smm!DirectMeasurement (			
			error<- 'Some of the fields of the class ' + class.name + ' are not declared at the top'
989
990
991
992
993
		)
	do {
		noc; 
	}
}
994
995
996
997
998

-- ------------------------------------------- MeasureFinalFieldCouldBeStatic  ---------------------------------------------
--- A Measure instance if the class violates the rule MeasureFinalFieldCouldBeStatic.
rule MeasureFinalFieldCouldBeStatic(field : java!FieldDeclaration) {
	to
999
1000
1001
1002
1003
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
1004
1005
			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.'
1006
1007
1008
		
		),
		measurement: smm!DirectMeasurement (			
1009
			error<-'The field '+ field.fragments->collect(i | i.name)->first() + ' could be static in the class '  + field.originalCompilationUnit.name +'.'
1010
		)
1011
		
1012
1013
1014
	do {
		noc; 
	}
1015
1016
1017
1018
1019
}

-- ----------------------------------------- ForLoopVariableCount----------------------------------------------
--- A Measure instance if the class violates the rule ForLoopVariableCount.
rule MeasureForLoopVariableCount(forStatement: java!ForStatement) {
1020
1021
1022
1023
1024
1025
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
1026
1027
1028
			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.'

1029
1030
		),
		measurement: smm!DirectMeasurement (			
1031
			error<- 'A "for" loop use more than one local variable in the file ' + forStatement.originalCompilationUnit.name
1032
1033
1034
1035
1036
1037
		)
	do {
		noc; 
	}
}

1038
1039
1040
-- -----------------------------------------GenericsNaming----------------------------------------------
--- A Measure instance if the class violate the rule GenericsNaming
rule MeasureGenericsNaming(type :java!TypeParameter) {
1041
1042
1043
1044
1045
1046
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
1047
1048
			name <- 'GenericsNaming',
			shortDescription <- 'Names for references to generic values should be limited to a single uppercase letter.'
1049
1050
		),
		measurement: smm!DirectMeasurement (
1051
			error<- 'The generic type ' + type.name + ' should be limited to a single uppercase letter.'
1052
1053
		)
	do {
1054
		noc;
1055
1056
1057
	}
}

1058
1059
1060
-- ------------------------------------------- IfStmtsMustUseBraces ---------------------------------------------
--- creates a new Measure when a class that contains an if statement without braces.
rule MeasureIfStmtsMustUseBraces(i : java!IfStatement) {
1061
1062
1063
1064
1065
1066
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
1067
1068
			name <- 'If then Statement must use braces',
			shortDescription <- 'Deprecated Avoid using if statements without using braces to surround the code block. If the code formatting...'		
1069
		),
1070
1071
		measurement: smm!DirectMeasurement (			
			error <- 'The class ' + i.originalCompilationUnit.name +  ' has an if statement without braces. '
1072
1073
1074
1075
1076
1077
		)
	do {
		noc; 
	}
}

1078
1079
1080
-- -----------------------------------------ImportFromSamePackage----------------------------------------------
--- A Measure instance if the class violate the rule ImportFromSamePackage
rule MeasureImportFromSamePackage(import : java!ImportDeclaration) {
1081
1082
1083
1084
1085
1086
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
1087
1088
			name <- 'ImportFromSamePackage',
			shortDescription <- 'There is no need to import a type that lives in the same package.'
1089
1090
		),
		measurement: smm!DirectMeasurement (
1091
			error<- 'No need to import ' + import.importedElement.name + ' in ' + import.originalCompilationUnit.name
1092
		)
1093
1094
1095
1096
1097
	do {
		noc;
	}
}

1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
-- ----------------------------------------- InefficientEmptyStringCheck ----------------------------------------------
--- creates a measure when String.trim().isEmpty() is used to check if a string is empty
rule MeasureInefficientEmptyStringCheck(mi: java!Expression){
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'InefficientEmptyStringCheck',
  			shortDescription <- 'Inefficient way to check if a String is really blank as it creates a new String object just to check its size.'
		),
		measurement: smm!DirectMeasurement (
			error <- mi.originalCompilationUnit.name + ' has an inefficient empty string check'
		)
	do {
		noc;
	}
}

1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
--- insufficientStringBufferDeclaration 
--- #FIXME: Add comment
rule MeasureInsufficientStringBufferDeclaration(w: java!CompilationUnit) {
	to
		om: smm!ObservedMeasure (
				measure <- noc,
				measurements <- measurement
			),
			noc: smm!DimensionalMeasure (
				name <- 'insufficientStringBufferDeclaration',
				shortDescription <- ' : insufficientStringBufferDeclaration.'
			),
			measurement: smm!DirectMeasurement (
				error <- ' class'+ w.name+ 'has insufficientStringBufferDeclaration'
			)
1133
1134
1135
1136
1137
	do {
		noc; 
	}
}

1138
1139
1140
-- ------------------------------------------- IntegerInstantiation ---------------------------------------------
--- A Measure instance if the class violates the rule 'IntegerInstantiation'.
rule MeasureIntegerInstantiation(variable : java!CompilationUnit) {
1141
1142
1143
1144
1145
1146
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
1147
1148
			name <- 'IntegerInstantiation',
			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.'		
1149
		),
1150
1151
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ variable.name + ' an instantiation of Integer must be Integer.ValueOf().'
1152
		)
1153
		
1154
1155
1156
1157
1158
	do {
		noc; 
	}
}

1159
1160
1161
-- ------------------------------------------- LongInstantiation ---------------------------------------------
--- A Measure instance if the class violates the rule 'LongInstantiation'.
rule MeasureLongInstantiation(variable : java!CompilationUnit) {
1162
1163
1164
1165
1166
1167
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
1168
1169
			name <- 'LongInstantiation',
			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.'		
1170
		),
1171
1172
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ variable.name + ' an instantiation of Long must be Long.ValueOf().'
1173
		)
1174
		
1175
1176
1177
1178
1179
	do {
		noc; 
	}
}

1180
1181
1182
-- ------------------------------------------- LongVariable  ---------------------------------------------
--- A Measure instance if the variable violates the rule LongVariable.
rule MeasureLongVariable(variable : java!VariableDeclarationFragment) {
1183
1184
1185
1186
1187
1188
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
1189
1190
			name <- 'LongVariable',
			shortDescription <- ': Fields, formal arguments, or local variable names that are too long can make the code difficult '
1191
1192
		),
		measurement: smm!DirectMeasurement (
1193
			error <- variable.name + ' is too Long ' 
1194
1195
1196
1197
1198
1199
		)
	do {
		noc; 
	}
}

1200
1201
1202
-- -----------------------------------------MethodWithSameNameAsEnclosingClass----------------------------------------------
--- A Measure instance if the class violate the rule MethodWithSameNameAsEnclosingClass
rule MeasureMethodWithSameNameAsEnclosingClass(method : java!MethodDeclaration) {
1203
1204
1205
1206
1207
1208
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
1209
1210
			name <- 'MethodWithSameNameAsEnclosingClass',
			shortDescription <- 'Non-constructor methods should not have the same name as the enclosing class.'
1211
1212
		),
		measurement: smm!DirectMeasurement (
1213
			error<- 'Method ' + method.name + ' has the same name as ' + method.originalCompilationUnit.name + ' and is not a contructor.'
1214
1215
1216
1217
1218
1219
		)
	do {
		noc;
	}
}

1220
1221
1222
-- -----------------------------------------MisLeadingVariableName----------------------------------------------
--- A Measure instance if the class violate the rule MisLeadingVariableName
rule MeasureMisLeadingVariableName(variable :java!VariableDeclarationFragment) {
1223
1224
1225
1226
1227
1228
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
1229
1230
			name <- 'MisLeadingVariableName',
			shortDescription <- 'Detects when a non-field has a name starting with �m_�. This usually denotes a field and could be confusing.'
1231
1232
		),
		measurement: smm!DirectMeasurement (
1233
			error<- 'Variable ' + variable.name + ' should not start with �m_� as it is not a field.'
1234
1235
1236
1237
1238
		)
	do {
		noc;
	}
}
1239

1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
-- ----------------------------------------- OneDeclarationPerLine ----------------------------------------------
--- creates a measure when several variables are declared on the same line
rule MeasureOneDeclarationPerLine(s: java!VariableDeclarationStatement){
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
			name <- 'OneDeclarationPerLine',
  			shortDescription <- 'Java allows the use of several variables declaration on one line, however it can lead to quite messy code.'
		),
		measurement: smm!DirectMeasurement (
			error <- s.originalCompilationUnit.name + ' has more than one variable declaration per line.'
		)
	do {
		noc;
	}
}

1260
1261
1262
-- ------------------------------------------- ShortInstantiation ---------------------------------------------
--- A Measure instance if the class violates the rule 'ShortInstantiation'.
rule MeasureShortInstantiation(variable : java!CompilationUnit) {
1263
1264
1265
1266
1267
1268
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
1269
1270
			name <- 'ShortInstantiation',
			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.'		
1271
		),
1272
1273
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ variable.name + ' an instantiation of Short must be Short.ValueOf().'
1274
		)
1275
		
1276
1277
1278
1279
1280
	do {
		noc; 
	}
}

1281
1282
1283
-- ------------------------------------------- SignatureDeclareThrowsException  ---------------------------------------------
--- A Measure instance if the class violates the rule SignatureDeclareThrowsException.
rule MeasureSignatureDeclareThrowsException(class : java!ClassDeclaration) {
1284
1285
1286
1287
1288
1289
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
1290
1291
1292
1293
			
			name <- 'SignatureDeclareThrowsException ',
			shortDescription <- 'A method/constructor should not explicitly throw the generic java.lang.Exception'
		
1294
		),
1295
1296
		measurement: smm!DirectMeasurement (			
			error<-'In the Class '+ class.name + ' a method/constructor explicitly throws the generic java.lang.Exception.'
1297
1298
1299
1300
		)
	do {
		noc; 
	}
1301
1302
1303
1304
1305
}	 

-- ------------------------------------------- SimplifyBooleanAssertion ---------------------------------------------
--- creates a new Measure when a class contains a negation in an assertTrue or assertFalse.
rule MeasureSimplifyBooleanAssertion(i : java!PrefixExpression) {
1306
1307
1308
1309
1310
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
1311
1312
1313
		noc: smm!DimensionalMeasure (
			name <- 'SimplifyBooleanAssertion',
			shortDescription <- 'Avoid negation in an assertTrue or assertFalse test.'		
1314
		),
1315
1316
		measurement: smm!DirectMeasurement (			
			error<-'The method test ' + i.eContainer().eContainer().eContainer().eContainer().name + ' contains a negation in an assertTrue or assertFalse.'
1317
1318
		)
	do {