Disconnect InferenceException from SourceException 38/109638/2
authorRobert Varga <robert.varga@pantheon.tech>
Thu, 4 Jan 2024 19:45:47 +0000 (20:45 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Thu, 4 Jan 2024 20:05:18 +0000 (21:05 +0100)
These two exceptions indicate different conditions, split them up to
make sure the class hierarchy prevents confusing the two.

JIRA: YANGTOOLS-1150
Change-Id: I0313d42c009e30079ac8bf0619bc989d18c6b0a4
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
model/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/meta/StatementSourceException.java
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/BuildGlobalContext.java
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/path/PathExpressionParser.java
parser/yang-parser-rfc7950/src/test/java/org/opendaylight/yangtools/yang/stmt/AbstractYangTest.java
parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/InferenceException.java
parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/SourceException.java

index 324d16858ab0635b3c216a6aa0c43c4eeb1da121..f3912f23b090fd244e8530182b6bca9c357f6c0c 100644 (file)
@@ -42,6 +42,11 @@ public class StatementSourceException extends RuntimeException {
         this(sourceRef, format.formatted(args));
     }
 
+    public StatementSourceException(final StatementSourceReference sourceRef, final Throwable cause,
+            final String format, final Object... args) {
+        this(sourceRef, format.formatted(args), cause);
+    }
+
     private static String createMessage(final StatementSourceReference sourceRef, final String message) {
         return requireNonNull(message) + " [at " + requireNonNull(sourceRef) + ']';
     }
index 0bfae3377e53e2b6b8ad02a50206fccf26670de3..033cfd3727731652a7f0c0bd3f5e5b718ee520f0 100644 (file)
@@ -253,36 +253,36 @@ final class BuildGlobalContext extends AbstractNamespaceStorage implements Globa
     private SomeModifiersUnresolvedException addSourceExceptions(final List<SourceSpecificContext> sourcesToProgress) {
         boolean addedCause = false;
         SomeModifiersUnresolvedException buildFailure = null;
-        for (final SourceSpecificContext failedSource : sourcesToProgress) {
-            final Optional<SourceException> optSourceEx = failedSource.failModifiers(currentPhase);
+        for (var failedSource : sourcesToProgress) {
+            final var optSourceEx = failedSource.failModifiers(currentPhase);
             if (optSourceEx.isEmpty()) {
                 continue;
             }
 
-            final SourceException sourceEx = optSourceEx.orElseThrow();
+            final var sourceEx = optSourceEx.orElseThrow();
             // Workaround for broken logging implementations which ignore
             // suppressed exceptions
-            final Throwable cause = sourceEx.getCause() != null ? sourceEx.getCause() : sourceEx;
+            final var cause = sourceEx.getCause() != null ? sourceEx.getCause() : sourceEx;
             if (LOG.isDebugEnabled()) {
                 LOG.error("Failed to parse YANG from source {}", failedSource, sourceEx);
             } else {
                 LOG.error("Failed to parse YANG from source {}: {}", failedSource, cause.getMessage());
             }
 
-            final Throwable[] suppressed = sourceEx.getSuppressed();
+            final var suppressed = sourceEx.getSuppressed();
             if (suppressed.length > 0) {
                 LOG.error("{} additional errors reported:", suppressed.length);
 
                 int count = 1;
-                for (final Throwable t : suppressed) {
-                    LOG.error("Error {}: {}", count, t.getMessage());
+                for (var supp : suppressed) {
+                    LOG.error("Error {}: {}", count, supp.getMessage());
                     count++;
                 }
             }
 
             if (!addedCause) {
                 addedCause = true;
-                final SourceIdentifier sourceId = failedSource.identifySource();
+                final var sourceId = failedSource.identifySource();
                 buildFailure = new SomeModifiersUnresolvedException(currentPhase, sourceId, sourceEx);
             } else {
                 buildFailure.addSuppressed(sourceEx);
index 1e53ea4afd47f05b684057390283964fb96156cb..17944e12d5d6b262a6229cd8fbfbbd9d5569ab47 100644 (file)
@@ -31,6 +31,7 @@ import org.opendaylight.yangtools.yang.common.UnresolvedQName.Unqualified;
 import org.opendaylight.yangtools.yang.common.YangVersion;
 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.StatementSourceException;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementSourceReference;
 import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier;
 import org.opendaylight.yangtools.yang.parser.spi.ParserNamespaces;
@@ -411,12 +412,12 @@ final class SourceSpecificContext implements NamespaceStorage, Mutable {
                 + finishedPhase + "]";
     }
 
-    Optional<SourceException> failModifiers(final ModelProcessingPhase identifier) {
-        final List<SourceException> exceptions = new ArrayList<>();
-        for (final ModifierImpl mod : modifiers.get(identifier)) {
+    Optional<StatementSourceException> failModifiers(final ModelProcessingPhase identifier) {
+        final var exceptions = new ArrayList<StatementSourceException>();
+        for (var mod : modifiers.get(identifier)) {
             try {
                 mod.failModifier();
-            } catch (final SourceException e) {
+            } catch (StatementSourceException e) {
                 exceptions.add(e);
             }
         }
@@ -425,8 +426,8 @@ final class SourceSpecificContext implements NamespaceStorage, Mutable {
             case 0 -> Optional.empty();
             case 1 -> Optional.of(exceptions.get(0));
             default -> {
-                final String message = String.format("Yang model processing phase %s failed", identifier);
-                final InferenceException ex = new InferenceException(message, root, exceptions.get(0));
+                final var ex = new InferenceException("Yang model processing phase " + identifier + " failed", root,
+                    exceptions.get(0));
                 exceptions.listIterator(1).forEachRemaining(ex::addSuppressed);
                 yield Optional.of(ex);
             }
index 5d3745a84c91110631031ef7385c072362579164..833d523d840b2a06ee12823ec2fa1910dc4522ea 100644 (file)
@@ -24,6 +24,7 @@ import org.opendaylight.yangtools.yang.model.api.PathExpression;
 import org.opendaylight.yangtools.yang.model.api.PathExpression.DerefSteps;
 import org.opendaylight.yangtools.yang.model.api.PathExpression.LocationPathSteps;
 import org.opendaylight.yangtools.yang.model.api.PathExpression.Steps;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementSourceException;
 import org.opendaylight.yangtools.yang.parser.antlr.LeafRefPathLexer;
 import org.opendaylight.yangtools.yang.parser.antlr.LeafRefPathParser;
 import org.opendaylight.yangtools.yang.parser.antlr.LeafRefPathParser.Absolute_pathContext;
@@ -41,7 +42,6 @@ import org.opendaylight.yangtools.yang.parser.antlr.LeafRefPathParser.Relative_p
 import org.opendaylight.yangtools.yang.parser.rfc7950.antlr.SourceExceptionParser;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
-import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 import org.opendaylight.yangtools.yang.xpath.api.YangBinaryExpr;
 import org.opendaylight.yangtools.yang.xpath.api.YangBinaryOperator;
 import org.opendaylight.yangtools.yang.xpath.api.YangExpr;
@@ -66,7 +66,7 @@ class PathExpressionParser {
         PathExpression parseExpression(final StmtContext<?, ?, ?> ctx, final String pathArg) {
             try {
                 return super.parseExpression(ctx, pathArg);
-            } catch (IllegalStateException | SourceException e) {
+            } catch (IllegalStateException | StatementSourceException e) {
                 LOG.warn("Failed to parse expression '{}'", pathArg, e);
                 return new UnparsedPathExpression(pathArg, e);
             }
index 080f0b4db0a111675f0398e0e87e292dfc607b26..b637f29733a6b049df5689a5d9c81b7bef57ce6a 100644 (file)
@@ -21,6 +21,7 @@ import org.eclipse.jdt.annotation.Nullable;
 import org.hamcrest.Matcher;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementSourceException;
 import org.opendaylight.yangtools.yang.model.ri.type.InvalidBitDefinitionException;
 import org.opendaylight.yangtools.yang.model.ri.type.InvalidEnumDefinitionException;
 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
@@ -76,7 +77,7 @@ public abstract class AbstractYangTest {
         return assertInstanceOf(cause, actual);
     }
 
-    public static <E extends SourceException> @NonNull E assertException(final Class<E> cause,
+    public static <E extends StatementSourceException> @NonNull E assertException(final Class<E> cause,
             final Matcher<String> matcher, final String... yangResourceName) {
         final var ret = assertException(cause, yangResourceName);
         assertThat(ret.getMessage(), matcher);
@@ -90,7 +91,7 @@ public abstract class AbstractYangTest {
         return ret;
     }
 
-    public static <E extends SourceException> @NonNull E assertExceptionDir(final String yangResourceName,
+    public static <E extends StatementSourceException> @NonNull E assertExceptionDir(final String yangResourceName,
             final Class<E> cause) {
         final var ex = assertThrows(SomeModifiersUnresolvedException.class,
             () -> TestUtils.loadModules(yangResourceName));
@@ -98,7 +99,7 @@ public abstract class AbstractYangTest {
         return assertInstanceOf(cause, actual);
     }
 
-    public static <E extends SourceException> @NonNull E assertExceptionDir(final String yangResourceName,
+    public static <E extends StatementSourceException> @NonNull E assertExceptionDir(final String yangResourceName,
             final Class<E> cause, final Matcher<String> matcher) {
         final var ret = assertExceptionDir(yangResourceName, cause);
         assertThat(ret.getMessage(), matcher);
index 2ddbd52303a427469c6409955939a5bef7a20c86..f3ec8b407db23793a6a47c28c0882e6fc26bbbc5 100644 (file)
@@ -8,40 +8,43 @@
 package org.opendaylight.yangtools.yang.parser.spi.meta;
 
 import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementSourceException;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementSourceReference;
-import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 
 /**
- * Thrown when there is an inference error.
+ * A {@link StatementSourceException} indicating an inference problem, e.g. a problem with how statements interact with
+ * each other.
  */
-public class InferenceException extends SourceException {
-    private static final long serialVersionUID = 1L;
+public final class InferenceException extends StatementSourceException {
+    @java.io.Serial
+    private static final long serialVersionUID = 2L;
 
     public InferenceException(final @NonNull String message, final @NonNull StatementSourceReference source) {
-        super(message, source);
+        super(source, message);
     }
 
     public InferenceException(final @NonNull String message, final @NonNull StatementSourceReference source,
             final Throwable cause) {
-        super(message, source, cause);
+        super(source, message, cause);
     }
 
     public InferenceException(final @NonNull StatementSourceReference source, final @NonNull String format,
             final Object... args) {
-        this(String.format(format, args), source);
+        super(source, format, args);
     }
 
     public InferenceException(final @NonNull String message, final @NonNull CommonStmtCtx stmt) {
-        super(message, stmt);
+        super(stmt.sourceReference(), message);
     }
 
     public InferenceException(final @NonNull String message, final @NonNull CommonStmtCtx stmt, final Throwable cause) {
-        super(message, stmt, cause);
+        super(stmt.sourceReference(), message, cause);
     }
 
     public InferenceException(final @NonNull CommonStmtCtx stmt, final @NonNull String format,
             final Object... args) {
-        this(stmt.sourceReference(), format, args);
+        super(stmt.sourceReference(), format, args);
     }
 
     /**
@@ -77,4 +80,42 @@ public class InferenceException extends SourceException {
             throw new InferenceException(stmt.sourceReference(), format, args);
         }
     }
+
+    /**
+     * Throw an instance of this exception if an object is null. If the object is non-null, it will
+     * be returned as the result of this method.
+     *
+     * @param obj Object reference to be checked
+     * @param stmt Statement context, not retained
+     * @param format Format string, according to {@link String#format(String, Object...)}.
+     * @param args Format string arguments, according to {@link String#format(String, Object...)}
+     * @return Object if it is not null
+     * @throws InferenceException if object is null
+     */
+    public static <T> @NonNull T throwIfNull(final @Nullable T obj, final @NonNull CommonStmtCtx stmt,
+            final @NonNull String format, final Object... args) {
+        if (obj == null) {
+            throw new InferenceException(stmt.sourceReference(), format, args);
+        }
+        return obj;
+    }
+
+    /**
+     * Throw an instance of this exception if an object is null. If the object is non-null, it will
+     * be returned as the result of this method.
+     *
+     * @param obj Object reference to be checked
+     * @param source Statement source reference
+     * @param format Format string, according to {@link String#format(String, Object...)}.
+     * @param args Format string arguments, according to {@link String#format(String, Object...)}
+     * @return Object if it is not null
+     * @throws InferenceException if object is null
+     */
+    public static <T> @NonNull T throwIfNull(final @Nullable T obj, final @NonNull StatementSourceReference source,
+            final @NonNull String format, final Object... args) {
+        if (obj == null) {
+            throw new InferenceException(source, format, args);
+        }
+        return obj;
+    }
 }
index ec3ce2ab722031b6e9fb6283e5e75afaab0fca41..b9019b2e2bd9c44ec66347f382b6de183e09846e 100644 (file)
@@ -55,7 +55,7 @@ public class SourceException extends StatementSourceException {
      */
     public SourceException(final @NonNull StatementSourceReference source, final @NonNull String format,
             final Object... args) {
-        this(String.format(format, args), source);
+        super(source, format, args);
     }
 
     /**
@@ -69,7 +69,7 @@ public class SourceException extends StatementSourceException {
      */
     public SourceException(final @NonNull StatementSourceReference source, final Throwable cause,
             final @NonNull String format, final Object... args) {
-        this(String.format(format, args), source, cause);
+        super(source, cause, format, args);
     }
 
     /**
@@ -80,7 +80,7 @@ public class SourceException extends StatementSourceException {
      * @param stmt Statement context, not retained
      */
     public SourceException(final @NonNull String message, final @NonNull CommonStmtCtx stmt) {
-        this(message, stmt.sourceReference());
+        super(stmt.sourceReference(), message);
     }
 
     /**
@@ -92,7 +92,7 @@ public class SourceException extends StatementSourceException {
      * @param cause Underlying cause of this exception
      */
     public SourceException(final @NonNull String message, final @NonNull CommonStmtCtx stmt, final Throwable cause) {
-        this(message, stmt.sourceReference(), cause);
+        super(stmt.sourceReference(), message, cause);
     }
 
     /**
@@ -104,7 +104,7 @@ public class SourceException extends StatementSourceException {
      * @param args Format string arguments, according to {@link String#format(String, Object...)}
      */
     public SourceException(final @NonNull CommonStmtCtx stmt, final @NonNull String format, final Object... args) {
-        this(stmt.sourceReference(), format, args);
+        super(stmt.sourceReference(), format, args);
     }
 
     /**