codeql/misc/codegen/templates/ql_parent.mustache

92 строки
4.2 KiB
Plaintext

// generated by {{generator}}
{{#imports}}
import {{.}}
{{/imports}}
private module Impl {
{{#classes}}
private Element getImmediateChildOf{{name}}({{name}} e, int index, string partialPredicateCall) {
{{! avoid unused argument warnings on root element, assuming the root element has no children }}
{{#root}}none(){{/root}}
{{^root}}
{{! b is the base offset 0, for ease of generation }}
{{! b<base> is constructed to be strictly greater than the indexes required for children coming from <base> }}
{{! n is the base offset for direct children, equal to the last base offset from above }}
{{! n<child> is constructed to be strictly greater than the indexes for <child> children }}
exists(int b{{#bases}}, int b{{.}}{{/bases}}, int n{{#properties}}{{#is_child}}, int n{{singular}}{{/is_child}}{{/properties}} |
b = 0
{{#bases}}
and
b{{.}} = b{{prev}} + 1 + max(int i | i = -1 or exists(getImmediateChildOf{{.}}(e, i, _)) | i)
{{/bases}}
and
n = b{{last_base}}
{{#properties}}
{{#is_child}}
{{! n<child> 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
n{{singular}} = n{{prev_child}} + 1{{#is_repeated}}+ max(int i | i = -1 or exists(e.get{{#type_is_hideable}}Immediate{{/type_is_hideable}}{{singular}}(i)) | i){{/is_repeated}}
{{/is_child}}
{{/properties}} and (
none()
{{#bases}}
or
result = getImmediateChildOf{{.}}(e, index - b{{prev}}, partialPredicateCall)
{{/bases}}
{{#properties}}
{{#is_child}}
or
{{#is_repeated}}
result = e.get{{#type_is_hideable}}Immediate{{/type_is_hideable}}{{singular}}(index - n{{prev_child}}) and partialPredicateCall = "{{singular}}(" + (index - n{{prev_child}}).toString() + ")"
{{/is_repeated}}
{{^is_repeated}}
index = n{{prev_child}} and result = e.get{{#type_is_hideable}}Immediate{{/type_is_hideable}}{{singular}}() and partialPredicateCall = "{{singular}}()"
{{/is_repeated}}
{{/is_child}}
{{/properties}}
))
{{/root}}
}
{{/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. `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)
}