// generated by {{generator}}, do not edit /** * This module provides the generated parent/child relationship. */ {{#imports}} import {{.}} {{/imports}} private module Impl { {{#classes}} {{#final}} private Element getImmediateChildOf{{name}}({{name}} e, int index, string partialPredicateCall) { {{^has_children}}none(){{/has_children}} {{#has_children}} {{! n is the base offset 0, for ease of generation }} {{! n is constructed to be strictly greater than the indexes for children }} exists(int n{{#all_children}}, int n{{property.singular}}{{/all_children}} | n = 0 {{#all_children}} {{#property}} {{! n is defined on top of the previous definition }} {{! for single and optional properties it adds 1 (regardless of whether the optional property exists) }} {{! for repeated it adds 1 + the maximum index (which works for repeated optional as well) }} and {{#type_is_hideable}} n{{singular}} = n{{prev}} + 1{{#is_repeated}}+ max(int i | i = -1 or exists(e.getImmediate{{singular}}(i)) | i){{/is_repeated}} {{/type_is_hideable}} {{^type_is_hideable}} n{{singular}} = n{{prev}} {{^is_repeated}}+ 1{{/is_repeated}}{{#is_repeated}}+ e.getNumberOf{{plural}}(){{/is_repeated}} {{/type_is_hideable}} {{/property}} {{/all_children}} and ( none() {{#all_children}} {{#property}} or {{#is_repeated}} result = e.get{{#type_is_hideable}}Immediate{{/type_is_hideable}}{{singular}}(index - n{{prev}}) and partialPredicateCall = "{{singular}}(" + (index - n{{prev}}).toString() + ")" {{/is_repeated}} {{^is_repeated}} index = n{{prev}} and result = e.get{{#type_is_hideable}}Immediate{{/type_is_hideable}}{{singular}}() and partialPredicateCall = "{{singular}}()" {{/is_repeated}} {{/property}} {{/all_children}} )) {{/has_children}} } {{/final}} {{/classes}} cached Element getImmediateChild(Element e, int index, string partialAccessor) { // why does this look more complicated than it should? // * none() simplifies generation, as we can append `or ...` without a special case for the first item none() {{#classes}} {{#final}} or result = getImmediateChildOf{{name}}(e, index, partialAccessor) {{/final}} {{/classes}} } } /** * Gets the "immediate" parent of `e`. "Immediate" means not taking into account node resolution: for example * if `e` has conversions, `getImmediateParent(e)` will give the innermost conversion in the hidden AST. */ Element getImmediateParent(Element e) { // `unique` is used here to tell the optimizer that there is in fact only one result // this is tested by the `library-tests/parent/no_double_parents.ql` test result = unique(Element x | e = Impl::getImmediateChild(x, _, _) | x) } /** * Gets the immediate child indexed at `index`. Indexes are not guaranteed to be contiguous, but are guaranteed to be distinct. */ Element getImmediateChild(Element e, int index) { result = Impl::getImmediateChild(e, index, _) } /** * Gets the immediate child indexed at `index`. Indexes are not guaranteed to be contiguous, but are guaranteed to be distinct. `accessor` is bound the member predicate call resulting in the given child. */ Element getImmediateChildAndAccessor(Element e, int index, string accessor) { exists(string partialAccessor | result = Impl::getImmediateChild(e, index, partialAccessor) and accessor = "get" + partialAccessor) } /** * Gets the child indexed at `index`. Indexes are not guaranteed to be contiguous, but are guaranteed to be distinct. `accessor` is bound the member predicate call resulting in the given child. */ Element getChildAndAccessor(Element e, int index, string accessor) { exists(string partialAccessor | result = Impl::getImmediateChild(e, index, partialAccessor).resolve() and accessor = "get" + partialAccessor) } /** * Gets the child indexed at `index`. Indexes are not guaranteed to be contiguous, but are guaranteed to be distinct. `accessor` is bound the member predicate call resulting in the given child. */ Element getChild(Element e, int index) { result = Impl::getImmediateChild(e, index, _).resolve() }