22 * Provides a library for writing QL tests whose success or failure is based on expected results
33 * embedded in the test source code as comments, rather than a `.expected` file.
44 *
5+ * To add this framework to a new language:
6+ * - Add a file `InlineExpectationsTestPrivate.qll` that defines a `LineComment` class. This class
7+ * must support a `getContents` method that returns the contents of the given comment, _excluding_
8+ * the comment indicator itself. It should also define `toString` and `getLocation` as usual.
9+ *
510 * To create a new inline expectations test:
611 * - Declare a class that extends `InlineExpectationsTest`. In the characteristic predicate of the
712 * new class, bind `this` to a unique string (usually the name of the test).
1318 * `hasActualResult()`. Often this is just a single tag.
1419 *
1520 * Example:
16- * ```
21+ * ```ql
1722 * class ConstantValueTest extends InlineExpectationsTest {
1823 * ConstantValueTest() { this = "ConstantValueTest" }
1924 *
3843 * There is no need to write a `select` clause or query predicate. All of the differences between
3944 * expected results and actual results will be reported in the `failures()` query predicate.
4045 *
41- * To annotate the test source code with an expected result, place a C++-style (`//`) comment on the
46+ * To annotate the test source code with an expected result, place a comment on the
4247 * same line as the expected result, with text of the following format as the body of the comment:
4348 *
44- * `// $tag=expected-value`
49+ * `$tag=expected-value`
4550 *
4651 * Where `tag` is the value of the `tag` parameter from `hasActualResult()`, and `expected-value` is
4752 * the value of the `value` parameter from `hasActualResult()`. The `=expected-value` portion may be
5358 * "Missing result: tag=expected-value".
5459 *
5560 * Example:
56- * ```
61+ * ```cpp
5762 * int i = x + 5; // $const=5
5863 * int j = y + (7 - 3) // $const=7 $const=3 $const=4 // The result of the subtraction is a constant.
5964 * ```
6267 * annotate that a particular expected result is known to be a false positive, or that a particular
6368 * missing result is known to be a false negative:
6469 *
65- * `// $f+:tag=expected-value` // False positive
66- * `// $f-:tag=expected-value` // False negative
70+ * `$f+:tag=expected-value` // False positive
71+ * `$f-:tag=expected-value` // False negative
6772 *
6873 * A false positive expectation is treated as any other expected result, except that if there is no
6974 * matching actual result, the message will be of the form "Fixed false positive: tag=value". A
7479 * If the same result value is expected for two or more tags on the same line, there is a shorthand
7580 * notation available:
7681 *
77- * `// $tag1,tag2=expected-value`
82+ * `$tag1,tag2=expected-value`
7883 *
7984 * is equivalent to:
8085 *
81- * `// $tag1=expected-value $tag2=expected-value`
86+ * `$tag1=expected-value $tag2=expected-value`
8287 */
8388
84- import cpp
89+ private import InlineExpectationsTestPrivate
8590
8691/**
8792 * Base class for tests with inline expectations. The test extends this class to provide the actual
@@ -150,12 +155,12 @@ abstract class InlineExpectationsTest extends string {
150155}
151156
152157/**
153- * RegEx pattern to match a comment containing one or more expected results. The comment must be a
154- * C++-style (`//`) comment with `$` as its first non-whitespace character. Any subsequent character
158+ * RegEx pattern to match a comment containing one or more expected results. The comment must have
159+ * `$` as its first non-whitespace character. Any subsequent character
155160 * is treated as part of the expected results, except that the comment may contain a `//` sequence
156161 * to treat the remainder of the line as a regular (non-interpreted) comment.
157162 */
158- private string expectationCommentPattern ( ) { result = "// \\s*(\\$(?:[^/]|/[^/])*)(?://.*)?" }
163+ private string expectationCommentPattern ( ) { result = "\\s*(\\$(?:[^/]|/[^/])*)(?://.*)?" }
159164
160165/**
161166 * RegEx pattern to match a single expected result, not including the leading `$`. It starts with an
@@ -166,7 +171,7 @@ private string expectationPattern() {
166171 result = "(?:(f(?:\\+|-)):)?((?:[A-Za-z-_]+)(?:\\s*,\\s*[A-Za-z-_]+)*)(?:=(.*))?"
167172}
168173
169- private string getAnExpectation ( CppStyleComment comment ) {
174+ private string getAnExpectation ( LineComment comment ) {
170175 result = comment .getContents ( ) .regexpCapture ( expectationCommentPattern ( ) , 1 ) .splitAt ( "$" ) .trim ( ) and
171176 result != ""
172177}
@@ -177,7 +182,7 @@ private newtype TFailureLocatable =
177182 ) {
178183 test .hasActualResult ( location , element , tag , value )
179184 } or
180- TValidExpectation ( CppStyleComment comment , string tag , string value , string knownFailure ) {
185+ TValidExpectation ( LineComment comment , string tag , string value , string knownFailure ) {
181186 exists ( string expectation |
182187 expectation = getAnExpectation ( comment ) and
183188 expectation .regexpMatch ( expectationPattern ( ) ) and
@@ -194,7 +199,7 @@ private newtype TFailureLocatable =
194199 )
195200 )
196201 } or
197- TInvalidExpectation ( CppStyleComment comment , string expectation ) {
202+ TInvalidExpectation ( LineComment comment , string expectation ) {
198203 expectation = getAnExpectation ( comment ) and
199204 not expectation .regexpMatch ( expectationPattern ( ) )
200205 }
@@ -232,7 +237,7 @@ class ActualResult extends FailureLocatable, TActualResult {
232237}
233238
234239abstract private class Expectation extends FailureLocatable {
235- CppStyleComment comment ;
240+ LineComment comment ;
236241
237242 override string toString ( ) { result = comment .toString ( ) }
238243
0 commit comments