Skip to content

Commit 40f0112

Browse files
authored
Merge pull request #297 from github/aibaars/alert-suppression
Alert suppression and file classifier query
2 parents 4f9518a + e03fe0f commit 40f0112

File tree

8 files changed

+251
-0
lines changed

8 files changed

+251
-0
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/** Provides classes for detecting generated code. */
2+
3+
private import ruby
4+
private import codeql.ruby.ast.internal.TreeSitter
5+
6+
/** A source file that contains generated code. */
7+
abstract class GeneratedCodeFile extends RubyFile { }
8+
9+
/** A file contining comments suggesting it contains generated code. */
10+
class GeneratedCommentFile extends GeneratedCodeFile {
11+
GeneratedCommentFile() { this = any(GeneratedCodeComment c).getLocation().getFile() }
12+
}
13+
14+
/** A comment line that indicates generated code. */
15+
abstract class GeneratedCodeComment extends Ruby::Comment { }
16+
17+
/**
18+
* A generic comment line that suggests that the file is generated.
19+
*/
20+
class GenericGeneratedCodeComment extends GeneratedCodeComment {
21+
GenericGeneratedCodeComment() {
22+
exists(string line, string entity, string was, string automatically | line = getValue() |
23+
entity = "file|class|art[ei]fact|module|script" and
24+
was = "was|is|has been" and
25+
automatically = "automatically |mechanically |auto[- ]?" and
26+
line.regexpMatch("(?i).*\\bThis (" + entity + ") (" + was + ") (" + automatically +
27+
")?generated\\b.*")
28+
)
29+
}
30+
}
31+
32+
/** A comment warning against modifications. */
33+
class DontModifyMarkerComment extends GeneratedCodeComment {
34+
DontModifyMarkerComment() {
35+
exists(string line | line = getValue() |
36+
line.regexpMatch("(?i).*\\bGenerated by\\b.*\\bDo not edit\\b.*") or
37+
line.regexpMatch("(?i).*\\bAny modifications to this file will be lost\\b.*")
38+
)
39+
}
40+
}
41+
42+
/** Holds if `file` looks like it contains generated code. */
43+
predicate isGeneratedCode(GeneratedCodeFile file) { any() }

ql/src/AlertSuppression.ql

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/**
2+
* @name Alert suppression
3+
* @description Generates information about alert suppressions.
4+
* @kind alert-suppression
5+
* @id rb/alert-suppression
6+
*/
7+
8+
import ruby
9+
import codeql.ruby.ast.internal.TreeSitter
10+
11+
/**
12+
* An alert suppression comment.
13+
*/
14+
class SuppressionComment extends Ruby::Comment {
15+
string annotation;
16+
17+
SuppressionComment() {
18+
// suppression comments must be single-line
19+
this.getLocation().getStartLine() = this.getLocation().getEndLine() and
20+
exists(string text | text = commentText(this) |
21+
// match `lgtm[...]` anywhere in the comment
22+
annotation = text.regexpFind("(?i)\\blgtm\\s*\\[[^\\]]*\\]", _, _)
23+
or
24+
// match `lgtm` at the start of the comment and after semicolon
25+
annotation = text.regexpFind("(?i)(?<=^|;)\\s*lgtm(?!\\B|\\s*\\[)", _, _).trim()
26+
)
27+
}
28+
29+
/**
30+
* Gets the text of this suppression comment.
31+
*/
32+
string getText() { result = commentText(this) }
33+
34+
/** Gets the suppression annotation in this comment. */
35+
string getAnnotation() { result = annotation }
36+
37+
/**
38+
* Holds if this comment applies to the range from column `startcolumn` of line `startline`
39+
* to column `endcolumn` of line `endline` in file `filepath`.
40+
*/
41+
predicate covers(string filepath, int startline, int startcolumn, int endline, int endcolumn) {
42+
this.getLocation().hasLocationInfo(filepath, startline, _, endline, endcolumn) and
43+
startcolumn = 1
44+
}
45+
46+
/** Gets the scope of this suppression. */
47+
SuppressionScope getScope() { this = result.getSuppressionComment() }
48+
}
49+
50+
private string commentText(Ruby::Comment comment) { result = comment.getValue().suffix(1) }
51+
52+
/**
53+
* The scope of an alert suppression comment.
54+
*/
55+
class SuppressionScope extends @ruby_token_comment {
56+
SuppressionScope() { this instanceof SuppressionComment }
57+
58+
/** Gets a suppression comment with this scope. */
59+
SuppressionComment getSuppressionComment() { result = this }
60+
61+
/**
62+
* Holds if this element is at the specified location.
63+
* The location spans column `startcolumn` of line `startline` to
64+
* column `endcolumn` of line `endline` in file `filepath`.
65+
* For more information, see
66+
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
67+
*/
68+
predicate hasLocationInfo(
69+
string filepath, int startline, int startcolumn, int endline, int endcolumn
70+
) {
71+
this.(SuppressionComment).covers(filepath, startline, startcolumn, endline, endcolumn)
72+
}
73+
74+
/** Gets a textual representation of this element. */
75+
string toString() { result = "suppression range" }
76+
}
77+
78+
from SuppressionComment c
79+
select c, // suppression comment
80+
c.getText(), // text of suppression comment (excluding delimiters)
81+
c.getAnnotation(), // text of suppression annotation
82+
c.getScope() // scope of suppression

ql/src/filters/ClassifyFiles.ql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* @name Classify files
3+
* @description This query produces a list of all files in a database
4+
* that are classified as generated code or test code.
5+
*
6+
* Used by LGTM.
7+
* @kind file-classifier
8+
* @id rb/file-classifier
9+
*/
10+
11+
import ruby
12+
import codeql.ruby.filters.GeneratedCode
13+
14+
predicate classify(File f, string category) {
15+
f instanceof GeneratedCodeFile and category = "generated"
16+
}
17+
18+
from File f, string category
19+
where classify(f, category)
20+
select f, category
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TestWindows.java eol=crlf
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
| Test.rb:1:16:1:21 | # lgtm | lgtm | lgtm | Test.rb:1:1:1:21 | suppression range |
2+
| Test.rb:2:1:2:32 | # lgtm[rb/confusing-method-name] | lgtm[rb/confusing-method-name] | lgtm[rb/confusing-method-name] | Test.rb:2:1:2:32 | suppression range |
3+
| Test.rb:3:1:3:65 | # lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation] | lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation] | lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation] | Test.rb:3:1:3:65 | suppression range |
4+
| Test.rb:4:1:4:23 | # lgtm[@tag:exceptions] | lgtm[@tag:exceptions] | lgtm[@tag:exceptions] | Test.rb:4:1:4:23 | suppression range |
5+
| Test.rb:5:1:5:48 | # lgtm[@tag:exceptions,rb/confusing-method-name] | lgtm[@tag:exceptions,rb/confusing-method-name] | lgtm[@tag:exceptions,rb/confusing-method-name] | Test.rb:5:1:5:48 | suppression range |
6+
| Test.rb:6:1:6:27 | # lgtm[@expires:2017-06-11] | lgtm[@expires:2017-06-11] | lgtm[@expires:2017-06-11] | Test.rb:6:1:6:27 | suppression range |
7+
| Test.rb:7:1:7:78 | # lgtm[rb/confusing-method-name] does not seem confusing despite alert by lgtm | lgtm[rb/confusing-method-name] does not seem confusing despite alert by lgtm | lgtm[rb/confusing-method-name] | Test.rb:7:1:7:78 | suppression range |
8+
| Test.rb:8:1:8:17 | # lgtm: blah blah | lgtm: blah blah | lgtm | Test.rb:8:1:8:17 | suppression range |
9+
| Test.rb:9:1:9:31 | # lgtm blah blah #falsepositive | lgtm blah blah #falsepositive | lgtm | Test.rb:9:1:9:31 | suppression range |
10+
| Test.rb:10:1:10:33 | #lgtm [rb/confusing-method-name] | lgtm [rb/confusing-method-name] | lgtm [rb/confusing-method-name] | Test.rb:10:1:10:33 | suppression range |
11+
| Test.rb:11:1:11:8 | # lgtm[] | lgtm[] | lgtm[] | Test.rb:11:1:11:8 | suppression range |
12+
| Test.rb:13:1:13:5 | #lgtm | lgtm | lgtm | Test.rb:13:1:13:5 | suppression range |
13+
| Test.rb:14:1:14:6 | #\tlgtm | \tlgtm | lgtm | Test.rb:14:1:14:6 | suppression range |
14+
| Test.rb:15:1:15:33 | # lgtm\t[rb/confusing-method-name] | lgtm\t[rb/confusing-method-name] | lgtm\t[rb/confusing-method-name] | Test.rb:15:1:15:33 | suppression range |
15+
| Test.rb:18:1:18:11 | # foo; lgtm | foo; lgtm | lgtm | Test.rb:18:1:18:11 | suppression range |
16+
| Test.rb:19:1:19:37 | # foo; lgtm[rb/confusing-method-name] | foo; lgtm[rb/confusing-method-name] | lgtm[rb/confusing-method-name] | Test.rb:19:1:19:37 | suppression range |
17+
| Test.rb:21:1:21:36 | # foo lgtm[rb/confusing-method-name] | foo lgtm[rb/confusing-method-name] | lgtm[rb/confusing-method-name] | Test.rb:21:1:21:36 | suppression range |
18+
| Test.rb:23:1:23:40 | # foo lgtm[rb/confusing-method-name] bar | foo lgtm[rb/confusing-method-name] bar | lgtm[rb/confusing-method-name] | Test.rb:23:1:23:40 | suppression range |
19+
| Test.rb:24:1:24:7 | # LGTM! | LGTM! | LGTM | Test.rb:24:1:24:7 | suppression range |
20+
| Test.rb:25:1:25:32 | # LGTM[rb/confusing-method-name] | LGTM[rb/confusing-method-name] | LGTM[rb/confusing-method-name] | Test.rb:25:1:25:32 | suppression range |
21+
| Test.rb:26:1:26:73 | #lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation] | lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation] | lgtm[rb/confusing-method-name] | Test.rb:26:1:26:73 | suppression range |
22+
| Test.rb:26:1:26:73 | #lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation] | lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation] | lgtm[rb/non-short-circuit-evaluation] | Test.rb:26:1:26:73 | suppression range |
23+
| Test.rb:27:1:27:37 | #lgtm[rb/confusing-method-name]; lgtm | lgtm[rb/confusing-method-name]; lgtm | lgtm | Test.rb:27:1:27:37 | suppression range |
24+
| Test.rb:27:1:27:37 | #lgtm[rb/confusing-method-name]; lgtm | lgtm[rb/confusing-method-name]; lgtm | lgtm[rb/confusing-method-name] | Test.rb:27:1:27:37 | suppression range |
25+
| TestWindows.rb:1:23:1:29 | # lgtm\r | lgtm\r | lgtm | TestWindows.rb:1:1:1:29 | suppression range |
26+
| TestWindows.rb:2:1:2:33 | # lgtm[rb/confusing-method-name]\r | lgtm[rb/confusing-method-name]\r | lgtm[rb/confusing-method-name] | TestWindows.rb:2:1:2:33 | suppression range |
27+
| TestWindows.rb:3:1:3:66 | # lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation]\r | lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation]\r | lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation] | TestWindows.rb:3:1:3:66 | suppression range |
28+
| TestWindows.rb:4:1:4:24 | # lgtm[@tag:exceptions]\r | lgtm[@tag:exceptions]\r | lgtm[@tag:exceptions] | TestWindows.rb:4:1:4:24 | suppression range |
29+
| TestWindows.rb:5:1:5:49 | # lgtm[@tag:exceptions,rb/confusing-method-name]\r | lgtm[@tag:exceptions,rb/confusing-method-name]\r | lgtm[@tag:exceptions,rb/confusing-method-name] | TestWindows.rb:5:1:5:49 | suppression range |
30+
| TestWindows.rb:6:1:6:28 | # lgtm[@expires:2017-06-11]\r | lgtm[@expires:2017-06-11]\r | lgtm[@expires:2017-06-11] | TestWindows.rb:6:1:6:28 | suppression range |
31+
| TestWindows.rb:7:1:7:79 | # lgtm[rb/confusing-method-name] does not seem confusing despite alert by lgtm\r | lgtm[rb/confusing-method-name] does not seem confusing despite alert by lgtm\r | lgtm[rb/confusing-method-name] | TestWindows.rb:7:1:7:79 | suppression range |
32+
| TestWindows.rb:8:1:8:18 | # lgtm: blah blah\r | lgtm: blah blah\r | lgtm | TestWindows.rb:8:1:8:18 | suppression range |
33+
| TestWindows.rb:9:1:9:32 | # lgtm blah blah #falsepositive\r | lgtm blah blah #falsepositive\r | lgtm | TestWindows.rb:9:1:9:32 | suppression range |
34+
| TestWindows.rb:10:1:10:34 | #lgtm [rb/confusing-method-name]\r | lgtm [rb/confusing-method-name]\r | lgtm [rb/confusing-method-name] | TestWindows.rb:10:1:10:34 | suppression range |
35+
| TestWindows.rb:11:1:11:9 | # lgtm[]\r | lgtm[]\r | lgtm[] | TestWindows.rb:11:1:11:9 | suppression range |
36+
| TestWindows.rb:13:1:13:6 | #lgtm\r | lgtm\r | lgtm | TestWindows.rb:13:1:13:6 | suppression range |
37+
| TestWindows.rb:14:1:14:7 | #\tlgtm\r | \tlgtm\r | lgtm | TestWindows.rb:14:1:14:7 | suppression range |
38+
| TestWindows.rb:15:1:15:34 | # lgtm\t[rb/confusing-method-name]\r | lgtm\t[rb/confusing-method-name]\r | lgtm\t[rb/confusing-method-name] | TestWindows.rb:15:1:15:34 | suppression range |
39+
| TestWindows.rb:18:1:18:12 | # foo; lgtm\r | foo; lgtm\r | lgtm | TestWindows.rb:18:1:18:12 | suppression range |
40+
| TestWindows.rb:19:1:19:38 | # foo; lgtm[rb/confusing-method-name]\r | foo; lgtm[rb/confusing-method-name]\r | lgtm[rb/confusing-method-name] | TestWindows.rb:19:1:19:38 | suppression range |
41+
| TestWindows.rb:21:1:21:37 | # foo lgtm[rb/confusing-method-name]\r | foo lgtm[rb/confusing-method-name]\r | lgtm[rb/confusing-method-name] | TestWindows.rb:21:1:21:37 | suppression range |
42+
| TestWindows.rb:23:1:23:41 | # foo lgtm[rb/confusing-method-name] bar\r | foo lgtm[rb/confusing-method-name] bar\r | lgtm[rb/confusing-method-name] | TestWindows.rb:23:1:23:41 | suppression range |
43+
| TestWindows.rb:24:1:24:8 | # LGTM!\r | LGTM!\r | LGTM | TestWindows.rb:24:1:24:8 | suppression range |
44+
| TestWindows.rb:25:1:25:33 | # LGTM[rb/confusing-method-name]\r | LGTM[rb/confusing-method-name]\r | LGTM[rb/confusing-method-name] | TestWindows.rb:25:1:25:33 | suppression range |
45+
| TestWindows.rb:26:1:26:74 | #lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation]\r | lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation]\r | lgtm[rb/confusing-method-name] | TestWindows.rb:26:1:26:74 | suppression range |
46+
| TestWindows.rb:26:1:26:74 | #lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation]\r | lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation]\r | lgtm[rb/non-short-circuit-evaluation] | TestWindows.rb:26:1:26:74 | suppression range |
47+
| TestWindows.rb:27:1:27:38 | #lgtm[rb/confusing-method-name]; lgtm\r | lgtm[rb/confusing-method-name]; lgtm\r | lgtm | TestWindows.rb:27:1:27:38 | suppression range |
48+
| TestWindows.rb:27:1:27:38 | #lgtm[rb/confusing-method-name]; lgtm\r | lgtm[rb/confusing-method-name]; lgtm\r | lgtm[rb/confusing-method-name] | TestWindows.rb:27:1:27:38 | suppression range |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
AlertSuppression.ql
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
class Test end # lgtm
2+
# lgtm[rb/confusing-method-name]
3+
# lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation]
4+
# lgtm[@tag:exceptions]
5+
# lgtm[@tag:exceptions,rb/confusing-method-name]
6+
# lgtm[@expires:2017-06-11]
7+
# lgtm[rb/confusing-method-name] does not seem confusing despite alert by lgtm
8+
# lgtm: blah blah
9+
# lgtm blah blah #falsepositive
10+
#lgtm [rb/confusing-method-name]
11+
# lgtm[]
12+
# lgtmfoo
13+
#lgtm
14+
# lgtm
15+
# lgtm [rb/confusing-method-name]
16+
# foolgtm[rb/confusing-method-name]
17+
# foolgtm
18+
# foo; lgtm
19+
# foo; lgtm[rb/confusing-method-name]
20+
# foo lgtm
21+
# foo lgtm[rb/confusing-method-name]
22+
# foo lgtm bar
23+
# foo lgtm[rb/confusing-method-name] bar
24+
# LGTM!
25+
# LGTM[rb/confusing-method-name]
26+
#lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation]
27+
#lgtm[rb/confusing-method-name]; lgtm
28+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
class TestWindows end # lgtm
2+
# lgtm[rb/confusing-method-name]
3+
# lgtm[rb/confusing-method-name, rb/non-short-circuit-evaluation]
4+
# lgtm[@tag:exceptions]
5+
# lgtm[@tag:exceptions,rb/confusing-method-name]
6+
# lgtm[@expires:2017-06-11]
7+
# lgtm[rb/confusing-method-name] does not seem confusing despite alert by lgtm
8+
# lgtm: blah blah
9+
# lgtm blah blah #falsepositive
10+
#lgtm [rb/confusing-method-name]
11+
# lgtm[]
12+
# lgtmfoo
13+
#lgtm
14+
# lgtm
15+
# lgtm [rb/confusing-method-name]
16+
# foolgtm[rb/confusing-method-name]
17+
# foolgtm
18+
# foo; lgtm
19+
# foo; lgtm[rb/confusing-method-name]
20+
# foo lgtm
21+
# foo lgtm[rb/confusing-method-name]
22+
# foo lgtm bar
23+
# foo lgtm[rb/confusing-method-name] bar
24+
# LGTM!
25+
# LGTM[rb/confusing-method-name]
26+
#lgtm[rb/confusing-method-name] and lgtm[rb/non-short-circuit-evaluation]
27+
#lgtm[rb/confusing-method-name]; lgtm
28+

0 commit comments

Comments
 (0)