зеркало из https://github.com/github/codeql.git
Codegen: implement `set` in qlgen (excluding QL tests)
This commit is contained in:
Родитель
00b59f83f2
Коммит
d5ee728657
|
@ -109,6 +109,7 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, prev_child: str =
|
|||
prev_child=prev_child if prop.is_child else None,
|
||||
is_optional=prop.is_optional,
|
||||
is_predicate=prop.is_predicate,
|
||||
is_unordered=prop.is_unordered,
|
||||
description=prop.description
|
||||
)
|
||||
if prop.is_single:
|
||||
|
@ -123,7 +124,7 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, prev_child: str =
|
|||
singular=inflection.singularize(inflection.camelize(prop.name)),
|
||||
plural=inflection.pluralize(inflection.camelize(prop.name)),
|
||||
tablename=inflection.tableize(f"{cls.name}_{prop.name}"),
|
||||
tableparams=["this", "index", "result"],
|
||||
tableparams=["this", "index", "result"] if not prop.is_unordered else ["this", "result"],
|
||||
doc=_get_doc(cls, prop, plural=False),
|
||||
doc_plural=_get_doc(cls, prop, plural=True),
|
||||
)
|
||||
|
|
|
@ -36,6 +36,7 @@ class Property:
|
|||
first: bool = False
|
||||
is_optional: bool = False
|
||||
is_predicate: bool = False
|
||||
is_unordered: bool = False
|
||||
prev_child: Optional[str] = None
|
||||
qltest_skip: bool = False
|
||||
description: List[str] = field(default_factory=list)
|
||||
|
@ -49,7 +50,11 @@ class Property:
|
|||
|
||||
@property
|
||||
def getter(self):
|
||||
return f"get{self.singular}" if not self.is_predicate else self.singular
|
||||
if self.is_predicate:
|
||||
return self.singular
|
||||
if self.is_unordered:
|
||||
return self.indefinite_getter
|
||||
return f"get{self.singular}"
|
||||
|
||||
@property
|
||||
def indefinite_getter(self):
|
||||
|
@ -77,6 +82,10 @@ class Property:
|
|||
def has_description(self) -> bool:
|
||||
return bool(self.description)
|
||||
|
||||
@property
|
||||
def is_indexed(self) -> bool:
|
||||
return self.is_repeated and not self.is_unordered
|
||||
|
||||
|
||||
@dataclass
|
||||
class Base:
|
||||
|
|
|
@ -66,9 +66,9 @@ module Generated {
|
|||
* This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the
|
||||
* behavior of both the `Immediate` and non-`Immediate` versions.
|
||||
*/
|
||||
{{type}} getImmediate{{singular}}({{#is_repeated}}int index{{/is_repeated}}) {
|
||||
{{type}} get{{#is_unordered}}An{{/is_unordered}}Immediate{{singular}}({{#is_indexed}}int index{{/is_indexed}}) {
|
||||
{{^ipa}}
|
||||
result = Synth::convert{{type}}FromRaw(Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_repeated}}index{{/is_repeated}}))
|
||||
result = Synth::convert{{type}}FromRaw(Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_indexed}}index{{/is_indexed}}))
|
||||
{{/ipa}}
|
||||
{{#ipa}}
|
||||
none()
|
||||
|
@ -83,8 +83,8 @@ module Generated {
|
|||
{{/description}}
|
||||
{{/has_description}}
|
||||
*/
|
||||
final {{type}} {{getter}}({{#is_repeated}}int index{{/is_repeated}}) {
|
||||
result = getImmediate{{singular}}({{#is_repeated}}index{{/is_repeated}}).resolve()
|
||||
final {{type}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) {
|
||||
result = get{{#is_unordered}}An{{/is_unordered}}Immediate{{singular}}({{#is_indexed}}index{{/is_indexed}}).resolve()
|
||||
}
|
||||
|
||||
{{/type_is_class}}
|
||||
|
@ -97,9 +97,9 @@ module Generated {
|
|||
{{/description}}
|
||||
{{/has_description}}
|
||||
*/
|
||||
{{type}} {{getter}}({{#is_repeated}}int index{{/is_repeated}}) {
|
||||
{{type}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) {
|
||||
{{^ipa}}
|
||||
{{^is_predicate}}result = {{/is_predicate}}Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_repeated}}index{{/is_repeated}})
|
||||
{{^is_predicate}}result = {{/is_predicate}}Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_indexed}}index{{/is_indexed}})
|
||||
{{/ipa}}
|
||||
{{#ipa}}
|
||||
none()
|
||||
|
@ -115,7 +115,7 @@ module Generated {
|
|||
exists({{getter}}({{#is_repeated}}index{{/is_repeated}}))
|
||||
}
|
||||
{{/is_optional}}
|
||||
{{#is_repeated}}
|
||||
{{#is_indexed}}
|
||||
|
||||
/**
|
||||
* Gets any of the {{doc_plural}}.
|
||||
|
@ -132,7 +132,15 @@ module Generated {
|
|||
result = count(int i | exists({{getter}}(i)))
|
||||
}
|
||||
{{/is_optional}}
|
||||
{{/is_repeated}}
|
||||
{{/is_indexed}}
|
||||
{{#is_unordered}}
|
||||
/**
|
||||
* Gets the number of {{doc_plural}}.
|
||||
*/
|
||||
final int getNumberOf{{plural}}() {
|
||||
result = count({{getter}}())
|
||||
}
|
||||
{{/is_unordered}}
|
||||
{{/properties}}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ module Raw {
|
|||
{{/description}}
|
||||
{{/has_description}}
|
||||
*/
|
||||
{{type}} {{getter}}({{#is_repeated}}int index{{/is_repeated}}) {
|
||||
{{type}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) {
|
||||
{{tablename}}({{#tableparams}}{{^first}}, {{/first}}{{param}}{{/tableparams}})
|
||||
}
|
||||
{{/properties}}
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
{{^is_predicate}}
|
||||
{{^is_unoredered}}
|
||||
Gets the {{#is_repeated}}`index`th {{/is_repeated}}{{doc}}{{#is_repeated}} (0-based){{/is_repeated}}{{#is_optional}}, if it exists{{/is_optional}}.
|
||||
{{/is_unoredered}}
|
||||
{{/is_predicate}}
|
||||
{{#is_predicate}}
|
||||
Holds if {{doc}}.
|
||||
{{/is_predicate}}
|
||||
{{#is_unordered}}
|
||||
Gets any of the {{doc_plural}}.
|
||||
{{/is_unordered}}
|
||||
|
|
|
@ -27,19 +27,26 @@ def test_property_is_a_class(type, expected):
|
|||
assert [p.param for p in prop.tableparams] == expected_tableparams
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name,expected_getter", [
|
||||
indefinite_getters = [
|
||||
("Argument", "getAnArgument"),
|
||||
("Element", "getAnElement"),
|
||||
("Integer", "getAnInteger"),
|
||||
("Operator", "getAnOperator"),
|
||||
("Unit", "getAUnit"),
|
||||
("Whatever", "getAWhatever"),
|
||||
])
|
||||
]
|
||||
|
||||
@pytest.mark.parametrize("name,expected_getter", indefinite_getters)
|
||||
def test_property_indefinite_article(name, expected_getter):
|
||||
prop = ql.Property(name, plural="X")
|
||||
assert prop.indefinite_getter == expected_getter
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name,expected_getter", indefinite_getters)
|
||||
def test_property_unordered_getter(name, expected_getter):
|
||||
prop = ql.Property(name, plural="X", is_unordered=True)
|
||||
assert prop.getter == expected_getter
|
||||
|
||||
@pytest.mark.parametrize("plural,expected", [
|
||||
(None, False),
|
||||
("", False),
|
||||
|
@ -49,6 +56,16 @@ def test_property_is_repeated(plural, expected):
|
|||
prop = ql.Property("foo", "Foo", "props", ["result"], plural=plural)
|
||||
assert prop.is_repeated is expected
|
||||
|
||||
@pytest.mark.parametrize("plural,unordered,expected", [
|
||||
(None, False, False),
|
||||
("", False, False),
|
||||
("X", False, True),
|
||||
("X", True, False),
|
||||
])
|
||||
def test_property_is_indexed(plural, unordered, expected):
|
||||
prop = ql.Property("foo", "Foo", "props", ["result"], plural=plural, is_unordered=unordered)
|
||||
assert prop.is_indexed is expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("is_optional,is_predicate,plural,expected", [
|
||||
(False, False, None, True),
|
||||
|
|
|
@ -337,6 +337,22 @@ def test_repeated_property(generate_classes, is_child, prev_child):
|
|||
])),
|
||||
}
|
||||
|
||||
def test_repeated_unordered_property(generate_classes):
|
||||
assert generate_classes([
|
||||
schema.Class("FakeRoot"),
|
||||
schema.Class("MyObject", properties=[
|
||||
schema.RepeatedUnorderedProperty("foo", "bar")]),
|
||||
]) == {
|
||||
"FakeRoot.qll": (a_ql_stub(name="FakeRoot", base_import=gen_import_prefix + "FakeRoot"),
|
||||
a_ql_class(name="FakeRoot", final=True)),
|
||||
"MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"),
|
||||
a_ql_class(name="MyObject", final=True, properties=[
|
||||
ql.Property(singular="Foo", plural="Foos", type="bar", tablename="my_object_foos",
|
||||
tableparams=["this", "result"], is_unordered=True,
|
||||
doc="foo of this my object", doc_plural="foos of this my object"),
|
||||
])),
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("is_child,prev_child", [(False, None), (True, "")])
|
||||
def test_repeated_optional_property(generate_classes, is_child, prev_child):
|
||||
|
|
Загрузка…
Ссылка в новой задаче