-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathAlertSuppressionAnnotations.ql
More file actions
102 lines (87 loc) · 3.56 KB
/
AlertSuppressionAnnotations.ql
File metadata and controls
102 lines (87 loc) · 3.56 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
92
93
94
95
96
97
98
99
100
101
102
/**
* @name Alert suppression using annotations
* @description Generates information about alert suppressions
* using 'SuppressWarnings' annotations.
* @kind alert-suppression
* @id java/alert-suppression-annotations
*/
import java
import Metrics.Internal.Extents
/**
* An alert suppression annotation.
*/
class SuppressionAnnotation extends SuppressWarningsAnnotation {
string annotation;
SuppressionAnnotation() {
exists(string text | text = this.getASuppressedWarningLiteral().getValue() |
// match `lgtm[...]` anywhere in the comment
annotation = text.regexpFind("(?i)\\blgtm\\s*\\[[^\\]]*\\]", _, _)
)
}
/**
* Gets the text of this suppression annotation.
*/
string getText() { result = getASuppressedWarningLiteral().getValue() }
/** Gets the LGTM suppression annotation in this Java annotation. */
string getAnnotation() { result = annotation }
private Annotation getASiblingAnnotation() {
result = getAnnotatedElement().(Annotatable).getAnAnnotation() and
(getAnnotatedElement() instanceof Callable or getAnnotatedElement() instanceof RefType)
}
private Annotation firstAnnotation() {
exists(Annotation m, int i |
result = m and
m = getASiblingAnnotation() and
i = rankOfAnnotation(m) and
not exists(Annotation other | other = getASiblingAnnotation() | rankOfAnnotation(other) < i)
)
}
private int rankOfAnnotation(Annotation m) {
this.getASiblingAnnotation() = m and
exists(Location mLoc, File f, int maxCol | mLoc = m.getLocation() |
f = mLoc.getFile() and
maxCol = max(Location loc | loc.getFile() = f | loc.getStartColumn()) and
result = mLoc.getStartLine() * maxCol + mLoc.getStartColumn()
)
}
/**
* Holds if this annotation applies to the range from column `startcolumn` of line `startline`
* to column `endcolumn` of line `endline` in file `filepath`.
*/
predicate covers(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
if firstAnnotation().hasLocationInfo(filepath, _, _, _, _)
then
getAnnotatedElement().hasLocationInfo(filepath, _, _, endline, endcolumn) and
firstAnnotation().hasLocationInfo(filepath, startline, startcolumn, _, _)
else getAnnotatedElement().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets the scope of this suppression. */
SuppressionScope getScope() { this = result.getSuppressionAnnotation() }
}
/**
* The scope of an alert suppression annotation.
*/
class SuppressionScope extends @annotation {
SuppressionScope() { this instanceof SuppressionAnnotation }
/** Gets a suppression annotation with this scope. */
SuppressionAnnotation getSuppressionAnnotation() { result = this }
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.(SuppressionAnnotation).covers(filepath, startline, startcolumn, endline, endcolumn)
}
/** Gets a textual representation of this element. */
string toString() { result = "suppression range" }
}
from SuppressionAnnotation c
select c, // suppression comment
c.getText(), // text of suppression comment (excluding delimiters)
c.getAnnotation(), // text of suppression annotation
c.getScope() // scope of suppression