DSL Items Parser: Fix incorrect parsing of keywords encountered in the wrong context (#4928)

* DSL Items Parser: Fix incorrect parsing of keywords encountered in the wrong context

When specifying tag names that match one of the valid item types, e.g. `Switch`, the parser incorrectly treated it as a new start of an item definition.

Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
This commit is contained in:
jimtng
2025-09-21 14:14:24 +02:00
committed by GitHub
parent 00b6a476a7
commit 7c848bf891
16 changed files with 360 additions and 170 deletions
@@ -43,6 +43,7 @@ Fragment-Host: org.openhab.core.model.item
org.eclipse.equinox.common;version='[3.19.0,3.19.1)',\
junit-jupiter-api;version='[5.13.4,5.13.5)',\
junit-jupiter-engine;version='[5.13.4,5.13.5)',\
junit-jupiter-params;version='[5.13.4,5.13.5)',\
junit-platform-commons;version='[1.13.4,1.13.5)',\
junit-platform-engine;version='[1.13.4,1.13.5)',\
junit-platform-launcher;version='[1.13.4,1.13.5)',\
@@ -27,11 +27,15 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.openhab.core.events.Event;
import org.openhab.core.events.EventSubscriber;
import org.openhab.core.items.GenericItem;
@@ -47,10 +51,12 @@ import org.openhab.core.items.events.AbstractItemRegistryEvent;
import org.openhab.core.items.events.ItemAddedEvent;
import org.openhab.core.items.events.ItemRemovedEvent;
import org.openhab.core.items.events.ItemUpdatedEvent;
import org.openhab.core.library.CoreItemFactory;
import org.openhab.core.library.items.NumberItem;
import org.openhab.core.library.items.SwitchItem;
import org.openhab.core.library.types.ArithmeticGroupFunction;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.QuantityTypeArithmeticGroupFunction;
import org.openhab.core.model.core.EventType;
import org.openhab.core.model.core.ModelRepository;
import org.openhab.core.model.core.ModelRepositoryChangeListener;
@@ -403,6 +409,34 @@ public class GenericItemProviderTest extends JavaOSGiTest {
});
}
private static Stream<Arguments> testGroupTypeSyntax() {
return Stream.of( //
Arguments.of("Group:Number Grp", "Number", GroupFunction.Equality.class),
Arguments.of("Group:Number:MAX Grp", "Number", ArithmeticGroupFunction.Max.class),
Arguments.of("Group:Number:Power Grp", "Number:Power", GroupFunction.Equality.class),
Arguments.of("Group:Number:Power:MAX Grp", "Number:Power",
QuantityTypeArithmeticGroupFunction.Max.class),
Arguments.of("Group:Switch:OR(ON,OFF) Grp", "Switch", ArithmeticGroupFunction.Or.class));
}
@ParameterizedTest
@MethodSource
public void testGroupTypeSyntax(String model, String expectedBaseType,
Class<? extends GroupFunction> expectedFunction) {
modelRepository.addOrRefreshModel(TESTMODEL_NAME, new ByteArrayInputStream(model.getBytes()));
assertThat(itemRegistry.getAll(), hasSize(1));
if (itemRegistry.getAll().iterator().next() instanceof GroupItem groupItem) {
assertThat(groupItem.getBaseItem(), is(notNullValue()));
assertThat(groupItem.getBaseItem().getType(), is(expectedBaseType));
assertThat(groupItem.getFunction(), instanceOf(expectedFunction));
} else {
throw new AssertionError("Item is not a GroupItem");
}
}
@Test
public void testStableOrder() {
String model = "Group testGroup " + //
@@ -711,4 +745,43 @@ public class GenericItemProviderTest extends JavaOSGiTest {
assertThat(stateDescription, is(notNullValue()));
assertThat(stateDescription.getPattern(), is("%s"));
}
@Test
public void testKeywordsInOtherFields() {
String itemTypeList = CoreItemFactory.VALID_ITEM_TYPES.stream().sorted().collect(joining(", "));
String functionList = GroupFunction.VALID_FUNCTIONS.stream().sorted().collect(joining(", "));
String model = """
DateTime DateTime [%s]
Switch Switch "Switch" <Switch> [%s]
// Multiline item with keywords at the start of line
String
String
<
String
>
[
String
]
Number EQUALITY
""".formatted(itemTypeList, functionList);
modelRepository.addOrRefreshModel(TESTMODEL_NAME, new ByteArrayInputStream(model.getBytes()));
assertThat(itemRegistry.getAll(), hasSize(4));
Item dateTimeItem = itemRegistry.get("DateTime");
assertThat(dateTimeItem.getTags().stream().sorted().collect(joining(", ")), is(equalTo(itemTypeList)));
Item switchItem = itemRegistry.get("Switch");
assertThat(switchItem.getTags().stream().sorted().collect(joining(", ")), is(equalTo(functionList)));
assertThat(switchItem.getLabel(), is("Switch"));
assertThat(switchItem.getCategory(), is("Switch"));
Item multilineItem = itemRegistry.get("String");
assertThat(multilineItem.getTags().stream().sorted().collect(joining(", ")), is(equalTo("String")));
assertThat(multilineItem.getCategory(), is("String"));
assertThat(itemRegistry.get("EQUALITY"), is(notNullValue()));
}
}