YamlRenderer: allow all primitive scalar types as map keys (#879)

This commit is contained in:
Josh B
2025-01-13 16:22:52 -08:00
committed by GitHub
parent 267de3c789
commit 160e4a5636
6 changed files with 101 additions and 10 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -415,6 +415,16 @@ public abstract class AbstractRenderer implements VmValueVisitor {
.build();
}
protected void cannotRenderNonScalarKey(Object key) {
assert enclosingValue != null;
var isMap = enclosingValue instanceof VmMap;
throw new VmExceptionBuilder()
.evalError(isMap ? "cannotRenderNonScalarMap" : "cannotRenderObjectWithNonScalarKey", name)
.withProgramValue(isMap ? "Map" : "Object", enclosingValue)
.withProgramValue("Key", key)
.build();
}
protected void increaseIndent() {
currIndent.append(indent);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -278,8 +278,24 @@ public final class YamlRendererNodes {
startNewLine();
}
if (key instanceof String string) {
emitter.emit(string, currIndent, true);
if (key instanceof String stringKey) {
emitter.emit(stringKey, currIndent, true);
builder.append(':');
return;
} else if (key instanceof Long longKey) {
emitter.emit(longKey);
builder.append(':');
return;
} else if (key instanceof Double doubleKey) {
emitter.emit(doubleKey);
builder.append(':');
return;
} else if (key instanceof Boolean booleanKey) {
emitter.emit(booleanKey);
builder.append(':');
return;
} else if (key instanceof VmNull) {
emitter.emitNull();
builder.append(':');
return;
}
@@ -290,7 +306,7 @@ public final class YamlRendererNodes {
return;
}
cannotRenderNonStringKey(key);
cannotRenderNonScalarKey(key);
}
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -310,7 +310,7 @@ public final class RendererNodes {
isDirective || key instanceof Long || key instanceof Boolean || key instanceof String;
if (!isValidKey) {
throw new VmExceptionBuilder()
.evalError("cannotRenderNonScalarMapKey")
.evalError("cannotRenderProtobufMapKey")
.withProgramValue("Key", key)
.build();
}
@@ -583,7 +583,7 @@ public final class RendererNodes {
|| keyType instanceof StringTypeNode
|| keyType instanceof BooleanTypeNode)) {
throw new VmExceptionBuilder()
.evalError("cannotRenderNonScalarMapKeyType")
.evalError("cannotRenderProtobufMapKeyType")
.withSourceSection(type.getSourceSection())
.build();
}

View File

@@ -608,10 +608,16 @@ Cannot render map with non-string key as {0}.
cannotRenderObjectWithNonStringKey=\
Cannot render object with non-string key as {0}.
cannotRenderNonScalarMapKey=\
cannotRenderNonScalarMap=\
Cannot render map with non-scalar key as {0}.
cannotRenderObjectWithNonScalarKey=\
Cannot render object with non-scalar key as {0}.
cannotRenderProtobufMapKey=\
Cannot render map with a non-scalar, floating point or byte array key.
cannotRenderNonScalarMapKeyType=\
cannotRenderProtobufMapKeyType=\
Cannot render map with a non-scalar, floating point or byte array key type.
cannotRenderObjectWithElementsAndOtherMembers=\

View File

@@ -0,0 +1,33 @@
// Test that non-String scalars can be rendered as YAML map keys.
mappingInt = new Mapping {
[5] = "abc"
[10] = "def"
[20] = "ghi"
}
mapInt = mappingInt.toMap()
mappingFloat = new Mapping {
[5.0] = "abc"
[10.5] = "def"
[20.999999990] = "ghi"
}
mapFloat = mappingFloat.toMap()
mappingBool = new Mapping {
[true] = "abc"
[false] = "def"
}
mapBool = mappingBool.toMap()
mappingNull = new Mapping {
[null] = "abc"
}
mapNull = mappingNull.toMap()
output {
renderer = new YamlRenderer {}
}

View File

@@ -0,0 +1,26 @@
mappingInt:
5: abc
10: def
20: ghi
mapInt:
5: abc
10: def
20: ghi
mappingFloat:
5.0: abc
10.5: def
20.99999999: ghi
mapFloat:
5.0: abc
10.5: def
20.99999999: ghi
mappingBool:
true: abc
false: def
mapBool:
true: abc
false: def
mappingNull:
null: abc
mapNull:
null: abc