-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathEmptyMethod.ql
More file actions
91 lines (85 loc) · 2.64 KB
/
EmptyMethod.ql
File metadata and controls
91 lines (85 loc) · 2.64 KB
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/**
* @id java/empty-method
* @name Empty method
* @description An empty method serves no purpose and makes code less readable. An empty method may
* indicate an error on the part of the developer.
* @kind problem
* @precision very-high
* @problem.severity warning
* @tags correctness
* maintainability
* readability
*/
import java
/**
* Represents a likely a test method, which is either a method that is already
* recognized as a `TestMethod` or something that is likely a JUnit test or
* something in the expected test path for Java tests.
*/
class LikelyTestMethod extends Method {
LikelyTestMethod() {
this.getDeclaringType() instanceof TestClass
or
this instanceof TestMethod
or
this instanceof LikelyJunitTest
or
//standard Maven/Gradle test file discovery filepath
this.getFile().getAbsolutePath().matches("%src/test/java%")
or
this.getDeclaringType() instanceof SurefireTest
}
}
/**
* Classes that are likely part of junit tests (more general than `TestMethod` from `UnitTest.qll`)
* A `Method` that is public, has no parameters,
* has a "void" return type, AND either has a name that starts with "test" OR
* has an annotation that ends with "Test"
*/
class LikelyJunitTest extends Method {
LikelyJunitTest() {
this.isPublic() and
this.getReturnType().hasName("void") and
this.hasNoParameters() and
(
this.getName().matches("JUnit%") or
this.getName().matches("test%") or
this.getAnAnnotation().getType().getName().matches("%Test")
)
}
}
/**
* Maven surefire patterns to consider which files are testcases:
* https://maven.apache.org/surefire/maven-surefire-plugin/examples/inclusion-exclusion.html
*/
class SurefireTest extends Class {
SurefireTest() {
this.getFile().getAbsolutePath().matches("%src/test/java%") and
this.getFile()
.getBaseName()
.matches(["Test%.java", "%Test.java", "%Tests.java", "%TestCase.java"])
}
}
/**
* A `Method` from source that is not abstract
*/
class NonAbstractSource extends Method {
NonAbstractSource() {
this.fromSource() and
not this.isAbstract() and
not this instanceof LikelyTestMethod
}
}
from NonAbstractSource m
where
//empty
not exists(m.getBody().getAChild()) and
//permit comment lines explaining why this is empty
m.getNumberOfCommentLines() = 0 and
//permit a javadoc above as well as sufficient reason to leave empty
not exists(m.getDoc().getJavadoc()) and
//annotated methods are considered compliant
not exists(m.getAnAnnotation()) and
//native methods have no body
not m.isNative()
select m, "This empty method should be completed."