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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

814
815

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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