|
6 | 6 | * To add this framework to a new language, add a new file |
7 | 7 | * (usually called `InlineExpectationsTest.qll`) with: |
8 | 8 | * - `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`. |
12 | 11 | * The `ExpectationComment` class must support a `getContents` method that returns |
13 | 12 | * 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. |
16 | 15 | * |
17 | 16 | * To create a new inline expectations test: |
18 | 17 | * - Declare a class that extends `InlineExpectationsTest`. In the characteristic predicate of the |
|
96 | 95 | * `tag1=expected-value tag2=expected-value` |
97 | 96 | */ |
98 | 97 |
|
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(); |
110 | 102 |
|
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(); |
115 | 105 |
|
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 | + ); |
122 | 109 | } |
123 | 110 |
|
124 | 111 | /** |
125 | 112 | * Classes and predicates implementing inline expectations. |
126 | 113 | */ |
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 | + } |
129 | 159 |
|
130 | 160 | /** |
131 | 161 | * 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> { |
372 | 402 |
|
373 | 403 | override string toString() { result = comment.toString() } |
374 | 404 |
|
375 | | - override Location getLocation() { result = comment.getLocation() } |
| 405 | + override Location getLocation() { result = getLocation(comment) } |
376 | 406 | } |
377 | 407 |
|
378 | 408 | private predicate onSameLine(ValidExpectation a, ActualResult b) { |
|
0 commit comments