analysis.atl 68.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
		-- thisModule.startsWith(),
94
		thisModule.stringToString(),
Gerson Sunyé's avatar
Gerson Sunyé committed
95
		thisModule.tooFewBranchesForASwitchStatement(),
Gerson Sunyé's avatar
Gerson Sunyé committed
96
		-- #FIXME: thisModule.useArraysAsList(),
97
98
99
100
101
102
		thisModule.useIndexOfChar(),
		thisModule.uselessStringValueOf(),
		
		-- Documentation rules
		--
		thisModule.commentContent(),
103
		thisModule.commentRequired(),
104
105
106
107
108
109
110
111

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


164

165
166
--- Creates an instance of Measure for the switch statement missing one or more break/return statements
rule MeasureMissingBreakInSwitch(ss: java!SwitchStatement) {
167
168
	to
		om: smm!ObservedMeasure (
169
			measure <- missingBreakInSwitch,
170
171
			measurements <- measurement
		),
172
173
174
		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.'
175
		),
176
177
178
		measurement: smm!DirectMeasurement (
			error <- 'Missing breaks in Switch in Class : ' + ss.originalCompilationUnit.name + '',
			-- Indicates the number of breaks missing in the switch statement
179
			value <- (thisModule.nbBranchesOfASwitchStatement(ss) - thisModule.nbEmptySwitchCasesOfASwitchStatement(ss)) - thisModule.nbBreakStatementOfASwitchStatement(ss)
180
		)
181
	do {
182
		missingBreakInSwitch; 
183
184
185
	}
}

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

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
-- ------------------------------------------- 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;
	}
}

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

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

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

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

306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
-- ------------------------------------------- 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;
	}
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

812
813

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

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

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

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

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

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

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

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

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

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

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

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

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

1057
1058
1059
-- ------------------------------------------- IfStmtsMustUseBraces ---------------------------------------------
--- creates a new Measure when a class that contains an if statement without braces.
rule MeasureIfStmtsMustUseBraces(i : java!IfStatement) {
1060
1061
1062
1063
1064
1065
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
		noc: smm!DimensionalMeasure (
1066
1067
			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...'		
1068
		),
1069
1070
		measurement: smm!DirectMeasurement (			
			error <- 'The class ' + i.originalCompilationUnit.name +  ' has an if statement without braces. '
1071
1072
1073
1074
1075
1076
		)
	do {
		noc; 
	}
}

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

1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
-- ----------------------------------------- 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;
	}
}

1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
--- 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'
			)
1132
1133
1134
1135
1136
	do {
		noc; 
	}
}

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

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

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

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

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

1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
-- ----------------------------------------- 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;
	}
}

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

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

-- ------------------------------------------- SimplifyBooleanAssertion ---------------------------------------------
--- creates a new Measure when a class contains a negation in an assertTrue or assertFalse.
rule MeasureSimplifyBooleanAssertion(i : java!PrefixExpression) {
1305
1306
1307
1308
1309
	to
		om: smm!ObservedMeasure (
			measure <- noc,
			measurements <- measurement
		),
Gerson Sunyé's avatar