Do not access GroupingNamespace during effective build 53/94053/4
authorRobert Varga <robert.varga@pantheon.tech>
Fri, 4 Dec 2020 17:02:36 +0000 (18:02 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Sat, 5 Dec 2020 13:27:21 +0000 (14:27 +0100)
There are two places which are accessing GroupingNamespace during
statement build:

AbstractGroupingStatementSupport.buildDeclared() performs a check
for namespace conflict. This is better done through an inference
action in FULL_DECLARATION of root model, when we can check whether
there is a conflict -- before we ever get to build statements.

UsesStatementSupport is searching namespaces to locate its source
to build its effective model -- to satisfy
UsesNode.getSourceGrouping(). This is better done by remembering
the source grouping's context in a statement-local namespace
and then pick it up when needed.

The two changes together allow us to sweep GroupingNamespace at
the end of RootStatementContext's build.

JIRA: YANGTOOLS-1197
Change-Id: I3a75ad92aeffeeed279466fffcf4402b17ee1d09
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/RootStatementContext.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/reactor/RFC7950Reactors.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/grouping/AbstractGroupingStatementSupport.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/uses/SourceGroupingNamespace.java [new file with mode: 0644]
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/uses/UsesStatementSupport.java

index f3077ba89ead7339ca33cd2fe7427178805dc907..a6e9743f8b2156cabf4804a70ef4053800cb1477 100644 (file)
@@ -30,6 +30,7 @@ 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.IdentifierNamespace;
 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.parser.spi.GroupingNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.SchemaTreeNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
 import org.opendaylight.yangtools.yang.parser.spi.meta.MutableStatement;
@@ -53,8 +54,7 @@ public final class RootStatementContext<A, D extends DeclaredStatement<A>, E ext
     private static final Logger LOG = LoggerFactory.getLogger(RootStatementContext.class);
     // These namespaces are well-known and not needed after the root is cleaned up
     private static final Map<Class<?>, SweptNamespace> SWEPT_NAMESPACES = ImmutableMap.of(
-        // FIXME: YANGTOOLS-1197: sweep GroupingNamespace
-        // GroupingNamespace.class, new SweptNamespace(GroupingNamespace.class),
+        GroupingNamespace.class, new SweptNamespace(GroupingNamespace.class),
         // FIXME: YANGTOOLS-1198: sweep TypeNamespace
         // TypeNamespace.class, new SweptNamespace(TypeNamespace.class),
         SchemaTreeNamespace.class, new SweptNamespace(SchemaTreeNamespace.class));
index 8d8b9e970e6fc562ef00ca24304f176be9a9bcf0..049e9e1017729164b3b13c8e525b21799e9891f2 100644 (file)
@@ -108,6 +108,7 @@ import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.type.TypeStatementRFC
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.typedef.TypedefStatementSupport;
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.unique.UniqueStatementSupport;
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.units.UnitsStatementSupport;
+import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.uses.SourceGroupingNamespace;
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.uses.UsesStatementSupport;
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.value.ValueStatementSupport;
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.when.WhenStatementSupport;
@@ -375,8 +376,9 @@ public final class RFC7950Reactors {
             .addSupport(FeatureNamespace.BEHAVIOUR)
             .addVersionSpecificSupport(VERSION_1, IfFeatureStatementRFC6020Support.getInstance())
             .addVersionSpecificSupport(VERSION_1_1, IfFeatureStatementRFC7950Support.getInstance())
-            .addSupport(UsesStatementSupport.getInstance())
             .addSupport(GroupingNamespace.BEHAVIOUR)
+            .addSupport(SourceGroupingNamespace.BEHAVIOUR)
+            .addSupport(UsesStatementSupport.getInstance())
             .addSupport(ErrorMessageStatementSupport.getInstance())
             .addSupport(ErrorAppTagStatementSupport.getInstance())
             .addVersionSpecificSupport(VERSION_1, LeafListStatementRFC6020Support.getInstance())
index ecca4c8ba7f3de64d43ae9e172ac56d8e6d2eb11..2ec6492fe20912f001ec4d61b09879c34b9b2744 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.grouping;
 
 import com.google.common.collect.ImmutableList;
+import java.util.Collection;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
@@ -18,6 +19,11 @@ import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.BaseQNameStatementSup
 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.SubstatementIndexingException;
 import org.opendaylight.yangtools.yang.parser.spi.GroupingNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceAction;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.InferenceContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder.Prerequisite;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
@@ -39,13 +45,31 @@ abstract class AbstractGroupingStatementSupport
             final Mutable<QName, GroupingStatement, GroupingEffectiveStatement> stmt) {
         super.onFullDefinitionDeclared(stmt);
 
-        if (stmt != null) {
-            final Mutable<?, ?, ?> parent = stmt.getParentContext();
-            if (parent != null) {
-                // Shadowing check: make sure we do not trample on pre-existing definitions. This catches sibling
-                // declarations and parent declarations which have already been declared.
-                checkConflict(parent, stmt);
-                parent.addContext(GroupingNamespace.class, stmt.getArgument(), stmt);
+        final Mutable<?, ?, ?> parent = stmt.getParentContext();
+        if (parent != null) {
+            // Shadowing check: make sure we do not trample on pre-existing definitions. This catches sibling
+            // declarations and parent declarations which have already been declared.
+            checkConflict(parent, stmt);
+            parent.addContext(GroupingNamespace.class, stmt.getArgument(), stmt);
+
+            final StmtContext<?, ?, ?> grandParent = parent.getParentContext();
+            if (grandParent != null) {
+                // Shadowing check: make sure grandparent does not see a conflicting definition. This is required to
+                // ensure that a grouping in child scope does not shadow a grouping in parent scope which occurs later
+                // in the text. For that check we need the full declaration of our model.
+                final ModelActionBuilder action = stmt.newInferenceAction(ModelProcessingPhase.FULL_DECLARATION);
+                action.requiresCtx(grandParent.getRoot(), ModelProcessingPhase.FULL_DECLARATION);
+                action.apply(new InferenceAction() {
+                    @Override
+                    public void apply(final InferenceContext ctx) {
+                        checkConflict(grandParent, stmt);
+                    }
+
+                    @Override
+                    public void prerequisiteFailed(final Collection<? extends Prerequisite<?>> failed) {
+                        // No-op
+                    }
+                });
             }
         }
     }
@@ -53,13 +77,11 @@ abstract class AbstractGroupingStatementSupport
     @Override
     protected final GroupingStatement createDeclared(final StmtContext<QName, GroupingStatement, ?> ctx,
             final ImmutableList<? extends DeclaredStatement<?>> substatements) {
-        checkDeclaredConflict(ctx);
         return new RegularGroupingStatement(ctx.getArgument(), substatements);
     }
 
     @Override
     protected final GroupingStatement createEmptyDeclared(final StmtContext<QName, GroupingStatement, ?> ctx) {
-        checkDeclaredConflict(ctx);
         return new EmptyGroupingStatement(ctx.getArgument());
     }
 
@@ -74,18 +96,6 @@ abstract class AbstractGroupingStatementSupport
         }
     }
 
-    private static void checkDeclaredConflict(final StmtContext<QName, ?, ?> ctx) {
-        // Shadowing check: make sure grandparent does not see a conflicting definition. This is required to ensure
-        // that a grouping in child scope does not shadow a grouping in parent scope which occurs later in the text.
-        final StmtContext<?, ?, ?> parent = ctx.getParentContext();
-        if (parent != null) {
-            final StmtContext<?, ?, ?> grandParent = parent.getParentContext();
-            if (grandParent != null) {
-                checkConflict(grandParent, ctx);
-            }
-        }
-    }
-
     private static void checkConflict(final StmtContext<?, ?, ?> parent, final StmtContext<QName, ?, ?> stmt) {
         final QName arg = stmt.getArgument();
         final StmtContext<?, ?, ?> existing = parent.getFromNamespace(GroupingNamespace.class, arg);
diff --git a/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/uses/SourceGroupingNamespace.java b/yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/uses/SourceGroupingNamespace.java
new file mode 100644 (file)
index 0000000..007f904
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2020 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.parser.rfc7950.stmt.uses;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.Empty;
+import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+
+@Beta
+public interface SourceGroupingNamespace extends IdentifierNamespace<Empty, StmtContext<?, ?, ?>> {
+    NamespaceBehaviour<Empty, StmtContext<?, ?, ?>, @NonNull SourceGroupingNamespace> BEHAVIOUR =
+        NamespaceBehaviour.statementLocal(SourceGroupingNamespace.class);
+}
index 1ec33dd506740019d5d2da54405333674644975d..9213cb2b7ff420a677218ac14afa388134078db8 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.uses;
 
+import static com.google.common.base.Verify.verifyNotNull;
+
 import com.google.common.base.Verify;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -17,6 +19,7 @@ import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Optional;
 import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.Empty;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.YangVersion;
@@ -113,6 +116,7 @@ public final class UsesStatementSupport
                 copyFromSourceToTarget(sourceGrpStmtCtx, targetNodeStmtCtx, usesNode);
                 resolveUsesNode(usesNode, targetNodeStmtCtx);
                 StmtContextUtils.validateIfFeatureAndWhenOnListKeys(usesNode);
+                usesNode.addToNs(SourceGroupingNamespace.class, Empty.getInstance(), sourceGrpStmtCtx);
             }
 
             @Override
@@ -143,7 +147,8 @@ public final class UsesStatementSupport
     @Override
     protected UsesEffectiveStatement createEffective(final Current<QName, UsesStatement> stmt,
             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
-        final GroupingDefinition sourceGrouping = getSourceGrouping(stmt);
+        final GroupingDefinition sourceGrouping = (GroupingDefinition)
+            verifyNotNull(stmt.getFromNamespace(SourceGroupingNamespace.class, Empty.getInstance())).buildEffective();
         final int flags = historyAndStatusFlags(stmt.history(), substatements);
         final QName argument = stmt.getArgument();
         final UsesStatement declared = stmt.declared();
@@ -177,12 +182,6 @@ public final class UsesStatementSupport
         return ImmutableMap.copyOf(refines);
     }
 
-    private static GroupingDefinition getSourceGrouping(final Current<QName, ?> stmt) {
-        // FIXME: YANGTOOLS-1197: we have this lookup in inference action, just store a replica in local namespace
-        //                        during apply and pick it up when we build the statement
-        return (GroupingDefinition) stmt.getFromNamespace(GroupingNamespace.class, stmt.getArgument()).buildEffective();
-    }
-
     /**
      * Copy statements from a grouping to a target node.
      *