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


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

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

 
rule Java2SMM {
	from
		project: java!Model
	to
		model: smm!SmmModel (
			name <- project.name,
			librairies <- lib
		),
		lib: smm!MeasureLibrary (
			name <- 'Java metrics',
			measureElements <- thisModule.allMeasures(project)
		)
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

811
812

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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