Skip to content

Commit 65fe9ab

Browse files
authored
Merge pull request #37 from erik-krogh/shared/inline-tests
inline Location into the shared implementation of InlineExpectationsTest
2 parents 08e9d33 + b3dd50b commit 65fe9ab

File tree

9 files changed

+164
-156
lines changed

9 files changed

+164
-156
lines changed

cpp/ql/test/TestUtilities/InlineExpectationsTest.qll

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,30 +6,27 @@
66
import cpp as C
77
private import codeql.util.test.InlineExpectationsTest
88

9-
private module Impl implements InlineExpectationsTestSig {
10-
private newtype TExpectationComment = MkExpectationComment(C::CppStyleComment c)
9+
private newtype TExpectationComment = MkExpectationComment(C::CppStyleComment c)
1110

12-
/**
13-
* Represents a line comment in the CPP style.
14-
* Unlike the `CppStyleComment` class, however, the string returned by `getContents` does _not_
15-
* include the preceding comment marker (`//`).
16-
*/
17-
class ExpectationComment extends TExpectationComment {
18-
C::CppStyleComment comment;
11+
/**
12+
* Represents a line comment in the CPP style.
13+
* Unlike the `CppStyleComment` class, however, the string returned by `getContents` does _not_
14+
* include the preceding comment marker (`//`).
15+
*/
16+
private class ExpectationComment extends TExpectationComment {
17+
C::CppStyleComment comment;
1918

20-
ExpectationComment() { this = MkExpectationComment(comment) }
19+
ExpectationComment() { this = MkExpectationComment(comment) }
2120

22-
/** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */
23-
string getContents() { result = comment.getContents().suffix(2) }
21+
/** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */
22+
string getContents() { result = comment.getContents().suffix(2) }
2423

25-
/** Gets a textual representation of this element. */
26-
string toString() { result = comment.toString() }
24+
/** Gets a textual representation of this element. */
25+
string toString() { result = comment.toString() }
2726

28-
/** Gets the location of this comment. */
29-
Location getLocation() { result = comment.getLocation() }
27+
predicate hasLocationInfo(string file, int line, int column, int endLine, int endColumn) {
28+
comment.getLocation().hasLocationInfo(file, line, column, endLine, endColumn)
3029
}
31-
32-
class Location = C::Location;
3330
}
3431

35-
import Make<Impl>
32+
import Make<ExpectationComment>

csharp/ql/test/TestUtilities/InlineExpectationsTest.qll

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66
private import csharp as CS
77
private import codeql.util.test.InlineExpectationsTest
88

9-
private module Impl implements InlineExpectationsTestSig {
10-
/**
11-
* A class representing line comments in C# used by the InlineExpectations core code
12-
*/
13-
class ExpectationComment extends CS::SinglelineComment {
14-
/** Gets the contents of the given comment, _without_ the preceding comment marker (`//`). */
15-
string getContents() { result = this.getText() }
16-
}
9+
/**
10+
* A class representing line comments in C# used by the InlineExpectations core code
11+
*/
12+
private class ExpectationComment extends CS::SinglelineComment {
13+
/** Gets the contents of the given comment, _without_ the preceding comment marker (`//`). */
14+
string getContents() { result = this.getText() }
1715

18-
class Location = CS::Location;
16+
predicate hasLocationInfo(string file, int line, int column, int endLine, int endColumn) {
17+
this.getLocation().hasLocationInfo(file, line, column, endLine, endColumn)
18+
}
1919
}
2020

21-
import Make<Impl>
21+
import Make<ExpectationComment>

go/ql/test/TestUtilities/InlineExpectationsTest.qll

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,13 @@
66
private import go as G
77
private import codeql.util.test.InlineExpectationsTest
88

9-
private module Impl implements InlineExpectationsTestSig {
10-
/**
11-
* Represents a line comment in the Go style.
12-
* include the preceding comment marker (`//`).
13-
*/
14-
class ExpectationComment extends G::Comment {
15-
/** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */
16-
string getContents() { result = this.getText() }
17-
}
18-
19-
class Location = G::Location;
9+
/**
10+
* Represents a line comment in the Go style.
11+
* include the preceding comment marker (`//`).
12+
*/
13+
private class ExpectationComment extends G::Comment {
14+
/** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */
15+
string getContents() { result = this.getText() }
2016
}
2117

22-
import Make<Impl>
18+
import Make<ExpectationComment>

java/ql/test/TestUtilities/InlineExpectationsTest.qll

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,41 +6,35 @@
66
private import java as J
77
private import codeql.util.test.InlineExpectationsTest
88

9-
private module Impl implements InlineExpectationsTestSig {
10-
/**
11-
* A class representing line comments in Java, which is simply Javadoc restricted
12-
* to EOL comments, with an extra accessor used by the InlineExpectations core code
13-
*/
14-
abstract class ExpectationComment extends J::Top {
15-
/** Gets the contents of the given comment, _without_ the preceding comment marker (`//`). */
16-
abstract string getContents();
17-
}
18-
19-
private class JavadocExpectationComment extends J::Javadoc, ExpectationComment {
20-
JavadocExpectationComment() { isEolComment(this) }
21-
22-
override string getContents() { result = this.getChild(0).toString() }
23-
}
9+
/**
10+
* A class representing line comments in Java, which is simply Javadoc restricted
11+
* to EOL comments, with an extra accessor used by the InlineExpectations core code
12+
*/
13+
abstract private class ExpectationComment extends J::Top {
14+
/** Gets the contents of the given comment, _without_ the preceding comment marker (`//`). */
15+
abstract string getContents();
16+
}
2417

25-
private class KtExpectationComment extends J::KtComment, ExpectationComment {
26-
KtExpectationComment() { this.isEolComment() }
18+
private class JavadocExpectationComment extends J::Javadoc, ExpectationComment {
19+
JavadocExpectationComment() { isEolComment(this) }
2720

28-
override string getContents() { result = this.getText().suffix(2).trim() }
29-
}
21+
override string getContents() { result = this.getChild(0).toString() }
22+
}
3023

31-
private class XmlExpectationComment extends ExpectationComment instanceof J::XmlComment {
32-
override string getContents() { result = this.(J::XmlComment).getText().trim() }
24+
private class KtExpectationComment extends J::KtComment, ExpectationComment {
25+
KtExpectationComment() { this.isEolComment() }
3326

34-
override Location getLocation() { result = this.(J::XmlComment).getLocation() }
27+
override string getContents() { result = this.getText().suffix(2).trim() }
28+
}
3529

36-
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
37-
this.(J::XmlComment).hasLocationInfo(path, sl, sc, el, ec)
38-
}
30+
private class XmlExpectationComment extends ExpectationComment instanceof J::XmlComment {
31+
override string getContents() { result = this.(J::XmlComment).getText().trim() }
3932

40-
override string toString() { result = this.(J::XmlComment).toString() }
33+
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
34+
this.(J::XmlComment).hasLocationInfo(path, sl, sc, el, ec)
4135
}
4236

43-
class Location = J::Location;
37+
override string toString() { result = this.(J::XmlComment).toString() }
4438
}
4539

46-
import Make<Impl>
40+
import Make<ExpectationComment>

python/ql/test/TestUtilities/InlineExpectationsTest.qll

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
private import python as PY
77
private import codeql.util.test.InlineExpectationsTest
88

9-
private module Impl implements InlineExpectationsTestSig {
10-
/**
11-
* A class representing line comments in Python. As this is the only form of comment Python
12-
* permits, we simply reuse the `Comment` class.
13-
*/
14-
class ExpectationComment = PY::Comment;
15-
16-
class Location = PY::Location;
9+
/**
10+
* A class representing line comments in Python. As this is the only form of comment Python
11+
* permits, we simply reuse the `Comment` class.
12+
*/
13+
private class ExpectationComment extends PY::Comment {
14+
predicate hasLocationInfo(string file, int line, int column, int endLine, int endColumn) {
15+
this.getLocation().hasLocationInfo(file, line, column, endLine, endColumn)
16+
}
1717
}
1818

19-
import Make<Impl>
19+
import Make<ExpectationComment>

ql/ql/test/TestUtilities/InlineExpectationsTest.qll

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,27 @@
55

66
private import ql as QL
77
private import codeql.util.test.InlineExpectationsTest
8+
private import codeql_ql.ast.internal.TreeSitter as TS
89

9-
private module Impl implements InlineExpectationsTestSig {
10-
private import codeql_ql.ast.internal.TreeSitter as TS
10+
private newtype TExpectationComment = MkExpectationComment(TS::QL::LineComment comment)
1111

12-
private newtype TExpectationComment = MkExpectationComment(TS::QL::LineComment comment)
13-
14-
/**
15-
* Represents a line comment.
16-
*/
17-
class ExpectationComment extends TExpectationComment {
18-
TS::QL::LineComment comment;
12+
/**
13+
* Represents a line comment.
14+
*/
15+
private class ExpectationComment extends TExpectationComment {
16+
TS::QL::LineComment comment;
1917

20-
ExpectationComment() { this = MkExpectationComment(comment) }
18+
ExpectationComment() { this = MkExpectationComment(comment) }
2119

22-
/** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */
23-
string getContents() { result = comment.getValue().suffix(2) }
20+
/** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */
21+
string getContents() { result = comment.getValue().suffix(2) }
2422

25-
/** Gets a textual representation of this element. */
26-
string toString() { result = comment.toString() }
23+
/** Gets a textual representation of this element. */
24+
string toString() { result = comment.toString() }
2725

28-
/** Gets the location of this comment. */
29-
Location getLocation() { result = comment.getLocation() }
26+
predicate hasLocationInfo(string file, int line, int column, int endLine, int endColumn) {
27+
comment.getLocation().hasLocationInfo(file, line, column, endLine, endColumn)
3028
}
31-
32-
class Location = QL::Location;
3329
}
3430

35-
import Make<Impl>
31+
import Make<ExpectationComment>

ruby/ql/test/TestUtilities/InlineExpectationsTest.qll

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,18 @@
33
* See `shared/util/codeql/util/test/InlineExpectationsTest.qll`
44
*/
55

6-
private import codeql.ruby.AST as R
76
private import codeql.util.test.InlineExpectationsTest
7+
private import codeql.ruby.ast.internal.TreeSitter
88

9-
private module Impl implements InlineExpectationsTestSig {
10-
private import codeql.ruby.ast.internal.TreeSitter
9+
/**
10+
* A class representing line comments in Ruby.
11+
*/
12+
private class ExpectationComment extends Ruby::Comment {
13+
string getContents() { result = this.getValue().suffix(1) }
1114

12-
/**
13-
* A class representing line comments in Ruby.
14-
*/
15-
class ExpectationComment extends Ruby::Comment {
16-
string getContents() { result = this.getValue().suffix(1) }
15+
predicate hasLocationInfo(string file, int line, int column, int endLine, int endColumn) {
16+
this.getLocation().hasLocationInfo(file, line, column, endLine, endColumn)
1717
}
18-
19-
class Location = R::Location;
2018
}
2119

22-
import Make<Impl>
20+
import Make<ExpectationComment>

shared/util/codeql/util/test/InlineExpectationsTest.qll

Lines changed: 59 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@
66
* To add this framework to a new language, add a new file
77
* (usually called `InlineExpectationsTest.qll`) with:
88
* - `private import codeql.util.test.InlineExpectationsTest` (this file)
9-
* - An implementation of the signature in `InlineExpectationsTestSig`.
10-
* Usually this is done in a mdule called `Impl`.
11-
* `Impl` has to define a `Location` class, and an `ExpectationComment` class.
9+
* - An implementation of the class signature in `ExpectationCommentSig`.
10+
* This class can e.g. be called `ExpectationComment`.
1211
* The `ExpectationComment` class must support a `getContents` method that returns
1312
* the contents of the given comment, _excluding_ the comment indicator itself.
14-
* It should also define `toString` and `getLocation` as usual.
15-
* - `import Make<Impl>` to expose the query predicates constructed in the `Make` module.
13+
* It should also define `toString` and `hasLocationInfo` as usual.
14+
* - `import Make<ExpectationComment>` to expose the query predicates constructed in the `Make` module.
1615
*
1716
* To create a new inline expectations test:
1817
* - Declare a class that extends `InlineExpectationsTest`. In the characteristic predicate of the
@@ -96,36 +95,67 @@
9695
* `tag1=expected-value tag2=expected-value`
9796
*/
9897

99-
/**
100-
* A signature specifying the required parts for
101-
* constructing inline expectations.
102-
*/
103-
signature module InlineExpectationsTestSig {
104-
/** The location of an element in the source code. */
105-
class Location {
106-
predicate hasLocationInfo(
107-
string filename, int startLine, int startColumn, int endLine, int endColumn
108-
);
109-
}
98+
/** A comment that may contain inline expectations. */
99+
signature class ExpectationCommentSig {
100+
/** Gets the contents of this comment, _excluding_ the comment indicator. */
101+
string getContents();
110102

111-
/** A comment that may contain inline expectations. */
112-
class ExpectationComment {
113-
/** Gets the contents of this comment, _excluding_ the comment indicator. */
114-
string getContents();
103+
/** Gets a textual representation of this element. */
104+
string toString();
115105

116-
/** Gets the location of this comment. */
117-
Location getLocation();
118-
119-
/** Gets a textual representation of this element. */
120-
string toString();
121-
}
106+
predicate hasLocationInfo(
107+
string filename, int startLine, int startColumn, int endLine, int endColumn
108+
);
122109
}
123110

124111
/**
125112
* Classes and predicates implementing inline expectations.
126113
*/
127-
module Make<InlineExpectationsTestSig Impl> {
128-
private import Impl
114+
module Make<ExpectationCommentSig ExpectationComment> {
115+
private newtype TTLocation =
116+
TLocation(string filename, int startLine, int startColumn, int endLine, int endColumn) {
117+
any(ExpectationComment c)
118+
.hasLocationInfo(filename, startLine, startColumn, endLine, endColumn)
119+
}
120+
121+
private class Location extends TLocation {
122+
string filename;
123+
int startLine;
124+
int startColumn;
125+
int endLine;
126+
int endColumn;
127+
128+
Location() { this = TLocation(filename, startLine, startColumn, endLine, endColumn) }
129+
130+
string getFilename() { result = filename }
131+
132+
int getStartLine() { result = startLine }
133+
134+
int getStartColumn() { result = startColumn }
135+
136+
int getEndLine() { result = endLine }
137+
138+
int getEndColumn() { result = endColumn }
139+
140+
string toString() {
141+
result = filename + ":" + startLine + ":" + startColumn + "-" + endLine + ":" + endColumn
142+
}
143+
144+
predicate hasLocationInfo(string f, int sl, int sc, int el, int ec) {
145+
f = filename and
146+
sl = startLine and
147+
sc = startColumn and
148+
el = endLine and
149+
ec = endColumn
150+
}
151+
}
152+
153+
private Location getLocation(ExpectationComment c) {
154+
exists(string filename, int startLine, int startColumn, int endLine, int endColumn |
155+
c.hasLocationInfo(filename, startLine, startColumn, endLine, endColumn) and
156+
result = TLocation(filename, startLine, startColumn, endLine, endColumn)
157+
)
158+
}
129159

130160
/**
131161
* The base class for tests with inline expectations. The test extends this class to provide the actual
@@ -372,7 +402,7 @@ module Make<InlineExpectationsTestSig Impl> {
372402

373403
override string toString() { result = comment.toString() }
374404

375-
override Location getLocation() { result = comment.getLocation() }
405+
override Location getLocation() { result = getLocation(comment) }
376406
}
377407

378408
private predicate onSameLine(ValidExpectation a, ActualResult b) {

0 commit comments

Comments
 (0)