From ed782c97c4b9d9c4569f998a4229b7ad5ad3388a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= Date: Wed, 27 Jul 2022 13:02:40 +0200 Subject: [PATCH] Take into account that configuration properties can contain a dot in RunTimeConfigurationGenerator Otherwise we sometimes get a bug where Quarkus would get to the wrong index when parsing a configuration property, and would end up mistakenly reporting missing configuration properties (in a really puzzling error message...). --- .../RunTimeConfigurationGenerator.java | 49 +++++++++++-------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java b/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java index 9427194fd7f49..d9fca767658fc 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java @@ -1310,10 +1310,7 @@ private MethodDescriptor generateParserBody(final ConfigPatternMap ke if (matched instanceof FieldContainer) { final FieldContainer fieldContainer = (FieldContainer) matched; if (dynamic) { - if (!itemMember.getPropertyName().isEmpty()) { - // consume segment - matchedBody.invokeVirtualMethod(NI_PREVIOUS, keyIter); - } + generateConsumeSegments(matchedBody, keyIter, itemMember.getPropertyName()); // we have to get or create all containing (and contained) groups of this member matchedBody.invokeStaticMethod(generateGetEnclosing(fieldContainer, type), keyIter, config); @@ -1467,10 +1464,7 @@ private MethodDescriptor generateGetEnclosing(final FieldContainer matchNode, fi // get the parent final FieldContainer fieldContainer = (FieldContainer) parent; final ClassDefinition.ClassMember classMember = fieldContainer.getClassMember(); - if (!classMember.getPropertyName().isEmpty()) { - // consume segment - mc.invokeVirtualMethod(NI_PREVIOUS, keyIter); - } + int consumedSegmentsCount = generateConsumeSegments(mc, keyIter, classMember.getPropertyName()); final ResultHandle enclosing = mc.invokeStaticMethod(generateGetEnclosing(fieldContainer, type), keyIter, config); @@ -1518,10 +1512,7 @@ private MethodDescriptor generateGetEnclosing(final FieldContainer matchNode, fi } else { mc.assign(group, fieldVal); } - if (!classMember.getPropertyName().isEmpty()) { - // restore - mc.invokeVirtualMethod(NI_NEXT, keyIter); - } + generateRestoreSegments(mc, keyIter, consumedSegmentsCount); mc.returnValue(group); } else { assert parent instanceof MapContainer; @@ -1576,16 +1567,11 @@ private MethodDescriptor generateGetEnclosing(final MapContainer matchNode, fina if (parent instanceof FieldContainer) { // get the parent final FieldContainer fieldContainer = (FieldContainer) parent; - if (!fieldContainer.getClassMember().getPropertyName().isEmpty()) { - // consume segment - mc.invokeVirtualMethod(NI_PREVIOUS, keyIter); - } + int consumedSegmentsCount = generateConsumeSegments(mc, keyIter, + fieldContainer.getClassMember().getPropertyName()); final ResultHandle enclosing = mc.invokeStaticMethod(generateGetEnclosing(fieldContainer, type), keyIter, config); - if (!fieldContainer.getClassMember().getPropertyName().isEmpty()) { - // restore - mc.invokeVirtualMethod(NI_NEXT, keyIter); - } + generateRestoreSegments(mc, keyIter, consumedSegmentsCount); final ResultHandle result; if (isFieldEligibleForDirectAccess(fieldContainer.getClassMember())) { @@ -1619,6 +1605,29 @@ private MethodDescriptor generateGetEnclosing(final MapContainer matchNode, fina return md; } + private int generateConsumeSegments(BytecodeCreator bc, ResultHandle keyIter, String propertyName) { + if (propertyName.isEmpty()) { + return 0; + } + bc.invokeVirtualMethod(NI_PREVIOUS, keyIter); + int consumedSegmentsCount = 1; + // For properties whose name contains dots, + // we need to call previous() multiple times + int dotIndex = propertyName.indexOf('.'); + while (dotIndex >= 0) { + bc.invokeVirtualMethod(NI_PREVIOUS, keyIter); + ++consumedSegmentsCount; + dotIndex = propertyName.indexOf('.', dotIndex + 1); + } + return consumedSegmentsCount; + } + + private void generateRestoreSegments(BytecodeCreator bc, ResultHandle keyIter, int consumedSegmentsCount) { + for (int i = 0; i < consumedSegmentsCount; i++) { + bc.invokeVirtualMethod(NI_NEXT, keyIter); + } + } + private FieldDescriptor getOrCreateConverterInstance(Field field) { return getOrCreateConverterInstance(field, ConverterType.of(field)); }