Skip to content

Commit ff27b2d

Browse files
committed
Support --learn for inline expectations via learnEdits
`codeql test run --learn` could previously only rewrite `.expected` files; inline expectations (the `// $ Alert` comments checked by `InlineExpectationsTest`) had to be fixed by hand. This teaches the shared test library to compute those source edits so the test runner can apply them. The `test-postprocess` query now exposes a `learnEdits` relation (`file, line, operation, startColumn, endColumn, text`) describing the minimal source rewrite that would make the inline expectations match the actual query results. It covers: - appending a fresh comment carrying every tag learned for a line that has an unexpected result and no existing comment to merge into; - rewriting an existing expectation comment as a whole so it matches the current results: dropping fixed-spurious tags, promoting a `MISSING:` expectation that now fires, clearing a stale `SPURIOUS:` annotation, and merging in freshly learned tags, re-rendering the remaining expectations (or deleting the comment when none remain); - preserving expectations this test does not own -- e.g. a tag annotated with a different query's id that shares the source file -- and any trailing regular note (`// $ Alert // note`); - recording any unexpected result, not just `Alert`. Edits are emitted as a query predicate rather than applied here: the engine consumes `learnEdits` only under `--learn` and ignores it otherwise, so ordinary `test run` output is unchanged. Comment syntax is provided per language by each `InlineExpectationsTestQuery.ql`'s `Input` (`getStartCommentMarker`), which for now renders only line-comment languages; block-comment languages (XML/YAML) can supply their markers later without changing this relation's shape.
1 parent d1fed84 commit ff27b2d

12 files changed

Lines changed: 611 additions & 26 deletions

File tree

cpp/ql/lib/utils/test/InlineExpectationsTestQuery.ql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,13 @@ private module Input implements T::TestPostProcessing::InputSig<Impl> {
1818
f.getRelativePath() + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
1919
)
2020
}
21+
22+
bindingset[relativePath]
23+
string getStartCommentMarker(string relativePath) {
24+
// C/C++ databases can also contain XML (e.g. `.xml`, `.props`), whose block-comment
25+
// syntax is not yet supported, so we only render for C/C++ sources.
26+
relativePath
27+
.regexpMatch(".*\\.(c|cc|cpp|cxx|cp|c\\+\\+|h|hh|hpp|hxx|h\\+\\+|inl|tcc|ipp|tpp|cu|cuh)") and
28+
result = "//"
29+
}
2130
}

csharp/ql/lib/utils/test/InlineExpectationsTestQuery.ql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,12 @@ private module Input implements T::TestPostProcessing::InputSig<Impl> {
1818
f.getRelativePath() + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
1919
)
2020
}
21+
22+
bindingset[relativePath]
23+
string getStartCommentMarker(string relativePath) {
24+
// C# databases can also contain XML (e.g. `.csproj`, `.config`) and Razor markup, whose
25+
// comment syntaxes are not yet supported, so we only render for C# sources.
26+
relativePath.regexpMatch(".*\\.(cs|csx)") and
27+
result = "//"
28+
}
2129
}

go/ql/lib/utils/test/InlineExpectationsTestQuery.ql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,12 @@ private module Input implements T::TestPostProcessing::InputSig<Impl> {
1818
f.getRelativePath() + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
1919
)
2020
}
21+
22+
bindingset[relativePath]
23+
string getStartCommentMarker(string relativePath) {
24+
// Go databases can also contain XML, whose block-comment syntax is not yet supported, so
25+
// we only render for Go sources.
26+
relativePath.matches("%.go") and
27+
result = "//"
28+
}
2129
}

java/ql/lib/utils/test/InlineExpectationsTestQuery.ql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,12 @@ private module Input implements T::TestPostProcessing::InputSig<Impl> {
1818
f.getRelativePath() + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
1919
)
2020
}
21+
22+
bindingset[relativePath]
23+
string getStartCommentMarker(string relativePath) {
24+
// Java databases can also contain XML; those files use a different (block) comment
25+
// syntax that is not yet supported, so we only render for Java and Kotlin sources.
26+
(relativePath.matches("%.java") or relativePath.matches("%.kt")) and
27+
result = "//"
28+
}
2129
}

javascript/ql/lib/utils/test/InlineExpectationsTestQuery.ql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,12 @@ private module Input implements T::TestPostProcessing::InputSig<Impl> {
1818
f.getRelativePath() + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
1919
)
2020
}
21+
22+
bindingset[relativePath]
23+
string getStartCommentMarker(string relativePath) {
24+
// JavaScript databases can also contain HTML, whose (block) comment syntax is not yet
25+
// supported, so we only render for the line-comment source files.
26+
relativePath.regexpMatch(".*\\.(js|cjs|mjs|jsx|ts|cts|mts|tsx)") and
27+
result = "//"
28+
}
2129
}

python/ql/lib/utils/test/InlineExpectationsTestQuery.ql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,12 @@ private module Input implements T::TestPostProcessing::InputSig<Impl> {
1818
f.getRelativePath() + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
1919
)
2020
}
21+
22+
bindingset[relativePath]
23+
string getStartCommentMarker(string relativePath) {
24+
// Python databases can also contain XML, whose block-comment syntax is not yet supported,
25+
// so we only render for Python sources.
26+
relativePath.regexpMatch(".*\\.(py|pyi)") and
27+
result = "#"
28+
}
2129
}

ql/ql/src/utils/test/InlineExpectationsTestQuery.ql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,12 @@ private module Input implements T::TestPostProcessing::InputSig<Impl> {
1818
f.getRelativePath() + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
1919
)
2020
}
21+
22+
bindingset[relativePath]
23+
string getStartCommentMarker(string relativePath) {
24+
// The QL extractor can also extract YAML (e.g. `qlpack.yml`), whose `#` comment syntax
25+
// differs, so we only render for QL sources and dbscheme files.
26+
relativePath.regexpMatch(".*\\.(ql|qll|dbscheme)") and
27+
result = "//"
28+
}
2129
}

ruby/ql/lib/utils/test/InlineExpectationsTestQuery.ql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,12 @@ private module Input implements T::TestPostProcessing::InputSig<Impl> {
1818
f.getRelativePath() + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
1919
)
2020
}
21+
22+
bindingset[relativePath]
23+
string getStartCommentMarker(string relativePath) {
24+
// Ruby databases can also contain ERB, whose comment syntax is not yet supported, so we
25+
// only render for plain Ruby sources.
26+
relativePath.matches("%.rb") and
27+
result = "#"
28+
}
2129
}

rust/ql/lib/utils/test/InlineExpectationsTestQuery.ql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,12 @@ private module Input implements T::TestPostProcessing::InputSig<Impl> {
1818
f.getRelativePath() + ":" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
1919
)
2020
}
21+
22+
bindingset[relativePath]
23+
string getStartCommentMarker(string relativePath) {
24+
// Rust databases can also contain YAML, whose `#` comment syntax differs, so we only
25+
// render for Rust sources.
26+
relativePath.matches("%.rs") and
27+
result = "//"
28+
}
2129
}

0 commit comments

Comments
 (0)