-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathComment.qll
More file actions
106 lines (90 loc) · 3.13 KB
/
Comment.qll
File metadata and controls
106 lines (90 loc) · 3.13 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
103
104
105
106
/**
* Provides classes representing comments in Python.
*/
overlay[local]
module;
import python
/** A source code comment */
class Comment extends @py_comment {
/** Gets the full text of the comment including the leading '#' */
string getText() { py_comments(this, result, _) }
/** Gets the contents of the comment excluding the leading '#' */
string getContents() { result = this.getText().suffix(1) }
Location getLocation() { py_comments(this, _, result) }
/** Gets a textual representation of this element. */
string toString() { result = "Comment " + this.getText() }
/**
* Gets this immediately following comment.
* Blanks line are allowed between this comment and the following comment,
* but code or other comments are not.
*/
Comment getFollowing() {
exists(File f, int n | this.file_line(f, n) |
result.file_line(f, n + 1)
or
result.file_line(f, n + 2) and f.emptyLine(n + 1)
or
result.file_line(f, n + 3) and f.emptyLine(n + 2) and f.emptyLine(n + 1)
)
}
private predicate file_line(File f, int n) {
this.getLocation().getFile() = f and
this.getLocation().getStartLine() = n
}
}
private predicate comment_block_part(Comment start, Comment part, int i) {
not exists(Comment prev | prev.getFollowing() = part) and
exists(part.getFollowing()) and
start = part and
i = 1
or
exists(Comment prev |
comment_block_part(start, prev, i - 1) and
part = prev.getFollowing()
)
}
/** A block of consecutive comments */
class CommentBlock extends @py_comment {
CommentBlock() { comment_block_part(this, _, _) }
private Comment last() { comment_block_part(this, result, this.length()) }
/** Gets a textual representation of this element. */
string toString() { result = "Comment block" }
/** Gets the length of this comment block (in comments) */
int length() { result = max(int i | comment_block_part(this, _, i)) }
/**
* 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://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.(Comment).getLocation().hasLocationInfo(filepath, startline, startcolumn, _, _) and
exists(Comment end | end = this.last() |
end.getLocation().hasLocationInfo(_, _, _, endline, endcolumn)
)
}
/** Holds if this comment block contains `c`. */
predicate contains(Comment c) {
comment_block_part(this, c, _)
or
this = c
}
/** Gets a string representation of this comment block. */
string getContents() {
result =
concat(Comment c, int i |
comment_block_part(this, c, i)
or
this = c and i = 0
|
c.getContents() order by i
)
}
}
/** A type-hint comment. Any comment that starts with `# type:` */
class TypeHintComment extends Comment {
TypeHintComment() { this.getText().regexpMatch("# +type:.*") }
}