@@ -2019,3 +2019,187 @@ class ModuleExpr extends TModuleExpr, ModuleRef {
20192019 pred = directMember ( "getQualifier" ) and result = this .getQualifier ( )
20202020 }
20212021}
2022+
2023+ /**
2024+ * Classes modelling YAML AST nodes.
2025+ */
2026+ module YAML {
2027+ /** A node in a YAML file */
2028+ class YAMLNode extends TYAMLNode , AstNode {
2029+ /** Holds if the predicate is a root node (has no parent) */
2030+ predicate isRoot ( ) { not exists ( getParent ( ) ) }
2031+ }
2032+
2033+ /** A YAML comment. */
2034+ class YAMLComment extends TYamlCommemt , YAMLNode {
2035+ Generated:: YamlComment yamlcomment ;
2036+
2037+ YAMLComment ( ) { this = TYamlCommemt ( yamlcomment ) }
2038+
2039+ override string getAPrimaryQlClass ( ) { result = "YAMLComment" }
2040+ }
2041+
2042+ /** A YAML entry. */
2043+ class YAMLEntry extends TYamlEntry , YAMLNode {
2044+ Generated:: YamlEntry yamle ;
2045+
2046+ YAMLEntry ( ) { this = TYamlEntry ( yamle ) }
2047+
2048+ /** Gets the key of this YAML entry. */
2049+ YAMLKey getKey ( ) {
2050+ exists ( Generated:: YamlKeyvaluepair pair |
2051+ pair .getParent ( ) = yamle and
2052+ result = TYamlKey ( pair .getKey ( ) )
2053+ )
2054+ }
2055+
2056+ /** Gets the value of this YAML entry. */
2057+ YAMLValue getValue ( ) {
2058+ exists ( Generated:: YamlKeyvaluepair pair |
2059+ pair .getParent ( ) = yamle and
2060+ result = TYamlValue ( pair .getValue ( ) )
2061+ )
2062+ }
2063+
2064+ override string getAPrimaryQlClass ( ) { result = "YAMLEntry" }
2065+ }
2066+
2067+ /** A YAML key. */
2068+ class YAMLKey extends TYamlKey , YAMLNode {
2069+ Generated:: YamlKey yamlkey ;
2070+
2071+ YAMLKey ( ) { this = TYamlKey ( yamlkey ) }
2072+
2073+ /**
2074+ * Gets the value of this YAML key.
2075+ */
2076+ YAMLValue getValue ( ) {
2077+ exists ( Generated:: YamlKeyvaluepair pair |
2078+ pair .getKey ( ) = yamlkey and result = TYamlValue ( pair .getValue ( ) )
2079+ )
2080+ }
2081+
2082+ override string getAPrimaryQlClass ( ) { result = "YAMLKey" }
2083+
2084+ /** Gets the value of this YAML value. */
2085+ string getNamePart ( int i ) {
2086+ i = 0 and result = yamlkey .getChild ( 0 ) .( Generated:: SimpleId ) .getValue ( )
2087+ or
2088+ exists ( YAMLKey child |
2089+ child = TYamlKey ( yamlkey .getChild ( 1 ) ) and
2090+ result = child .getNamePart ( i - 1 )
2091+ )
2092+ }
2093+
2094+ /**
2095+ * Gets all the name parts of this YAML key concatenated with `/`.
2096+ * Dashes are replaced with `/` (because we don't have that information in the generated AST).
2097+ */
2098+ string getQualifiedName ( ) {
2099+ result = concat ( string part , int i | part = getNamePart ( i ) | part , "/" order by i )
2100+ }
2101+ }
2102+
2103+ /** A YAML list item. */
2104+ class YAMLListItem extends TYamlListitem , YAMLNode {
2105+ Generated:: YamlListitem yamllistitem ;
2106+
2107+ YAMLListItem ( ) { this = TYamlListitem ( yamllistitem ) }
2108+
2109+ /**
2110+ * Gets the value of this YAML list item.
2111+ */
2112+ YAMLValue getValue ( ) { result = TYamlValue ( yamllistitem .getChild ( ) ) }
2113+
2114+ override string getAPrimaryQlClass ( ) { result = "YAMLListItem" }
2115+ }
2116+
2117+ /** A YAML value. */
2118+ class YAMLValue extends TYamlValue , YAMLNode {
2119+ Generated:: YamlValue yamlvalue ;
2120+
2121+ YAMLValue ( ) { this = TYamlValue ( yamlvalue ) }
2122+
2123+ override string getAPrimaryQlClass ( ) { result = "YAMLValue" }
2124+
2125+ /** Gets the value of this YAML value. */
2126+ string getValue ( ) { result = yamlvalue .getValue ( ) }
2127+ }
2128+
2129+ // to not expose the entire `File` API on `QlPack`.
2130+ private newtype TQLPack = MKQlPack ( File file ) { file .getBaseName ( ) = "qlpack.yml" }
2131+
2132+ YAMLEntry test ( ) { not result .isRoot ( ) }
2133+
2134+ /**
2135+ * A `qlpack.yml` file.
2136+ */
2137+ class QLPack extends MKQlPack {
2138+ File file ;
2139+
2140+ QLPack ( ) { this = MKQlPack ( file ) }
2141+
2142+ private string getProperty ( string name ) {
2143+ exists ( YAMLEntry entry |
2144+ entry .isRoot ( ) and
2145+ entry .getKey ( ) .getQualifiedName ( ) = name and
2146+ result = entry .getValue ( ) .getValue ( ) and
2147+ entry .getLocation ( ) .getFile ( ) = file
2148+ )
2149+ }
2150+
2151+ /** Gets the name of this qlpack */
2152+ string getName ( ) { result = getProperty ( "name" ) }
2153+
2154+ /** Gets the version of this qlpack */
2155+ string getVersion ( ) { result = getProperty ( "version" ) }
2156+
2157+ /** Gets the database scheme of this qlpack */
2158+ string getDbScheme ( ) { result = getProperty ( "dbscheme" ) }
2159+
2160+ /** Gets the extractor of this qlpack */
2161+ string getExtractor ( ) { result = getProperty ( "extractor" ) }
2162+
2163+ string toString ( ) { result = getName ( ) }
2164+
2165+ /** Gets the file that this `QLPack` represents. */
2166+ File getFile ( ) { result = file }
2167+
2168+ private predicate isADependency ( YAMLEntry entry ) {
2169+ exists ( YAMLEntry deps |
2170+ deps .getLocation ( ) .getFile ( ) = file and entry .getLocation ( ) .getFile ( ) = file
2171+ |
2172+ deps .isRoot ( ) and
2173+ deps .getKey ( ) .getQualifiedName ( ) = "dependencies" and
2174+ entry .getLocation ( ) .getStartLine ( ) = 1 + deps .getLocation ( ) .getStartLine ( ) and
2175+ entry .getLocation ( ) .getStartColumn ( ) > deps .getLocation ( ) .getStartColumn ( )
2176+ )
2177+ or
2178+ exists ( YAMLEntry prev | isADependency ( prev ) |
2179+ prev .getLocation ( ) .getFile ( ) = file and
2180+ entry .getLocation ( ) .getFile ( ) = file and
2181+ entry .getLocation ( ) .getStartLine ( ) = 1 + prev .getLocation ( ) .getStartLine ( ) and
2182+ entry .getLocation ( ) .getStartColumn ( ) = prev .getLocation ( ) .getStartColumn ( )
2183+ )
2184+ }
2185+
2186+ predicate hasDependency ( string name , string version ) {
2187+ exists ( YAMLEntry entry | isADependency ( entry ) |
2188+ entry .getKey ( ) .getQualifiedName ( ) = name and
2189+ entry .getValue ( ) .getValue ( ) = version
2190+ )
2191+ }
2192+
2193+ Location getLocation ( ) {
2194+ // hacky, just pick the first node in the file.
2195+ result =
2196+ min ( YAMLNode entry , Location l , File f |
2197+ entry .getLocation ( ) .getFile ( ) = file and
2198+ f = file and
2199+ l = entry .getLocation ( )
2200+ |
2201+ entry order by l .getStartLine ( ) , l .getStartColumn ( ) , l .getEndColumn ( ) , l .getEndLine ( )
2202+ ) .getLocation ( )
2203+ }
2204+ }
2205+ }
0 commit comments