Skip to content

Commit 8813aea

Browse files
committed
Swift: allow default class doc name to be set for properties
1 parent c22a7e1 commit 8813aea

File tree

7 files changed

+59
-17
lines changed

7 files changed

+59
-17
lines changed

swift/codegen/generators/qlgen.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ def _get_doc(cls: schema.Class, prop: schema.Property, plural=None):
9595
return format.format(**{noun: transform(noun) for noun in nouns})
9696

9797
prop_name = _humanize(prop.name)
98-
class_name = _humanize(inflection.underscore(cls.name))
98+
class_name = cls.default_doc_name or _humanize(inflection.underscore(cls.name))
9999
if prop.is_predicate:
100100
return f"this {class_name} {prop_name}"
101101
if plural is not None:

swift/codegen/lib/schema/defs.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,13 @@ def include(source: str):
3333
"__includes", []).append(source)
3434

3535

36+
@_dataclass
3637
class _Pragma(_schema.PropertyModifier):
3738
""" A class or property pragma.
3839
For properties, it functions similarly to a `_PropertyModifier` with `|`, adding the pragma.
3940
For schema classes it acts as a python decorator with `@`.
4041
"""
41-
42-
def __init__(self, pragma):
43-
self.pragma = pragma
42+
pragma: str
4443

4544
def modify(self, prop: _schema.Property):
4645
prop.pragmas.append(self.pragma)
@@ -54,6 +53,15 @@ def __call__(self, cls: type) -> type:
5453
return cls
5554

5655

56+
@_dataclass
57+
class _DefaultDocNameClassModifier:
58+
doc_name: str
59+
60+
def __call__(self, cls: type) -> type:
61+
cls._doc_name = self.doc_name
62+
return cls
63+
64+
5765
class _Optionalizer(_schema.PropertyModifier):
5866
def modify(self, prop: _schema.Property):
5967
K = _schema.Property.Kind
@@ -122,6 +130,10 @@ def f(cls: type) -> type:
122130
uncollapse_hierarchy=_Pragma("qltest_uncollapse_hierarchy"),
123131
)
124132

133+
ql = _Namespace(
134+
default_doc_name=_DefaultDocNameClassModifier,
135+
)
136+
125137
cpp = _Namespace(
126138
skip=_Pragma("cpp_skip"),
127139
)

swift/codegen/lib/schema/schema.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class Class:
8080
pragmas: List[str] = field(default_factory=list)
8181
ipa: Optional[IpaInfo] = None
8282
doc: List[str] = field(default_factory=list)
83+
default_doc_name: Optional[str] = None
8384

8485
@property
8586
def final(self):
@@ -207,6 +208,7 @@ def _get_class(cls: type) -> Class:
207208
for n, a in cls.__dict__.get("__annotations__", {}).items()
208209
],
209210
doc=split_doc(cls.__doc__),
211+
default_doc_name=cls.__dict__.get("_doc_name"),
210212
)
211213

212214

swift/codegen/test/test_qlgen.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,5 +774,20 @@ def test_property_doc_override_with_format(generate_classes):
774774
}
775775

776776

777+
def test_property_on_class_with_default_doc_name(generate_classes):
778+
assert generate_classes([
779+
schema.Class("MyObject", properties=[
780+
schema.SingleProperty("foo", "bar")],
781+
default_doc_name="baz"),
782+
]) == {
783+
"MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"),
784+
ql.Class(name="MyObject", final=True,
785+
properties=[
786+
ql.Property(singular="Foo", type="bar", tablename="my_objects",
787+
tableparams=["this", "result"], doc="foo of this baz"),
788+
])),
789+
}
790+
791+
777792
if __name__ == '__main__':
778793
sys.exit(pytest.main([__file__] + sys.argv[1:]))

swift/codegen/test/test_schema.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,5 +554,17 @@ class A:
554554
}
555555

556556

557+
def test_class_default_doc_name():
558+
@schema.load
559+
class data:
560+
@defs.ql.default_doc_name("b")
561+
class A:
562+
pass
563+
564+
assert data.classes == {
565+
'A': schema.Class('A', default_doc_name="b"),
566+
}
567+
568+
557569
if __name__ == '__main__':
558570
sys.exit(pytest.main([__file__] + sys.argv[1:]))

swift/ql/lib/codeql/swift/generated/type/AnyFunctionType.qll

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import codeql.swift.elements.type.Type
66
module Generated {
77
class AnyFunctionType extends Synth::TAnyFunctionType, Type {
88
/**
9-
* Gets the result of this any function type.
9+
* Gets the result of this function type.
1010
*
1111
* This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the
1212
* behaviour of both the `Immediate` and non-`Immediate` versions.
@@ -19,12 +19,12 @@ module Generated {
1919
}
2020

2121
/**
22-
* Gets the result of this any function type.
22+
* Gets the result of this function type.
2323
*/
2424
final Type getResult() { result = getImmediateResult().resolve() }
2525

2626
/**
27-
* Gets the `index`th parameter type of this any function type (0-based).
27+
* Gets the `index`th parameter type of this function type (0-based).
2828
*
2929
* This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the
3030
* behaviour of both the `Immediate` and non-`Immediate` versions.
@@ -37,46 +37,46 @@ module Generated {
3737
}
3838

3939
/**
40-
* Gets the `index`th parameter type of this any function type (0-based).
40+
* Gets the `index`th parameter type of this function type (0-based).
4141
*/
4242
final Type getParamType(int index) { result = getImmediateParamType(index).resolve() }
4343

4444
/**
45-
* Gets any of the parameter types of this any function type.
45+
* Gets any of the parameter types of this function type.
4646
*/
4747
final Type getAParamType() { result = getParamType(_) }
4848

4949
/**
50-
* Gets the number of parameter types of this any function type.
50+
* Gets the number of parameter types of this function type.
5151
*/
5252
final int getNumberOfParamTypes() { result = count(getAParamType()) }
5353

5454
/**
55-
* Gets the `index`th parameter label of this any function type (0-based).
55+
* Gets the `index`th parameter label of this function type (0-based).
5656
*/
5757
string getParamLabel(int index) {
5858
result = Synth::convertAnyFunctionTypeToRaw(this).(Raw::AnyFunctionType).getParamLabel(index)
5959
}
6060

6161
/**
62-
* Gets any of the parameter labels of this any function type.
62+
* Gets any of the parameter labels of this function type.
6363
*/
6464
final string getAParamLabel() { result = getParamLabel(_) }
6565

6666
/**
67-
* Gets the number of parameter labels of this any function type.
67+
* Gets the number of parameter labels of this function type.
6868
*/
6969
final int getNumberOfParamLabels() { result = count(getAParamLabel()) }
7070

7171
/**
72-
* Holds if this any function type is throwing.
72+
* Holds if this type refers to a throwing function.
7373
*/
7474
predicate isThrowing() {
7575
Synth::convertAnyFunctionTypeToRaw(this).(Raw::AnyFunctionType).isThrowing()
7676
}
7777

7878
/**
79-
* Holds if this any function type is async.
79+
* Holds if this type refers to an `async` function.
8080
*/
8181
predicate isAsync() {
8282
Synth::convertAnyFunctionTypeToRaw(this).(Raw::AnyFunctionType).isAsync()

swift/schema.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -783,12 +783,13 @@ class WhileStmt(LabeledConditionalStmt):
783783
class TypeRepr(AstNode):
784784
type: Type
785785

786+
@ql.default_doc_name("function type")
786787
class AnyFunctionType(Type):
787788
result: Type
788789
param_types: list[Type]
789790
param_labels: list[string]
790-
is_throwing: predicate
791-
is_async: predicate
791+
is_throwing: predicate | doc("this type refers to a throwing function")
792+
is_async: predicate | doc("this type refers to an `async` function")
792793

793794
class AnyGenericType(Type):
794795
parent: optional[Type]

0 commit comments

Comments
 (0)