Skip to content

Commit 6830c2f

Browse files
committed
Swift: enhance property docs
1 parent 9abaa5c commit 6830c2f

File tree

133 files changed

+939
-642
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

133 files changed

+939
-642
lines changed

swift/codegen/generators/qlgen.py

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,49 @@ class NoClasses(Error):
5555
pass
5656

5757

58-
def _humanize(s):
58+
abbreviations = {
59+
"expr": "expression",
60+
"arg": "argument",
61+
"stmt": "statement",
62+
"decl": "declaration",
63+
"repr": "representation",
64+
"param": "parameter",
65+
}
66+
67+
abbreviations.update({f"{k}s": f"{v}s" for k, v in abbreviations.items()})
68+
69+
_abbreviations_re = re.compile("|".join(fr"\b{abbr}\b" for abbr in abbreviations))
70+
71+
72+
def _humanize(s: str) -> str:
5973
ret = inflection.humanize(s)
60-
return re.sub(r"^\w", lambda m: m[0].lower(), ret)
74+
ret = ret[0].lower() + ret[1:]
75+
ret = _abbreviations_re.sub(lambda m: abbreviations[m[0]], ret)
76+
return ret
77+
78+
79+
_format_re = re.compile(r"\{(\w+)\}")
80+
81+
82+
def _get_doc(cls: schema.Class, prop: schema.Property, plural=None):
83+
if prop.doc:
84+
if plural is None:
85+
# for consistency, ignore format in non repeated properties
86+
return _format_re.sub(lambda m: m[1], prop.doc)
87+
format = prop.doc
88+
nouns = [m[1] for m in _format_re.finditer(prop.doc)]
89+
if not nouns:
90+
noun, _, rest = prop.doc.partition(" ")
91+
format = f"{{{noun}}} {rest}"
92+
nouns = [noun]
93+
transform = inflection.pluralize if plural else inflection.singularize
94+
return format.format(**{noun: transform(noun) for noun in nouns})
95+
96+
prop_name = _humanize(prop.name)
97+
class_name = _humanize(inflection.underscore(cls.name))
98+
if plural is not None:
99+
prop_name = inflection.pluralize(prop_name) if plural else inflection.singularize(prop_name)
100+
return f"{prop_name} of this {class_name}"
61101

62102

63103
def get_ql_property(cls: schema.Class, prop: schema.Property, prev_child: str = "") -> ql.Property:
@@ -67,30 +107,30 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, prev_child: str =
67107
prev_child=prev_child if prop.is_child else None,
68108
is_optional=prop.is_optional,
69109
is_predicate=prop.is_predicate,
70-
description=prop.description,
110+
description=prop.description
71111
)
72112
if prop.is_single:
73113
args.update(
74114
singular=inflection.camelize(prop.name),
75115
tablename=inflection.tableize(cls.name),
76116
tableparams=["this"] + ["result" if p is prop else "_" for p in cls.properties if p.is_single],
77-
doc=_humanize(prop.doc or prop.name),
117+
doc=_get_doc(cls, prop),
78118
)
79119
elif prop.is_repeated:
80120
args.update(
81121
singular=inflection.singularize(inflection.camelize(prop.name)),
82122
plural=inflection.pluralize(inflection.camelize(prop.name)),
83123
tablename=inflection.tableize(f"{cls.name}_{prop.name}"),
84124
tableparams=["this", "index", "result"],
85-
doc=_humanize(inflection.singularize(prop.doc or prop.name)),
86-
doc_plural=_humanize(inflection.pluralize(prop.doc or prop.name))
125+
doc=_get_doc(cls, prop, plural=False),
126+
doc_plural=_get_doc(cls, prop, plural=True),
87127
)
88128
elif prop.is_optional:
89129
args.update(
90130
singular=inflection.camelize(prop.name),
91131
tablename=inflection.tableize(f"{cls.name}_{prop.name}"),
92132
tableparams=["this", "result"],
93-
doc=_humanize(prop.doc or prop.name),
133+
doc=_get_doc(cls, prop),
94134
)
95135
elif prop.is_predicate:
96136
args.update(

swift/codegen/templates/ql_class.mustache

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ module Generated {
5959

6060
{{#type_is_class}}
6161
/**
62-
* {{>ql_property_doc}} * This includes nodes from the "hidden" AST and can be used to be overridden by subclasses.
62+
* {{>ql_property_doc}} *
63+
* This includes nodes from the "hidden" AST.
6364
*/
6465
{{type}} getImmediate{{singular}}({{#is_repeated}}int index{{/is_repeated}}) {
6566
{{^ipa}}

swift/codegen/test/test_qlgen.py

Lines changed: 110 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ def test_single_property(generate_classes):
190190
ql.Class(name="MyObject", final=True,
191191
properties=[
192192
ql.Property(singular="Foo", type="bar", tablename="my_objects",
193-
tableparams=["this", "result"], doc="foo"),
193+
tableparams=["this", "result"], doc="foo of this my object"),
194194
])),
195195
}
196196

@@ -215,31 +215,31 @@ def test_children(generate_classes):
215215
ql.Class(name="MyObject", final=True,
216216
properties=[
217217
ql.Property(singular="A", type="int", tablename="my_objects",
218-
tableparams=["this", "result", "_"], doc="a"),
218+
tableparams=["this", "result", "_"], doc="a of this my object"),
219219
ql.Property(singular="Child1", type="int", tablename="my_objects",
220220
tableparams=["this", "_", "result"], prev_child="",
221-
doc="child 1"),
221+
doc="child 1 of this my object"),
222222
ql.Property(singular="B", plural="Bs", type="int",
223223
tablename="my_object_bs",
224224
tableparams=["this", "index", "result"],
225-
doc="b", doc_plural="bs"),
225+
doc="b of this my object", doc_plural="bs of this my object"),
226226
ql.Property(singular="Child", plural="Children", type="int",
227227
tablename="my_object_children",
228228
tableparams=["this", "index", "result"], prev_child="Child1",
229-
doc="child", doc_plural="children"),
229+
doc="child of this my object", doc_plural="children of this my object"),
230230
ql.Property(singular="C", type="int", tablename="my_object_cs",
231-
tableparams=["this", "result"], is_optional=True, doc="c"),
231+
tableparams=["this", "result"], is_optional=True, doc="c of this my object"),
232232
ql.Property(singular="Child3", type="int", tablename="my_object_child_3s",
233233
tableparams=["this", "result"], is_optional=True,
234-
prev_child="Child", doc="child 3"),
234+
prev_child="Child", doc="child 3 of this my object"),
235235
ql.Property(singular="D", plural="Ds", type="int",
236236
tablename="my_object_ds",
237237
tableparams=["this", "index", "result"], is_optional=True,
238-
doc="d", doc_plural="ds"),
238+
doc="d of this my object", doc_plural="ds of this my object"),
239239
ql.Property(singular="Child4", plural="Child4s", type="int",
240240
tablename="my_object_child_4s",
241241
tableparams=["this", "index", "result"], is_optional=True,
242-
prev_child="Child3", doc="child 4", doc_plural="child 4s"),
242+
prev_child="Child3", doc="child 4 of this my object", doc_plural="child 4s of this my object"),
243243
])),
244244
}
245245

@@ -256,11 +256,11 @@ def test_single_properties(generate_classes):
256256
ql.Class(name="MyObject", final=True,
257257
properties=[
258258
ql.Property(singular="One", type="x", tablename="my_objects",
259-
tableparams=["this", "result", "_", "_"], doc="one"),
259+
tableparams=["this", "result", "_", "_"], doc="one of this my object"),
260260
ql.Property(singular="Two", type="y", tablename="my_objects",
261-
tableparams=["this", "_", "result", "_"], doc="two"),
261+
tableparams=["this", "_", "result", "_"], doc="two of this my object"),
262262
ql.Property(singular="Three", type="z", tablename="my_objects",
263-
tableparams=["this", "_", "_", "result"], doc="three"),
263+
tableparams=["this", "_", "_", "result"], doc="three of this my object"),
264264
])),
265265
}
266266

@@ -278,7 +278,7 @@ def test_optional_property(generate_classes, is_child, prev_child):
278278
ql.Class(name="MyObject", final=True, properties=[
279279
ql.Property(singular="Foo", type="bar", tablename="my_object_foos",
280280
tableparams=["this", "result"],
281-
is_optional=True, prev_child=prev_child, doc="foo"),
281+
is_optional=True, prev_child=prev_child, doc="foo of this my object"),
282282
])),
283283
}
284284

@@ -296,7 +296,7 @@ def test_repeated_property(generate_classes, is_child, prev_child):
296296
ql.Class(name="MyObject", final=True, properties=[
297297
ql.Property(singular="Foo", plural="Foos", type="bar", tablename="my_object_foos",
298298
tableparams=["this", "index", "result"], prev_child=prev_child,
299-
doc="foo", doc_plural="foos"),
299+
doc="foo of this my object", doc_plural="foos of this my object"),
300300
])),
301301
}
302302

@@ -315,7 +315,7 @@ def test_repeated_optional_property(generate_classes, is_child, prev_child):
315315
ql.Class(name="MyObject", final=True, properties=[
316316
ql.Property(singular="Foo", plural="Foos", type="bar", tablename="my_object_foos",
317317
tableparams=["this", "index", "result"], is_optional=True,
318-
prev_child=prev_child, doc="foo", doc_plural="foos"),
318+
prev_child=prev_child, doc="foo of this my object", doc_plural="foos of this my object"),
319319
])),
320320
}
321321

@@ -346,7 +346,7 @@ def test_single_class_property(generate_classes, is_child, prev_child):
346346
ql.Property(singular="Foo", type="Bar", tablename="my_objects",
347347
tableparams=[
348348
"this", "result"],
349-
prev_child=prev_child, doc="foo"),
349+
prev_child=prev_child, doc="foo of this my object"),
350350
],
351351
)),
352352
"Bar.qll": (ql.Stub(name="Bar", base_import=gen_import_prefix + "Bar"),
@@ -644,7 +644,8 @@ def test_property_description(generate_classes):
644644
ql.Class(name="MyObject", final=True,
645645
properties=[
646646
ql.Property(singular="Foo", type="bar", tablename="my_objects",
647-
tableparams=["this", "result"], doc="foo",
647+
tableparams=["this", "result"],
648+
doc="foo of this my object",
648649
description=description),
649650
])),
650651
}
@@ -667,20 +668,108 @@ def test_property_doc_override(generate_classes):
667668
def test_repeated_property_doc_override(generate_classes):
668669
assert generate_classes([
669670
schema.Class("MyObject", properties=[
670-
schema.RepeatedProperty("x", "int", doc="children"),
671-
schema.RepeatedOptionalProperty("y", "int", doc="child")]),
671+
schema.RepeatedProperty("x", "int", doc="children of this"),
672+
schema.RepeatedOptionalProperty("y", "int", doc="child of this")]),
672673
]) == {
673674
"MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"),
674675
ql.Class(name="MyObject", final=True,
675676
properties=[
676677
ql.Property(singular="X", plural="Xes", type="int",
677678
tablename="my_object_xes",
678679
tableparams=["this", "index", "result"],
679-
doc="child", doc_plural="children"),
680+
doc="child of this", doc_plural="children of this"),
680681
ql.Property(singular="Y", plural="Ys", type="int",
681682
tablename="my_object_ies", is_optional=True,
682683
tableparams=["this", "index", "result"],
683-
doc="child", doc_plural="children"),
684+
doc="child of this", doc_plural="children of this"),
685+
])),
686+
}
687+
688+
689+
@pytest.mark.parametrize("abbr,expected", list(qlgen.abbreviations.items()))
690+
def test_property_doc_abbreviations(generate_classes, abbr, expected):
691+
expected_doc = f"foo {expected} bar of this object"
692+
assert generate_classes([
693+
schema.Class("Object", properties=[
694+
schema.SingleProperty(f"foo_{abbr}_bar", "baz")]),
695+
]) == {
696+
"Object.qll": (ql.Stub(name="Object", base_import=gen_import_prefix + "Object"),
697+
ql.Class(name="Object", final=True,
698+
properties=[
699+
ql.Property(singular=f"Foo{abbr.capitalize()}Bar", type="baz", tablename="objects",
700+
tableparams=["this", "result"], doc=expected_doc),
701+
])),
702+
}
703+
704+
705+
@pytest.mark.parametrize("abbr,expected", list(qlgen.abbreviations.items()))
706+
def test_property_doc_abbreviations_ignored_if_within_word(generate_classes, abbr, expected):
707+
expected_doc = f"foo {abbr}acadabra bar of this object"
708+
assert generate_classes([
709+
schema.Class("Object", properties=[
710+
schema.SingleProperty(f"foo_{abbr}acadabra_bar", "baz")]),
711+
]) == {
712+
"Object.qll": (ql.Stub(name="Object", base_import=gen_import_prefix + "Object"),
713+
ql.Class(name="Object", final=True,
714+
properties=[
715+
ql.Property(singular=f"Foo{abbr.capitalize()}acadabraBar", type="baz", tablename="objects",
716+
tableparams=["this", "result"], doc=expected_doc),
717+
])),
718+
}
719+
720+
721+
def test_repeated_property_doc_override_with_format(generate_classes):
722+
assert generate_classes([
723+
schema.Class("MyObject", properties=[
724+
schema.RepeatedProperty("x", "int", doc="special {children} of this"),
725+
schema.RepeatedOptionalProperty("y", "int", doc="special {child} of this")]),
726+
]) == {
727+
"MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"),
728+
ql.Class(name="MyObject", final=True,
729+
properties=[
730+
ql.Property(singular="X", plural="Xes", type="int",
731+
tablename="my_object_xes",
732+
tableparams=["this", "index", "result"],
733+
doc="special child of this", doc_plural="special children of this"),
734+
ql.Property(singular="Y", plural="Ys", type="int",
735+
tablename="my_object_ies", is_optional=True,
736+
tableparams=["this", "index", "result"],
737+
doc="special child of this", doc_plural="special children of this"),
738+
])),
739+
}
740+
741+
742+
def test_repeated_property_doc_override_with_multiple_formats(generate_classes):
743+
assert generate_classes([
744+
schema.Class("MyObject", properties=[
745+
schema.RepeatedProperty("x", "int", doc="{cat} or {dog}"),
746+
schema.RepeatedOptionalProperty("y", "int", doc="{cats} or {dogs}")]),
747+
]) == {
748+
"MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"),
749+
ql.Class(name="MyObject", final=True,
750+
properties=[
751+
ql.Property(singular="X", plural="Xes", type="int",
752+
tablename="my_object_xes",
753+
tableparams=["this", "index", "result"],
754+
doc="cat or dog", doc_plural="cats or dogs"),
755+
ql.Property(singular="Y", plural="Ys", type="int",
756+
tablename="my_object_ies", is_optional=True,
757+
tableparams=["this", "index", "result"],
758+
doc="cat or dog", doc_plural="cats or dogs"),
759+
])),
760+
}
761+
762+
763+
def test_property_doc_override_with_format(generate_classes):
764+
assert generate_classes([
765+
schema.Class("MyObject", properties=[
766+
schema.SingleProperty("foo", "bar", doc="special {baz} of this")]),
767+
]) == {
768+
"MyObject.qll": (ql.Stub(name="MyObject", base_import=gen_import_prefix + "MyObject"),
769+
ql.Class(name="MyObject", final=True,
770+
properties=[
771+
ql.Property(singular="Foo", type="bar", tablename="my_objects",
772+
tableparams=["this", "result"], doc="special baz of this"),
684773
])),
685774
}
686775

0 commit comments

Comments
 (0)