Skip to content

Commit 4321b5e

Browse files
committed
QL for QL: generalise non-US spelling query
1. Catch common misspelling as well. 2. Also check names of classes, predicates, etc.
1 parent 7cd51d6 commit 4321b5e

9 files changed

Lines changed: 9153 additions & 75 deletions

File tree

config/identical-files.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,5 +550,9 @@
550550
"HttpToFileAccessCustomizations JS/Ruby": [
551551
"javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll",
552552
"ruby/ql/lib/codeql/ruby/security/HttpToFileAccessCustomizations.qll"
553+
],
554+
"Typo database": [
555+
"javascript/ql/src/Expressions/TypoDatabase.qll",
556+
"ql/ql/src/codeql_ql/style/TypoDatabase.qll"
553557
]
554558
}

ql/ql/src/codeql_ql/style/AcronymsShouldBeCamelCaseQuery.qll

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,5 @@
11
import ql
2-
3-
/**
4-
* Gets the name for a `node` that defines something in a QL program.
5-
* E.g. a predicate, class, or module definition.
6-
*/
7-
string getName(AstNode node, string kind) {
8-
result = node.(Class).getName() and kind = "class"
9-
or
10-
// not including CharPreds or db relations. The remaining are: classlessPredicate, classPredicate, newTypeBranch.
11-
result = node.(ClasslessPredicate).getName() and
12-
kind = "classlessPredicate"
13-
or
14-
result = node.(ClassPredicate).getName() and
15-
kind = "classPredicate"
16-
or
17-
result = node.(NewTypeBranch).getName() and
18-
kind = "newtypeBranch"
19-
or
20-
result = node.(NewType).getName() and
21-
kind = "newtype"
22-
or
23-
result = node.(VarDecl).getName() and
24-
kind = "variable" and
25-
not node = any(FieldDecl f).getVarDecl()
26-
or
27-
result = node.(FieldDecl).getName() and kind = "field"
28-
or
29-
result = node.(Module).getName() and kind = "module"
30-
or
31-
result = node.(Import).importedAs() and kind = "import"
32-
}
2+
private import NodeName
333

344
string prettyPluralKind(string kind) {
355
kind = "class" and result = "classes"
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import ql
2+
private import NodeName
3+
private import TypoDatabase
4+
5+
predicate misspelling(string wrong, string right, string mistake) {
6+
mistake = "common misspelling" and
7+
typos(wrong, right)
8+
or
9+
mistake = "non-US spelling" and
10+
non_us_spelling(wrong, right)
11+
}
12+
13+
/**
14+
* Holds if `word` is an acceptable spelling that would otherwise be considered
15+
* a mistake by the typo database.
16+
*/
17+
predicate isAllowed(string word) {
18+
word =
19+
[
20+
"asign", // 'sign of a', not 'assign'
21+
"larg", // 'left argument', not 'large'
22+
"nto", // some comments refer to the variable `nTo`
23+
"thn" // deliberate misspelling of 'then' to avoid using a keyword
24+
]
25+
}
26+
27+
predicate non_us_spelling(string wrong, string right) {
28+
exists(string s |
29+
wrong = s.splitAt("/", 0) and
30+
right = s.splitAt("/", 1) and
31+
s =
32+
[
33+
"colour/color", "authorise/authorize", "authorises/authorizes", "authorised/authorized",
34+
"analyse/analyze", "analysed/analyzed", "behaviour/behavior", "modelling/modeling",
35+
"modelled/modeled"
36+
]
37+
)
38+
}
39+
40+
/**
41+
* Gets a word in the camel-case string `s`. For example, if `s` is
42+
* `"getFooBar"`, it returns `"get"`, `"Foo"`, and `"Bar"`.
43+
*/
44+
bindingset[s]
45+
string getACamelCaseWord(string s) { result = s.regexpFind("(^[a-z]+)|([A-Z][a-z]+)", _, _) }
46+
47+
bindingset[s]
48+
string getACommentWord(string s) { result = s.regexpFind("\\b\\w+\\b", _, _) }
49+
50+
string getAWord(AstNode node, string kind) {
51+
result = getACommentWord(node.(QLDoc).getContents()).toLowerCase() and
52+
kind = "QLDoc comment"
53+
or
54+
exists(string nodeKind |
55+
result = getACamelCaseWord(getName(node, nodeKind)).toLowerCase() and
56+
kind = nodeKind + " name"
57+
)
58+
}
59+
60+
predicate misspelled_element(AstNode node, string kind, string wrong, string right, string mistake) {
61+
wrong = getAWord(node, kind) and
62+
misspelling(wrong, right, mistake) and
63+
not isAllowed(wrong)
64+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import ql
2+
3+
/**
4+
* Gets the name for a `node` that defines something in a QL program.
5+
* E.g. a predicate, class, or module definition.
6+
*/
7+
string getName(AstNode node, string kind) {
8+
result = node.(Class).getName() and kind = "class"
9+
or
10+
// not including CharPreds or db relations. The remaining are: classlessPredicate, classPredicate, newTypeBranch.
11+
result = node.(ClasslessPredicate).getName() and
12+
kind = "classlessPredicate"
13+
or
14+
result = node.(ClassPredicate).getName() and
15+
kind = "classPredicate"
16+
or
17+
result = node.(NewTypeBranch).getName() and
18+
kind = "newtypeBranch"
19+
or
20+
result = node.(NewType).getName() and
21+
kind = "newtype"
22+
or
23+
result = node.(VarDecl).getName() and
24+
kind = "variable" and
25+
not node = any(FieldDecl f).getVarDecl()
26+
or
27+
result = node.(FieldDecl).getName() and kind = "field"
28+
or
29+
result = node.(Module).getName() and kind = "module"
30+
or
31+
result = node.(Import).importedAs() and kind = "import"
32+
}

0 commit comments

Comments
 (0)