}
private @NonNull Stream<DeclaredStatement<?>> substatementsAsDeclared() {
- // FIXME: YANGTOOLS-1383: this stream includes implicit case statements, but it should not
- return substatements.stream().map(AbstractResumedStatement::declared);
+ var stream = substatements.stream();
+ if (getImplicitDeclaredFlag()) {
+ stream = stream.map(stmt -> {
+ var ret = stmt;
+ while (ret.origin() == StatementOrigin.CONTEXT) {
+ final var stmts = ret.substatements;
+ verify(stmts.size() == 1, "Unexpected substatements %s", stmts);
+ ret = verifyNotNull(stmts.get(0));
+ }
+ return ret;
+ });
+ }
+
+ return stream.map(AbstractResumedStatement::declared);
}
@Override
private AbstractResumedStatement<?, ?, ?> createImplicitParent(final int offset,
final StatementSupport<?, ?, ?> implicitParent, final StatementSourceReference ref, final String argument) {
+ setImplicitDeclaredFlag();
return createSubstatement(offset, new StatementDefinitionContext<>(implicitParent),
ImplicitSubstatement.of(ref), argument);
}
*/
private byte executionOrder;
+ /**
+ * This field should live in AbstractResumedStatement, but is placed here for memory efficiency to squat in the
+ * alignment shadow of {@link #bitsAight} and {@link #executionOrder}.
+ */
+ private boolean implicitDeclaredFlag;
+
+ // TODO: we a single byte of alignment shadow left, we should think how we can use it to cache information we build
+ // during buildEffective()
+
// Copy constructor used by subclasses to implement reparent()
StatementContextBase(final StatementContextBase<A, D, E> original) {
super(original);
* @return True if {@link #allSubstatements()} and {@link #allSubstatementsStream()} would return an empty stream.
*/
abstract boolean hasEmptySubstatements();
+
+ // Note: these two are exposed for AbstractResumedStatement only
+ final boolean getImplicitDeclaredFlag() {
+ return implicitDeclaredFlag;
+ }
+
+ final void setImplicitDeclaredFlag() {
+ implicitDeclaredFlag = true;
+ }
}
--- /dev/null
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.stmt;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.CaseStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ContainerStatement;
+
+public class YT1383Test extends AbstractYangTest {
+ @Test
+ public void testDeclaredImplicitCase() {
+ final var foo = assertEffectiveModel("/bugs/YT1383/foo.yang").getModuleStatements().values().iterator()
+ .next().findFirstEffectiveSubstatement(ChoiceEffectiveStatement.class).orElseThrow();
+
+ // Effective view of things
+ final var effStatements = foo.effectiveSubstatements();
+ assertEquals(2, effStatements.size());
+ final var bar = effStatements.get(0);
+ assertThat(bar, instanceOf(CaseEffectiveStatement.class));
+ assertNotNull(bar.getDeclared());
+ final var baz = effStatements.get(1);
+ assertThat(baz, instanceOf(CaseEffectiveStatement.class));
+ assertNull(baz.getDeclared());
+
+ // Declared view of things
+ final var fooDecl = foo.getDeclared();
+ assertNotNull(fooDecl);
+ final var declStatements = fooDecl.declaredSubstatements();
+ assertEquals(2, declStatements.size());
+ final var barDecl = declStatements.get(0);
+ assertThat(barDecl, instanceOf(CaseStatement.class));
+ final var bazDecl = declStatements.get(1);
+ assertThat(bazDecl, instanceOf(ContainerStatement.class));
+ }
+}