6
6
*/
7
7
8
8
private import codeql.yaml.Yaml as LibYaml
9
+ private import codeql.files.FileSystem
9
10
10
11
private module YamlSig implements LibYaml:: InputSig {
11
12
import codeql.Locations
@@ -49,6 +50,68 @@ private module YamlSig implements LibYaml::InputSig {
49
50
50
51
import LibYaml:: Make< YamlSig >
51
52
53
+ /** A `qlpack.yml` document. */
54
+ class QlPackDocument extends YamlDocument {
55
+ QlPackDocument ( ) { this .getFile ( ) .getBaseName ( ) = [ "qlpack.yml" , "qlpack.test.yml" ] }
56
+
57
+ /** Gets the name of this QL pack. */
58
+ string getPackName ( ) {
59
+ exists ( YamlMapping n |
60
+ n .getDocument ( ) = this and
61
+ result = n .lookup ( "name" ) .( YamlScalar ) .getValue ( )
62
+ )
63
+ }
64
+
65
+ private string getADependencyName ( ) {
66
+ exists ( YamlMapping n , YamlScalar key |
67
+ n .getDocument ( ) = this and
68
+ n .lookup ( "dependencies" ) .( YamlMapping ) .maps ( key , _) and
69
+ result = key .getValue ( )
70
+ )
71
+ }
72
+
73
+ /** Gets a dependency of this QL pack. */
74
+ QlPackDocument getADependency ( ) { result .getPackName ( ) = this .getADependencyName ( ) }
75
+
76
+ private Folder getRootFolder ( ) { result = this .getFile ( ) .getParentContainer ( ) }
77
+
78
+ /** Gets a folder inside this QL pack. */
79
+ pragma [ nomagic]
80
+ Folder getAFolder ( ) {
81
+ result = this .getRootFolder ( )
82
+ or
83
+ exists ( Folder mid |
84
+ mid = this .getAFolder ( ) and
85
+ result .getParentContainer ( ) = mid and
86
+ not result = any ( QlPackDocument other ) .getRootFolder ( )
87
+ )
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Holds if `qlref` is a `.qlref` YAML document referencing a query
93
+ * at relative path `relativePath`, and `f` is a candidate folder
94
+ * in which to lookup the referenced query.
95
+ *
96
+ * `f` is either:
97
+ * - the root of the QL pack containing `qlref`,
98
+ * - the root of a QL pack that is a dependency of the QL pack containing `qlref`, or
99
+ * - the folder containing `qlref`.
100
+ */
101
+ private predicate shouldAppend ( QlRefDocument qlref , Folder f , string relativePath ) {
102
+ relativePath = qlref .getRelativeQueryPath ( ) and
103
+ (
104
+ exists ( QlPackDocument pack |
105
+ pack .getAFolder ( ) = qlref .getFile ( ) .getParentContainer ( ) and
106
+ f = [ pack , pack .getADependency ( ) ] .getFile ( ) .getParentContainer ( )
107
+ )
108
+ or
109
+ f = qlref .getFile ( ) .getParentContainer ( )
110
+ )
111
+ }
112
+
113
+ private predicate shouldAppend ( Folder f , string relativePath ) { shouldAppend ( _, f , relativePath ) }
114
+
52
115
/** A `.qlref` YAML document. */
53
116
class QlRefDocument extends YamlDocument {
54
117
QlRefDocument ( ) { this .getFile ( ) .getExtension ( ) = "qlref" }
@@ -65,6 +128,24 @@ class QlRefDocument extends YamlDocument {
65
128
)
66
129
}
67
130
131
+ /** Gets the relative path of the query in this `.qlref` file. */
132
+ string getRelativeQueryPath ( ) {
133
+ exists ( YamlMapping n | n .getDocument ( ) = this |
134
+ result = n .lookup ( "query" ) .( YamlScalar ) .getValue ( )
135
+ )
136
+ or
137
+ not exists ( YamlMapping n | n .getDocument ( ) = this ) and
138
+ result = this .eval ( ) .( YamlScalar ) .getValue ( )
139
+ }
140
+
141
+ /** Gets the query file referenced in this `.qlref` file. */
142
+ File getQueryFile ( ) {
143
+ exists ( Folder f , string relativePath |
144
+ shouldAppend ( this , f , relativePath ) and
145
+ result = Folder:: Append< shouldAppend / 2 > :: append ( f , relativePath )
146
+ )
147
+ }
148
+
68
149
predicate isPrintAst ( ) {
69
150
this .getFile ( ) .getStem ( ) = "PrintAst"
70
151
or
0 commit comments