Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ql/ql/src/codeql/files/FileSystem.qll
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class Container = Impl::Container;

class Folder = Impl::Folder;

module Folder = Impl::Folder;

/** A file. */
class File extends Container, Impl::File {
/** Gets a token in this file. */
Expand Down
71 changes: 71 additions & 0 deletions ql/ql/src/codeql_ql/ast/Yaml.qll
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

private import codeql.yaml.Yaml as LibYaml
private import codeql.files.FileSystem

private module YamlSig implements LibYaml::InputSig {
import codeql.Locations
Expand Down Expand Up @@ -49,6 +50,58 @@ private module YamlSig implements LibYaml::InputSig {

import LibYaml::Make<YamlSig>

/** A `qlpack.yml` document. */
class QlPackDocument extends YamlDocument {
QlPackDocument() { this.getFile().getBaseName() = ["qlpack.yml", "qlpack.test.yml"] }

/** Gets the name of this QL pack. */
string getPackName() {
exists(YamlMapping n |
n.getDocument() = this and
result = n.lookup("name").(YamlScalar).getValue()
)
}

private string getADependencyName() {
exists(YamlMapping n, YamlScalar key |
n.getDocument() = this and
n.lookup("dependencies").(YamlMapping).maps(key, _) and
result = key.getValue()
)
}

/** Gets a dependency of this QL pack. */
QlPackDocument getADependency() { result.getPackName() = this.getADependencyName() }

private Folder getRootFolder() { result = this.getFile().getParentContainer() }

/** Gets a folder inside this QL pack. */
pragma[nomagic]
Folder getAFolder() {
result = this.getRootFolder()
or
exists(Folder mid |
mid = this.getAFolder() and
result.getParentContainer() = mid and
not result = any(QlPackDocument other).getRootFolder()
)
}
}

private predicate shouldAppend(QlRefDocument qlref, Folder f, string relativePath) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would make the code a lot more readable if this predicate had a QLDoc comment.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, done.

relativePath = qlref.getRelativeQueryPath() and
(
exists(QlPackDocument pack |
pack.getAFolder() = qlref.getFile().getParentContainer() and
f = [pack, pack.getADependency()].getFile().getParentContainer()
)
or
f = qlref.getFile().getParentContainer()
)
}

private predicate shouldAppend(Folder f, string relativePath) { shouldAppend(_, f, relativePath) }

/** A `.qlref` YAML document. */
class QlRefDocument extends YamlDocument {
QlRefDocument() { this.getFile().getExtension() = "qlref" }
Expand All @@ -65,6 +118,24 @@ class QlRefDocument extends YamlDocument {
)
}

/** Gets the relative path of the query in this `.qlref` file. */
string getRelativeQueryPath() {
exists(YamlMapping n | n.getDocument() = this |
result = n.lookup("query").(YamlScalar).getValue()
)
or
not exists(YamlMapping n | n.getDocument() = this) and
result = this.eval().(YamlScalar).getValue()
}

/** Gets the query file referenced in this `.qlref` file. */
File getQueryFile() {
exists(Folder f, string relativePath |
shouldAppend(this, f, relativePath) and
result = Folder::Append<shouldAppend/2>::append(f, relativePath)
)
}

predicate isPrintAst() {
this.getFile().getStem() = "PrintAst"
or
Expand Down
6 changes: 4 additions & 2 deletions ql/ql/src/queries/style/QlRefInlineExpectations.ql
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
import ql
import codeql_ql.ast.Yaml

from QlRefDocument f
from QlRefDocument f, TopLevel t, QueryDoc doc
where
not f.usesInlineExpectations() and
not f.isPrintAst()
t.getFile() = f.getQueryFile() and
doc = t.getQLDoc() and
doc.getQueryKind() in ["problem", "path-problem"]
select f, "Query test does not use inline test expectations."
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* @name Problem query
* @description Description of the problem
* @kind problem
* @problem.severity warning
* @id ql/problem-query
*/

import ql

from VarDecl decl
where none()
select decl, "Problem"
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
| QlRefInlineExpectations.qlref:1:1:1:40 | queries ... ions.ql | Query test does not use inline test expectations. |
| Test3.qlref:1:1:1:39 | query: ... ists.ql | Query test does not use inline test expectations. |
| Test3.qlref:1:1:1:22 | query: ... uery.ql | Query test does not use inline test expectations. |
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
query: queries/style/OmittableExists.ql
query: ProblemQuery.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
query: queries/style/OmittableExists.ql
query: ProblemQuery.ql
postprocess:
- utils/test/InlineExpectationsTestQuery.ql
Original file line number Diff line number Diff line change
@@ -1 +1 @@
query: queries/style/OmittableExists.ql
query: ProblemQuery.ql
Loading