import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import java.util.stream.Collectors;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.rfc8040.model.api.YangDataConstants;
import org.opendaylight.yangtools.rfc8040.model.api.YangDataEffectiveStatement;
import org.opendaylight.yangtools.rfc8040.model.api.YangDataStatement;
import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
import org.opendaylight.yangtools.yang.parser.spi.meta.InvalidSubstatementException;
import org.opendaylight.yangtools.yang.parser.spi.meta.MissingSubstatementException;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ParserNamespace;
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;
@Beta
public final class YangDataStatementSupport
extends AbstractStatementSupport<YangDataName, YangDataStatement, YangDataEffectiveStatement> {
+ private static final @NonNull ParserNamespace<YangDataName,
+ StmtContext<YangDataName, YangDataStatement, YangDataEffectiveStatement>> NAMESPACE =
+ new ParserNamespace<>("yang-data");
+ public static final @NonNull NamespaceBehaviour<YangDataName,
+ StmtContext<YangDataName, YangDataStatement, YangDataEffectiveStatement>> BEHAVIOUR =
+ NamespaceBehaviour.global(NAMESPACE);
+
// As per RFC8040 page 81:
//
// The substatements of this extension MUST follow the
}
@Override
- public void onStatementAdded(final Mutable<YangDataName, YangDataStatement, YangDataEffectiveStatement> ctx) {
+ public void onStatementAdded(final Mutable<YangDataName, YangDataStatement, YangDataEffectiveStatement> stmt) {
// as per https://www.rfc-editor.org/rfc/rfc8040#section-8,
// yang-data is ignored unless it appears as a top-level statement
- if (ctx.coerceParentContext().getParentContext() != null) {
- ctx.setUnsupported();
+ final var parent = stmt.coerceParentContext();
+ if (parent.getParentContext() != null) {
+ stmt.setUnsupported();
+ return;
+ }
+
+ final var name = stmt.argument();
+ final var prev = parent.namespaceItem(NAMESPACE, name);
+ if (prev != null) {
+ throw new SourceException(stmt,
+ "Error in module '%s': cannot add '%s'. Node name collision: '%s' already declared at %s",
+ stmt.getRoot().rawArgument(), name, prev.argument(), prev.sourceReference());
}
+ parent.addToNs(NAMESPACE, stmt.argument(), stmt);
}
@Override
--- /dev/null
+/*
+ * Copyright (c) 2022 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.rfc8040.parser;
+
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.junit.jupiter.api.Test;
+import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedException;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
+
+class YT1482Test extends AbstractYangDataTest {
+ @Test
+ void duplicateNamesAreRejected() throws Exception {
+ final var action = REACTOR.newBuild().addSources(IETF_RESTCONF_MODULE, sourceForResource("/yt1482.yang"));
+
+ final var ex = assertThrows(SomeModifiersUnresolvedException.class, action::buildEffective);
+ final var cause = assertInstanceOf(SourceException.class, ex.getCause());
+ assertThat(cause.getMessage(), startsWith("""
+ Error in module 'yt1482': cannot add 'YangDataName[module=QNameModule{ns=yt1482}, name=some]'. Node name \
+ collision: 'YangDataName[module=QNameModule{ns=yt1482}, name=some]' already declared at """));
+ }
+}