mirror of
https://github.com/apple/pkl.git
synced 2026-05-25 16:19:20 +02:00
SPICE-0024: Annotation converters (#1333)
This enables defining declarative key and/or value transformations in cases where neither `Class`- nor path-based converters can be applied gracefully. It is also the only way to express transforming the resulting property names in `Typed` objects without applying a converter to the entire containing type, which is cumbersome at best. SPICE: https://github.com/apple/pkl-evolution/pull/26
This commit is contained in:
+19
@@ -0,0 +1,19 @@
|
||||
class LineComment extends ConvertProperty {
|
||||
text: String
|
||||
|
||||
valuePrefix: String = ""
|
||||
prefix: String
|
||||
suffix: String = ""
|
||||
|
||||
render = (prop, renderer) ->
|
||||
Pair(prop.key, new RenderDirective {
|
||||
text =
|
||||
List(
|
||||
valuePrefix,
|
||||
(renderer as ValueRenderer).renderValue(prop.value),
|
||||
prefix,
|
||||
outer.text,
|
||||
suffix,
|
||||
).join("")
|
||||
})
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
open class Prefix extends ConvertProperty {
|
||||
prefix: String
|
||||
|
||||
render = (prop, _) -> Pair(prefix + prop.key, prop.value)
|
||||
}
|
||||
|
||||
class CamelCase extends ConvertProperty {
|
||||
render = (prop, _) ->
|
||||
Pair(
|
||||
prop.key.replaceAllMapped(Regex("[^A-Za-z0-9]+([A-Za-z0-9])"), (match) ->
|
||||
match.groups[1].value.toUpperCase()
|
||||
),
|
||||
prop.value,
|
||||
)
|
||||
}
|
||||
|
||||
class MultiplyValue extends ConvertProperty {
|
||||
factor: Number
|
||||
render = (prop, _) ->
|
||||
Pair(prop.key, prop.value as Number * factor)
|
||||
}
|
||||
|
||||
class SubtractValue extends ConvertProperty {
|
||||
difference: Number
|
||||
render = (prop, _) ->
|
||||
Pair(prop.key, prop.value as Number - difference)
|
||||
}
|
||||
|
||||
open class Foo {
|
||||
no_converter: Int = 1
|
||||
|
||||
@Prefix { prefix = "foo_" }
|
||||
prefixed_with_foo: Int = 2
|
||||
|
||||
@Prefix { prefix = "foo_" }
|
||||
base_class_first: Int = 3
|
||||
|
||||
@MultiplyValue { factor = 2 }
|
||||
transform_value: Int = 4
|
||||
|
||||
@SubtractValue { difference = 2 }
|
||||
@MultiplyValue { factor = 3 }
|
||||
@ConvertProperty {
|
||||
render = (prop, _) -> Pair(prop.key, prop.value as Number + 4)
|
||||
}
|
||||
@MultiplyValue { factor = 3 }
|
||||
@SubtractValue { difference = 11 }
|
||||
in_order: Int = 5
|
||||
}
|
||||
|
||||
class Bar extends Foo {
|
||||
@CamelCase
|
||||
base_class_first: Int = 3
|
||||
}
|
||||
|
||||
output {
|
||||
value = new Bar {}
|
||||
renderer = new PcfRenderer {
|
||||
convertPropertyTransformers {
|
||||
[Prefix] { prefix = "foo_" }
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import "pkl:json"
|
||||
|
||||
import ".../input-helper/api/annotationConverter.pkl"
|
||||
|
||||
@json.Property { name = "FOO" }
|
||||
foo: String = "a"
|
||||
|
||||
@annotationConverter.LineComment { text = "bar" }
|
||||
bar: String = "b"
|
||||
|
||||
baz: Nested
|
||||
|
||||
class Nested {
|
||||
@annotationConverter.LineComment { text = "qux" }
|
||||
qux: String = "c"
|
||||
|
||||
quux: String = "c"
|
||||
}
|
||||
|
||||
output {
|
||||
renderer = new JsonRenderer {
|
||||
convertPropertyTransformers {
|
||||
// NB: this renders https://json5.org format which is a superset of JSON that supports commas.
|
||||
[annotationConverter.LineComment] { prefix = ", // " }
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
import "pkl:jsonnet"
|
||||
|
||||
import ".../input-helper/api/annotationConverter.pkl"
|
||||
|
||||
@jsonnet.Property { name = "FOO" }
|
||||
foo: String = "a"
|
||||
|
||||
@annotationConverter.LineComment { text = "bar" }
|
||||
bar: String = "b"
|
||||
|
||||
baz: Nested
|
||||
|
||||
class Nested {
|
||||
@annotationConverter.LineComment { text = "qux" }
|
||||
qux: String = "c"
|
||||
|
||||
quux: String = "c"
|
||||
}
|
||||
|
||||
output {
|
||||
renderer = new jsonnet.Renderer {
|
||||
convertPropertyTransformers {
|
||||
[annotationConverter.LineComment] { prefix = ", // " }
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import ".../input-helper/api/annotationConverter.pkl"
|
||||
|
||||
foo: String = "a"
|
||||
|
||||
@annotationConverter.LineComment { text = "bar" }
|
||||
bar: String = "b"
|
||||
|
||||
baz: Nested
|
||||
|
||||
class Nested {
|
||||
@annotationConverter.LineComment { text = "qux" }
|
||||
qux: String = "c"
|
||||
|
||||
quux: String = "c"
|
||||
}
|
||||
|
||||
output {
|
||||
renderer = new PListRenderer {
|
||||
convertPropertyTransformers {
|
||||
[annotationConverter.LineComment] { prefix = "<!-- "; suffix = " -->" }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import ".../input-helper/api/annotationConverter.pkl"
|
||||
|
||||
foo: String = "a"
|
||||
|
||||
@annotationConverter.LineComment { text = "bar" }
|
||||
bar: String = "b"
|
||||
|
||||
baz: Nested
|
||||
|
||||
class Nested {
|
||||
@annotationConverter.LineComment { text = "qux" }
|
||||
qux: String = "c"
|
||||
|
||||
quux: String = "c"
|
||||
}
|
||||
|
||||
output {
|
||||
renderer = new PcfRenderer {
|
||||
convertPropertyTransformers {
|
||||
[annotationConverter.LineComment] { prefix = " // "; valuePrefix = "= " }
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import ".../input-helper/api/annotationConverter.pkl"
|
||||
|
||||
foo: String = "a"
|
||||
|
||||
@annotationConverter.LineComment { text = "bar" }
|
||||
bar: String = "b"
|
||||
|
||||
baz: Nested
|
||||
|
||||
class Nested {
|
||||
@annotationConverter.LineComment { text = "qux" }
|
||||
qux: String = "c"
|
||||
|
||||
quux: String = "c"
|
||||
}
|
||||
|
||||
output {
|
||||
renderer = new PropertiesRenderer {
|
||||
convertPropertyTransformers {
|
||||
[annotationConverter.LineComment] { prefix = "\n# " }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import "pkl:protobuf"
|
||||
|
||||
import ".../input-helper/api/annotationConverter.pkl"
|
||||
|
||||
class Comment extends Annotation
|
||||
|
||||
@protobuf.Property { name = "FOO" }
|
||||
foo: String = "a"
|
||||
|
||||
@annotationConverter.LineComment { text = "bar" }
|
||||
bar: String = "b"
|
||||
|
||||
baz: Nested
|
||||
|
||||
class Nested {
|
||||
@annotationConverter.LineComment { text = "qux" }
|
||||
qux: String = "c"
|
||||
|
||||
quux: String = "c"
|
||||
}
|
||||
|
||||
output {
|
||||
renderer = new protobuf.Renderer {
|
||||
convertPropertyTransformers {
|
||||
[annotationConverter.LineComment] { prefix = " # " }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import "pkl:xml"
|
||||
|
||||
import ".../input-helper/api/annotationConverter.pkl"
|
||||
|
||||
@xml.Property { name = "FOO" }
|
||||
foo: String = "a"
|
||||
|
||||
@annotationConverter.LineComment { text = "bar" }
|
||||
bar: String = "b"
|
||||
|
||||
baz: Nested
|
||||
|
||||
class Nested {
|
||||
@annotationConverter.LineComment { text = "qux" }
|
||||
qux: String = "c"
|
||||
|
||||
quux: String = "c"
|
||||
}
|
||||
|
||||
output {
|
||||
renderer = new xml.Renderer {
|
||||
convertPropertyTransformers {
|
||||
[annotationConverter.LineComment] { prefix = "<!-- "; suffix = " -->" }
|
||||
}
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
import "pkl:yaml"
|
||||
|
||||
import ".../input-helper/api/annotationConverter.pkl"
|
||||
|
||||
class Tag extends ConvertProperty {
|
||||
tag: String(startsWith("!"))
|
||||
|
||||
render = (prop, renderer) ->
|
||||
if (renderer is YamlRenderer)
|
||||
Pair(prop.key, new RenderDirective {
|
||||
text = " \(tag) \(renderer.renderValue(prop.value))"
|
||||
})
|
||||
else
|
||||
prop
|
||||
}
|
||||
|
||||
@yaml.Property { name = "FOO" }
|
||||
foo: String = "a"
|
||||
|
||||
@annotationConverter.LineComment { text = "bar" }
|
||||
bar: String = "b"
|
||||
|
||||
baz: Nested
|
||||
|
||||
class Nested {
|
||||
@annotationConverter.LineComment { text = "qux" }
|
||||
qux: String = "c"
|
||||
|
||||
quux: String = "c"
|
||||
|
||||
@Tag { tag = "!!foo" }
|
||||
quuux: String = "d"
|
||||
}
|
||||
|
||||
output {
|
||||
renderer = new YamlRenderer {
|
||||
convertPropertyTransformers {
|
||||
[annotationConverter.LineComment] { prefix = " # "; valuePrefix = " " }
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
no_converter = 1
|
||||
foo_prefixed_with_foo = 2
|
||||
fooBaseClassFirst = 3
|
||||
transform_value = 8
|
||||
in_order = 28
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"FOO": "a",
|
||||
"bar": "b", // bar,
|
||||
"baz": {
|
||||
"qux": "c", // qux,
|
||||
"quux": "c"
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
FOO: 'a',
|
||||
bar: 'b', // bar,
|
||||
baz: {
|
||||
qux: 'c', // qux,
|
||||
quux: 'c',
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>foo</key>
|
||||
<string>a</string>
|
||||
<key>bar</key>
|
||||
<string>b</string><!-- bar -->
|
||||
<key>baz</key>
|
||||
<dict>
|
||||
<key>qux</key>
|
||||
<string>c</string><!-- qux -->
|
||||
<key>quux</key>
|
||||
<string>c</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,6 @@
|
||||
foo = "a"
|
||||
bar = "b" // bar
|
||||
baz {
|
||||
qux = "c" // qux
|
||||
quux = "c"
|
||||
}
|
||||
+6
@@ -172,6 +172,12 @@
|
||||
-
|
||||
- 3
|
||||
- {}
|
||||
-
|
||||
- 16
|
||||
- 'convertPropertyTransformers'
|
||||
-
|
||||
- 3
|
||||
- {}
|
||||
-
|
||||
- 16
|
||||
- 'extension'
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
foo = a
|
||||
bar = b
|
||||
# bar
|
||||
baz.qux = c
|
||||
# qux
|
||||
baz.quux = c
|
||||
@@ -0,0 +1,6 @@
|
||||
FOO: "a"
|
||||
bar: "b" # bar
|
||||
baz: {
|
||||
qux: "c" # qux
|
||||
quux: "c"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<root>
|
||||
<FOO>a</FOO>
|
||||
<bar>b<!-- bar --></bar>
|
||||
<baz>
|
||||
<qux>c<!-- qux --></qux>
|
||||
<quux>c</quux>
|
||||
</baz>
|
||||
</root>
|
||||
@@ -0,0 +1,6 @@
|
||||
FOO: a
|
||||
bar: b # bar
|
||||
baz:
|
||||
qux: c # qux
|
||||
quux: c
|
||||
quuux: !!foo d
|
||||
Reference in New Issue
Block a user