Skip to content

Commit 8483b9f

Browse files
committed
QL: add query detecting block comments in a position where a QLDoc should be
1 parent df9533f commit 8483b9f

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

ql/ql/src/codeql_ql/ast/Ast.qll

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,16 @@ class QLDoc extends TQLDoc, AstNode {
156156
override string getAPrimaryQlClass() { result = "QLDoc" }
157157
}
158158

159+
class BlockComment extends TBlockComment, AstNode {
160+
QL::BlockComment comment;
161+
162+
BlockComment() { this = TBlockComment(comment) }
163+
164+
string getContents() { result = comment.getValue() }
165+
166+
override string getAPrimaryQlClass() { result = "BlockComment" }
167+
}
168+
159169
/**
160170
* The `from, where, select` part of a QL query.
161171
*/

ql/ql/src/codeql_ql/ast/internal/AstNodes.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ cached
66
newtype TAstNode =
77
TTopLevel(QL::Ql file) or
88
TQLDoc(QL::Qldoc qldoc) or
9+
TBlockComment(QL::BlockComment comment) or
910
TClasslessPredicate(QL::ClasslessPredicate pred) or
1011
TVarDecl(QL::VarDecl decl) or
1112
TFieldDecl(QL::Field field) or
@@ -146,6 +147,8 @@ QL::AstNode toQL(AST::AstNode n) {
146147
or
147148
n = TQLDoc(result)
148149
or
150+
n = TBlockComment(result)
151+
or
149152
n = TClasslessPredicate(result)
150153
or
151154
n = TVarDecl(result)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* @name Block comment that is not QLDoc
3+
* @description Placing a block comment that could have been a QLDoc comment is an indication that it should have been a QLDoc comment.
4+
* @kind problem
5+
* @problem.severity warning
6+
* @id ql/non-doc-block
7+
* @tags maintainability
8+
* @precision very-high
9+
*/
10+
11+
import ql
12+
13+
predicate canHaveQLDoc(AstNode node) {
14+
node instanceof Class
15+
or
16+
node instanceof Module
17+
or
18+
node instanceof ClasslessPredicate
19+
or
20+
node instanceof ClassPredicate
21+
}
22+
23+
pragma[noinline]
24+
int getLineAboveNodeThatCouldHaveDoc(File file) {
25+
exists(AstNode node | canHaveQLDoc(node) |
26+
result = node.getLocation().getStartLine() - 1 and file = node.getLocation().getFile()
27+
)
28+
}
29+
30+
pragma[noinline]
31+
BlockComment getACommentThatCouldBeQLDoc(File file) {
32+
file = result.getLocation().getFile() and
33+
result.getLocation().getEndLine() = getLineAboveNodeThatCouldHaveDoc(file) and
34+
result.getLocation().getFile().getExtension() = "qll" and
35+
not result.getContents().matches("/**%")
36+
}
37+
38+
pragma[noinline]
39+
BlockComment getCommentAt(File file, int endLine) {
40+
result = getACommentThatCouldBeQLDoc(file) and
41+
result.getLocation().getEndLine() = endLine
42+
}
43+
44+
from AstNode node, BlockComment comment
45+
where
46+
canHaveQLDoc(node) and
47+
not exists(node.getQLDoc()) and
48+
not node.(ClassPredicate).isOverride() and // ignore override predicates
49+
not node.hasAnnotation("deprecated") and // ignore deprecated
50+
not node.hasAnnotation("private") and // ignore private
51+
comment = getCommentAt(node.getLocation().getFile(), node.getLocation().getStartLine() - 1)
52+
select comment, "Block comment could be QLDoc for $@.", node, "the below code"

0 commit comments

Comments
 (0)