package org.opendaylight.yangtools.yang.parser.stmt.reactor;
import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Verify.verify;
+import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
final ModelProcessingPhase phase = getCompletedPhase();
checkState(phase == ModelProcessingPhase.FULL_DECLARATION || phase == ModelProcessingPhase.EFFECTIVE_MODEL,
"Cannot build declared instance after phase %s", phase);
- return declaredInstance = definition().getFactory().createDeclared(this);
+ return declaredInstance = definition().getFactory().createDeclared(this, substatementsAsDeclared());
+ }
+
+ private @NonNull Stream<DeclaredStatement<?>> substatementsAsDeclared() {
+ // FIXME: YANGTOOLS-1383: this stream includes implicit case statements, but it should not
+ return substatements.stream().map(AbstractResumedStatement::declared);
}
@Override
final var implicitParent = definition().getImplicitParentFor(this, def.getPublicView());
if (implicitParent.isPresent()) {
return createImplicitParent(offset, implicitParent.orElseThrow(), ref, argument)
- .createSubstatement(offset, def, ref, argument);
+ .createSubstatement(0, def, ref, argument);
}
final AbstractResumedStatement<X, Y, Z> ret = new SubstatementContext<>(this, def, ref, argument);
}
@Override
- final Iterable<ReactorStmtCtx<?, ?, ?>> effectiveChildrenToComplete() {
- return effective;
+ final Iterator<ReactorStmtCtx<?, ?, ?>> effectiveChildrenToComplete() {
+ return effective.iterator();
}
@Override
}
/**
- * Lookup substatement by its offset in this statement.
+ * Attempt to lookup a declared substatement by its offset in this statement, passing through any implicit
+ * statements which have been created to encapsulate it.
*
* @param offset Substatement offset
* @return Substatement, or null if substatement does not exist.
*/
- final AbstractResumedStatement<?, ?, ?> lookupSubstatement(final int offset) {
- return substatements.get(offset);
+ final @Nullable AbstractResumedStatement<?, ?, ?> enterSubstatement(final int offset) {
+ var ret = substatements.get(offset);
+ if (ret != null) {
+ while (ret.origin() == StatementOrigin.CONTEXT) {
+ ret = verifyNotNull(ret.substatements.get(0));
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * End the specified phase for this statement and return this statement's declared parent statement.
+ *
+ * @param phase processing phase that ended
+ * @return Declared parent statement
+ */
+ final @Nullable AbstractResumedStatement<?, ?, ?> exitStatement(final ModelProcessingPhase phase) {
+ finishDeclaration(phase);
+ final var parent = getParentContext();
+ if (parent == null) {
+ return null;
+ }
+
+ var ret = verifyParent(parent);
+ // Unwind all undeclared statements
+ while (ret.origin() == StatementOrigin.CONTEXT) {
+ ret.finishDeclaration(phase);
+ ret = verifyParent(ret.getParentContext());
+ }
+ return ret;
+ }
+
+ // FIXME: AbstractResumedStatement should only ever have AbstractResumedStatement parents, which would remove the
+ // need for this method. In ordered to do that we need to untangle SubstatementContext's users and do not
+ // allow it being reparent()ed.
+ private static AbstractResumedStatement<?, ?, ?> verifyParent(final StatementContextBase<?, ?, ?> parent) {
+ verify(parent instanceof AbstractResumedStatement, "Unexpected parent context %s", parent);
+ return (AbstractResumedStatement<?, ?, ?>) parent;
}
final void resizeSubstatements(final int expectedSize) {
substatements = substatements.ensureCapacity(expectedSize);
}
- final void walkChildren(final ModelProcessingPhase phase) {
+ final void declarationFinished(final ModelProcessingPhase phase) {
+ finishChildrenDeclaration(phase);
+ finishDeclaration(phase);
+ }
+
+ private void finishChildrenDeclaration(final ModelProcessingPhase phase) {
checkState(isFullyDefined());
- substatements.forEach(stmt -> {
- stmt.walkChildren(phase);
- stmt.endDeclared(phase);
- });
+ substatements.forEach(stmt -> stmt.declarationFinished(phase));
+ }
+
+ /**
+ * Ends declared section of current node for the specified phase.
+ *
+ * @param phase processing phase that ended
+ */
+ private void finishDeclaration(final ModelProcessingPhase phase) {
+ definition().onDeclarationFinished(this, phase);
}
private AbstractResumedStatement<?, ?, ?> createImplicitParent(final int offset,
final StatementSupport<?, ?, ?> implicitParent, final StatementSourceReference ref, final String argument) {
- final StatementDefinitionContext<?, ?, ?> def = new StatementDefinitionContext<>(implicitParent);
- return createSubstatement(offset, def, ImplicitSubstatement.of(ref), argument);
+ return createSubstatement(offset, new StatementDefinitionContext<>(implicitParent),
+ ImplicitSubstatement.of(ref), argument);
}
}