9393private import InlineExpectationsTestPrivate
9494
9595/**
96- * Base class for tests with inline expectations. The test extends this class to provide the actual
96+ * The base class for tests with inline expectations. The test extends this class to provide the actual
9797 * results of the query, which are then compared with the expected results in comments to produce a
9898 * list of failure messages that point out where the actual results differ from the expected
9999 * results.
@@ -121,11 +121,17 @@ abstract class InlineExpectationsTest extends string {
121121 * - `value` - The value of the result, which will be matched against the value associated with
122122 * `tag` in any expected result comment on that line.
123123 */
124- abstract predicate hasActualResult ( string file , int line , string element , string tag , string value ) ;
124+ abstract predicate hasActualResult ( Location location , string element , string tag , string value ) ;
125125
126- predicate hasActualResult ( Location location , string element , string tag , string value ) {
127- this .hasActualResult ( location .getFile ( ) .getAbsolutePath ( ) , location .getStartLine ( ) , element ,
128- tag , value )
126+ /**
127+ * Holds if there is an optional result on the specified location.
128+ *
129+ * This is similar to `hasActualResult`, but returns results that do not require a matching annotation.
130+ * A failure will still arise if there is an annotation that does not match any results, but not vice versa.
131+ * Override this predicate to specify optional results.
132+ */
133+ predicate hasOptionalResult ( Location location , string element , string tag , string value ) {
134+ none ( )
129135 }
130136
131137 final predicate hasFailureMessage ( FailureLocatable element , string message ) {
@@ -139,13 +145,14 @@ abstract class InlineExpectationsTest extends string {
139145 )
140146 or
141147 not exists ( ValidExpectation expectation | expectation .matchesActualResult ( actualResult ) ) and
142- message = "Unexpected result: " + actualResult .getExpectationText ( )
148+ message = "Unexpected result: " + actualResult .getExpectationText ( ) and
149+ not actualResult .isOptional ( )
143150 )
144151 )
145152 or
146153 exists ( ValidExpectation expectation |
147154 not exists ( ActualResult actualResult | expectation .matchesActualResult ( actualResult ) ) and
148- expectation .getTag ( ) = this . getARelevantTag ( ) and
155+ expectation .getTag ( ) = getARelevantTag ( ) and
149156 element = expectation and
150157 (
151158 expectation instanceof GoodExpectation and
@@ -174,7 +181,7 @@ private string expectationCommentPattern() { result = "\\s*\\$((?:[^/]|/[^/])*)(
174181/**
175182 * The possible columns in an expectation comment. The `TDefaultColumn` branch represents the first
176183 * column in a comment. This column is not precedeeded by a name. `TNamedColumn(name)` represents a
177- * column containing expected results preceeded by the string `name:`.
184+ * column containing expected results preceded by the string `name:`.
178185 */
179186private newtype TColumn =
180187 TDefaultColumn ( ) or
@@ -248,9 +255,13 @@ private string expectationPattern() {
248255
249256private newtype TFailureLocatable =
250257 TActualResult (
251- InlineExpectationsTest test , Location location , string element , string tag , string value
258+ InlineExpectationsTest test , Location location , string element , string tag , string value ,
259+ boolean optional
252260 ) {
253- test .hasActualResult ( location , element , tag , value )
261+ test .hasActualResult ( location , element , tag , value ) and
262+ optional = false
263+ or
264+ test .hasOptionalResult ( location , element , tag , value ) and optional = true
254265 } or
255266 TValidExpectation ( ExpectationComment comment , string tag , string value , string knownFailure ) {
256267 exists ( TColumn column , string tags |
@@ -269,7 +280,7 @@ class FailureLocatable extends TFailureLocatable {
269280
270281 Location getLocation ( ) { none ( ) }
271282
272- final string getExpectationText ( ) { result = this . getTag ( ) + "=" + this . getValue ( ) }
283+ final string getExpectationText ( ) { result = getTag ( ) + "=" + getValue ( ) }
273284
274285 string getTag ( ) { none ( ) }
275286
@@ -282,8 +293,9 @@ class ActualResult extends FailureLocatable, TActualResult {
282293 string element ;
283294 string tag ;
284295 string value ;
296+ boolean optional ;
285297
286- ActualResult ( ) { this = TActualResult ( test , location , element , tag , value ) }
298+ ActualResult ( ) { this = TActualResult ( test , location , element , tag , value , optional ) }
287299
288300 override string toString ( ) { result = element }
289301
@@ -294,6 +306,8 @@ class ActualResult extends FailureLocatable, TActualResult {
294306 override string getTag ( ) { result = tag }
295307
296308 override string getValue ( ) { result = value }
309+
310+ predicate isOptional ( ) { optional = true }
297311}
298312
299313abstract private class Expectation extends FailureLocatable {
@@ -318,24 +332,24 @@ private class ValidExpectation extends Expectation, TValidExpectation {
318332 string getKnownFailure ( ) { result = knownFailure }
319333
320334 predicate matchesActualResult ( ActualResult actualResult ) {
321- this . getLocation ( ) .getStartLine ( ) = actualResult .getLocation ( ) .getStartLine ( ) and
322- this . getLocation ( ) .getFile ( ) = actualResult .getLocation ( ) .getFile ( ) and
323- this . getTag ( ) = actualResult .getTag ( ) and
324- this . getValue ( ) = actualResult .getValue ( )
335+ getLocation ( ) .getStartLine ( ) = actualResult .getLocation ( ) .getStartLine ( ) and
336+ getLocation ( ) .getFile ( ) = actualResult .getLocation ( ) .getFile ( ) and
337+ getTag ( ) = actualResult .getTag ( ) and
338+ getValue ( ) = actualResult .getValue ( )
325339 }
326340}
327341
328342/* Note: These next three classes correspond to all the possible values of type `TColumn`. */
329343class GoodExpectation extends ValidExpectation {
330- GoodExpectation ( ) { this . getKnownFailure ( ) = "" }
344+ GoodExpectation ( ) { getKnownFailure ( ) = "" }
331345}
332346
333347class FalsePositiveExpectation extends ValidExpectation {
334- FalsePositiveExpectation ( ) { this . getKnownFailure ( ) = "SPURIOUS" }
348+ FalsePositiveExpectation ( ) { getKnownFailure ( ) = "SPURIOUS" }
335349}
336350
337351class FalseNegativeExpectation extends ValidExpectation {
338- FalseNegativeExpectation ( ) { this . getKnownFailure ( ) = "MISSING" }
352+ FalseNegativeExpectation ( ) { getKnownFailure ( ) = "MISSING" }
339353}
340354
341355class InvalidExpectation extends Expectation , TInvalidExpectation {
0 commit comments