YangSyntaxErrorException should identify its source 47/64747/5
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 25 Oct 2017 21:06:46 +0000 (23:06 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Fri, 27 Oct 2017 14:26:34 +0000 (16:26 +0200)
Having just the module name is not sufficient in reactor settings where
there may be diverse sources involved.

Update YangSyntaxErrorException to contain SourceIdentifier when available.

Change-Id: Ied076ecd60fcef000ef498f632d2288fa2f6d954
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-parser-api/src/main/java/org/opendaylight/yangtools/yang/model/parser/api/YangSyntaxErrorException.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/util/YangModelDependencyInfo.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/rfc6020/repo/YangErrorListener.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/rfc6020/repo/YangStatementStreamSource.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ASTSchemaSource.java

index 95b59ccaa7dcb32d641421442b23700465589978..c2da1bdbd7b79e418c4ebe91f9e24627894ef8b1 100644 (file)
@@ -7,44 +7,49 @@
  */
 package org.opendaylight.yangtools.yang.model.parser.api;
 
-import com.google.common.base.Preconditions;
+import static java.util.Objects.requireNonNull;
+
+import java.util.Optional;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 
 public class YangSyntaxErrorException extends Exception {
-    private static final long serialVersionUID = 1L;
-    private final String module;
+    private static final long serialVersionUID = 2L;
+
+    private final SourceIdentifier source;
     private final int line;
     private final int charPositionInLine;
 
-    public YangSyntaxErrorException(final String module, final int line, final int charPositionInLine,
-            final String message) {
-        this(module, line, charPositionInLine, message, null);
+    public YangSyntaxErrorException(@Nullable final SourceIdentifier source, final int line,
+            final int charPositionInLine, final String message) {
+        this(source, line, charPositionInLine, message, null);
     }
 
-    public YangSyntaxErrorException(final String module, final int line, final int charPositionInLine,
-            final String message, final Throwable cause) {
-        super(Preconditions.checkNotNull(message), cause);
-        this.module = module;
+    public YangSyntaxErrorException(@Nullable final SourceIdentifier source, final int line,
+            final int charPositionInLine, final String message, @Nullable final Throwable cause) {
+        super(requireNonNull(message), cause);
+        this.source = source;
         this.line = line;
         this.charPositionInLine = charPositionInLine;
     }
 
-    public String getModule() {
-        return module;
+    public final Optional<SourceIdentifier> getSource() {
+        return Optional.ofNullable(source);
     }
 
-    public int getLine() {
+    public final int getLine() {
         return line;
     }
 
-    public int getCharPositionInLine() {
+    public final int getCharPositionInLine() {
         return charPositionInLine;
     }
 
     public String getFormattedMessage() {
         final StringBuilder sb = new StringBuilder(getMessage());
-        if (module != null) {
-            sb.append(" in module ");
-            sb.append(module);
+        if (source != null) {
+            sb.append(" in source ");
+            sb.append(source);
         }
         if (line != 0) {
             sb.append(" on line ");
index f1415726138701a51cce3304dbe9dc852dd92246..b97edabb1a9344f93e67afd06d452297692380bb 100644 (file)
@@ -26,6 +26,7 @@ import org.opendaylight.yangtools.yang.common.Revision;
 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
 import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
 import org.opendaylight.yangtools.yang.parser.rfc6020.repo.YangStatementStreamSource;
 import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource;
@@ -160,28 +161,30 @@ public abstract class YangModelDependencyInfo {
     /**
      * Extracts {@link YangModelDependencyInfo} from an abstract syntax tree of a YANG model.
      *
+     * @param source Source identifier
      * @param tree Abstract syntax tree
      * @return {@link YangModelDependencyInfo}
      * @throws YangSyntaxErrorException If the AST is not a valid YANG module/submodule
      */
-    public static YangModelDependencyInfo fromAST(final String name,
-            final ParserRuleContext tree) throws YangSyntaxErrorException {
+    public static YangModelDependencyInfo fromAST(final SourceIdentifier source, final ParserRuleContext tree)
+            throws YangSyntaxErrorException {
 
         if (tree instanceof StatementContext) {
             final StatementContext rootStatement = (StatementContext) tree;
-            return parseAST(rootStatement, name);
+            return parseAST(rootStatement, source);
         }
 
-        throw new YangSyntaxErrorException(name, 0, 0, "Unknown YANG text type");
+        throw new YangSyntaxErrorException(source, 0, 0, "Unknown YANG text type");
     }
 
-    private static YangModelDependencyInfo parseAST(final StatementContext rootStatement, final String sourceName) {
+    private static YangModelDependencyInfo parseAST(final StatementContext rootStatement,
+            final SourceIdentifier source) {
         final String keyWordText = rootStatement.keyword().getText();
         if (MODULE.equals(keyWordText)) {
-            return parseModuleContext(rootStatement, sourceName);
+            return parseModuleContext(rootStatement, source);
         }
         if (SUBMODULE.equals(keyWordText)) {
-            return parseSubmoduleContext(rootStatement, sourceName);
+            return parseSubmoduleContext(rootStatement, source);
         }
         throw new IllegalArgumentException("Root of parsed AST must be either module or submodule");
     }
@@ -204,41 +207,43 @@ public abstract class YangModelDependencyInfo {
             YangTextSchemaSource.forResource(refClass, resourceName));
         final ParserRuleContext ast = source.getYangAST();
         checkArgument(ast instanceof StatementContext);
-        return parseAST((StatementContext) ast, source.getIdentifier().toYangFilename());
+        return parseAST((StatementContext) ast, source.getIdentifier());
     }
 
-    private static YangModelDependencyInfo parseModuleContext(final StatementContext module, final String sourceName) {
-        final String name = Utils.stringFromStringContext(module.argument(), getReference(sourceName, module));
-        final String latestRevision = getLatestRevision(module, sourceName);
-        final Optional<SemVer> semVer = Optional.ofNullable(findSemanticVersion(module, sourceName));
-        final ImmutableSet<ModuleImport> imports = parseImports(module, sourceName);
-        final ImmutableSet<ModuleImport> includes = parseIncludes(module, sourceName);
+    private static YangModelDependencyInfo parseModuleContext(final StatementContext module,
+            final SourceIdentifier source) {
+        final String name = Utils.stringFromStringContext(module.argument(), getReference(source, module));
+        final String latestRevision = getLatestRevision(module, source);
+        final Optional<SemVer> semVer = Optional.ofNullable(findSemanticVersion(module, source));
+        final ImmutableSet<ModuleImport> imports = parseImports(module, source);
+        final ImmutableSet<ModuleImport> includes = parseIncludes(module, source);
 
         return new ModuleDependencyInfo(name, latestRevision, imports, includes, semVer);
     }
 
-    private static ImmutableSet<ModuleImport> parseImports(final StatementContext module, final String sourceName) {
+    private static ImmutableSet<ModuleImport> parseImports(final StatementContext module,
+            final SourceIdentifier source) {
         final Set<ModuleImport> result = new HashSet<>();
         for (final StatementContext subStatementContext : module.statement()) {
             if (IMPORT.equals(subStatementContext.keyword().getText())) {
-                final String revisionDateStr = getRevisionDateString(subStatementContext, sourceName);
+                final String revisionDateStr = getRevisionDateString(subStatementContext, source);
                 final String importedModuleName = Utils.stringFromStringContext(subStatementContext.argument(),
-                        getReference(sourceName, subStatementContext));
+                        getReference(source, subStatementContext));
                 final Revision revisionDate = Revision.ofNullable(revisionDateStr).orElse(null);
-                final SemVer importSemVer = findSemanticVersion(subStatementContext, sourceName);
+                final SemVer importSemVer = findSemanticVersion(subStatementContext, source);
                 result.add(new ModuleImportImpl(importedModuleName, revisionDate, importSemVer));
             }
         }
         return ImmutableSet.copyOf(result);
     }
 
-    private static SemVer findSemanticVersion(final StatementContext statement, final String sourceName) {
+    private static SemVer findSemanticVersion(final StatementContext statement, final SourceIdentifier source) {
         String semVerString = null;
         for (final StatementContext subStatement : statement.statement()) {
             final String subStatementName = Utils.trimPrefix(subStatement.keyword().getText());
             if (OPENCONFIG_VERSION.equals(subStatementName)) {
                 semVerString = Utils.stringFromStringContext(subStatement.argument(),
-                        getReference(sourceName, subStatement));
+                        getReference(source, subStatement));
                 break;
             }
         }
@@ -246,13 +251,14 @@ public abstract class YangModelDependencyInfo {
         return Strings.isNullOrEmpty(semVerString) ? null : SemVer.valueOf(semVerString);
     }
 
-    private static ImmutableSet<ModuleImport> parseIncludes(final StatementContext module, final String sourceName) {
+    private static ImmutableSet<ModuleImport> parseIncludes(final StatementContext module,
+            final SourceIdentifier source) {
         final Set<ModuleImport> result = new HashSet<>();
         for (final StatementContext subStatementContext : module.statement()) {
             if (INCLUDE.equals(subStatementContext.keyword().getText())) {
-                final String revisionDateStr = getRevisionDateString(subStatementContext, sourceName);
+                final String revisionDateStr = getRevisionDateString(subStatementContext, source);
                 final String IncludeModuleName = Utils.stringFromStringContext(subStatementContext.argument(),
-                        getReference(sourceName, subStatementContext));
+                        getReference(source, subStatementContext));
                 final Revision revisionDate = Revision.ofNullable(revisionDateStr).orElse(null);
                 result.add(new ModuleImportImpl(IncludeModuleName, revisionDate));
             }
@@ -260,23 +266,23 @@ public abstract class YangModelDependencyInfo {
         return ImmutableSet.copyOf(result);
     }
 
-    private static String getRevisionDateString(final StatementContext importStatement, final String sourceName) {
+    private static String getRevisionDateString(final StatementContext importStatement, final SourceIdentifier source) {
         String revisionDateStr = null;
         for (final StatementContext importSubStatement : importStatement.statement()) {
             if (REVISION_DATE.equals(importSubStatement.keyword().getText())) {
                 revisionDateStr = Utils.stringFromStringContext(importSubStatement.argument(),
-                        getReference(sourceName, importSubStatement));
+                        getReference(source, importSubStatement));
             }
         }
         return revisionDateStr;
     }
 
-    public static String getLatestRevision(final StatementContext module, final String sourceName) {
+    public static String getLatestRevision(final StatementContext module, final SourceIdentifier source) {
         String latestRevision = null;
         for (final StatementContext subStatementContext : module.statement()) {
             if (REVISION.equals(subStatementContext.keyword().getText())) {
                 final String currentRevision = Utils.stringFromStringContext(subStatementContext.argument(),
-                        getReference(sourceName, subStatementContext));
+                        getReference(source, subStatementContext));
                 if (latestRevision == null || latestRevision.compareTo(currentRevision) == -1) {
                     latestRevision = currentRevision;
                 }
@@ -286,30 +292,30 @@ public abstract class YangModelDependencyInfo {
     }
 
     private static YangModelDependencyInfo parseSubmoduleContext(final StatementContext submodule,
-            final String sourceName) {
-        final String name = Utils.stringFromStringContext(submodule.argument(), getReference(sourceName, submodule));
-        final String belongsTo = parseBelongsTo(submodule, sourceName);
+            final SourceIdentifier source) {
+        final String name = Utils.stringFromStringContext(submodule.argument(), getReference(source, submodule));
+        final String belongsTo = parseBelongsTo(submodule, source);
 
-        final String latestRevision = getLatestRevision(submodule, sourceName);
-        final ImmutableSet<ModuleImport> imports = parseImports(submodule, sourceName);
-        final ImmutableSet<ModuleImport> includes = parseIncludes(submodule, sourceName);
+        final String latestRevision = getLatestRevision(submodule, source);
+        final ImmutableSet<ModuleImport> imports = parseImports(submodule, source);
+        final ImmutableSet<ModuleImport> includes = parseIncludes(submodule, source);
 
         return new SubmoduleDependencyInfo(name, latestRevision, belongsTo, imports, includes);
     }
 
-    private static String parseBelongsTo(final StatementContext submodule, final String sourceName) {
+    private static String parseBelongsTo(final StatementContext submodule, final SourceIdentifier source) {
         for (final StatementContext subStatementContext : submodule.statement()) {
             if (BELONGS_TO.equals(subStatementContext.keyword().getText())) {
                 return Utils.stringFromStringContext(subStatementContext.argument(),
-                    getReference(sourceName, subStatementContext));
+                    getReference(source, subStatementContext));
             }
         }
         return null;
     }
 
-    private static StatementSourceReference getReference(final String sourceName,
+    private static StatementSourceReference getReference(final SourceIdentifier source,
             final StatementContext context) {
-        return DeclarationInTextSource.atPosition(sourceName, context.getStart().getLine(),
+        return DeclarationInTextSource.atPosition(source.getName(), context.getStart().getLine(),
             context.getStart().getCharPositionInLine());
     }
 
index bedf967996cf8fc9f40864e57ad91500c4d8716b..312a395aa4f5a9dee0bf7a39c1e01f72aa950b45 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.yangtools.yang.parser.rfc6020.repo;
 
+import static java.util.Objects.requireNonNull;
+
 import java.util.ArrayList;
 import java.util.List;
 import org.antlr.v4.runtime.BaseErrorListener;
@@ -14,21 +16,26 @@ import org.antlr.v4.runtime.Parser;
 import org.antlr.v4.runtime.RecognitionException;
 import org.antlr.v4.runtime.Recognizer;
 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public final class YangErrorListener extends BaseErrorListener {
     private static final Logger LOG = LoggerFactory.getLogger(YangErrorListener.class);
+
     private final List<YangSyntaxErrorException> exceptions = new ArrayList<>();
+    private final SourceIdentifier source;
+
+    public YangErrorListener(final SourceIdentifier source) {
+        this.source = requireNonNull(source);
+    }
 
     @Override
     @SuppressWarnings("checkstyle:parameterName")
     public void syntaxError(final Recognizer<?, ?> recognizer, final Object offendingSymbol, final int line,
             final int charPositionInLine, final String msg, final RecognitionException e) {
-        LOG.debug("Syntax error at {}:{}: {}", line, charPositionInLine, msg, e);
-
-        final String module = getModuleName(recognizer);
-        exceptions.add(new YangSyntaxErrorException(module, line, charPositionInLine, msg, e));
+        LOG.debug("Syntax error in {} at {}:{}: {}", source, line, charPositionInLine, msg, e);
+        exceptions.add(new YangSyntaxErrorException(source, line, charPositionInLine, msg, e));
     }
 
     @SuppressWarnings("checkstyle:illegalCatch")
@@ -62,11 +69,11 @@ public final class YangErrorListener extends BaseErrorListener {
         }
 
         final StringBuilder sb = new StringBuilder();
-        String module = null;
+        SourceIdentifier source = null;
         boolean first = true;
         for (YangSyntaxErrorException e : exceptions) {
-            if (module == null) {
-                module = e.getModule();
+            if (source == null) {
+                source = e.getSource().orElse(null);
             }
             if (first) {
                 first = false;
@@ -77,6 +84,6 @@ public final class YangErrorListener extends BaseErrorListener {
             sb.append(e.getFormattedMessage());
         }
 
-        throw new YangSyntaxErrorException(module, 0, 0, sb.toString());
+        throw new YangSyntaxErrorException(source, 0, 0, sb.toString());
     }
 }
index 15a7aa9440285cd8e960441e812a9189a20ac16e..2cd24879b7099a589543acb27d7bea6276c6553c 100644 (file)
@@ -78,7 +78,7 @@ public final class YangStatementStreamSource implements StatementStreamSource {
             YangSyntaxErrorException {
         final StatementContext context;
         try (InputStream stream = source.openStream()) {
-            context = parseYangSource(stream);
+            context = parseYangSource(source.getIdentifier(), stream);
         }
 
         final String sourceName = source.getSymbolicName().orElse(null);
@@ -145,15 +145,15 @@ public final class YangStatementStreamSource implements StatementStreamSource {
         return context;
     }
 
-    private static StatementContext parseYangSource(final InputStream stream) throws IOException,
-            YangSyntaxErrorException {
+    private static StatementContext parseYangSource(final SourceIdentifier source, final InputStream stream)
+            throws IOException, YangSyntaxErrorException {
         final YangStatementLexer lexer = new YangStatementLexer(CharStreams.fromStream(stream));
         final CommonTokenStream tokens = new CommonTokenStream(lexer);
         final YangStatementParser parser = new YangStatementParser(tokens);
         //disconnect from console error output
         parser.removeErrorListeners();
 
-        final YangErrorListener errorListener = new YangErrorListener();
+        final YangErrorListener errorListener = new YangErrorListener(source);
         parser.addErrorListener(errorListener);
 
         final StatementContext result = parser.statement();
index 3bfc6552461c2c30fb8acda8cef1116ea1c3f313..f772a495c0f47b4a431e3f85ea610f765dc1bc8b 100644 (file)
@@ -48,45 +48,6 @@ public final class ASTSchemaSource implements SchemaSourceRepresentation {
         this.symbolicName = symbolicName;
     }
 
-    /**
-     * Create a new instance of AST representation for a abstract syntax tree,
-     * performing minimal semantic analysis to acquire dependency information.
-     *
-     * @param name YANG source name. Used only for error reporting.
-     * @param tree ANTLR abstract syntax tree
-     * @return A new representation instance.
-     * @throws YangSyntaxErrorException if we fail to extract dependency information.
-     */
-    public static ASTSchemaSource create(@Nonnull final String name, @Nonnull final ParserRuleContext tree)
-            throws YangSyntaxErrorException {
-        final YangModelDependencyInfo depInfo = YangModelDependencyInfo.fromAST(name, tree);
-        final SourceIdentifier id = getSourceId(depInfo);
-        final SemVerSourceIdentifier semVerId = getSemVerSourceId(depInfo);
-        return new ASTSchemaSource(id, semVerId, tree, depInfo, null);
-    }
-
-    /**
-     * Create a new instance of AST representation for a abstract syntax tree,
-     * performing minimal semantic analysis to acquire dependency information.
-     *
-     * @param identifier
-     *            SourceIdentifier of yang schema source.
-     * @param tree
-     *            ANTLR abstract syntax tree
-     * @param text
-     *            YANG text source
-     * @return A new representation instance.
-     * @throws YangSyntaxErrorException
-     *             if we fail to extract dependency information.
-     *
-     * @deprecated Use {@link #create(SourceIdentifier, ParserRuleContext)} instead.
-     */
-    @Deprecated
-    public static ASTSchemaSource create(@Nonnull final SourceIdentifier identifier,
-            @Nonnull final ParserRuleContext tree, final String text) throws YangSyntaxErrorException {
-        return create(identifier, tree);
-    }
-
     /**
      * Create a new instance of AST representation for a abstract syntax tree, performing minimal semantic analysis
      * to acquire dependency information.
@@ -126,7 +87,7 @@ public final class ASTSchemaSource implements SchemaSourceRepresentation {
     private static ASTSchemaSource create(@Nonnull final SourceIdentifier identifier,
             @Nullable final String symbolicName, @Nonnull final ParserRuleContext tree)
                     throws YangSyntaxErrorException {
-        final YangModelDependencyInfo depInfo = YangModelDependencyInfo.fromAST(identifier.getName(), tree);
+        final YangModelDependencyInfo depInfo = YangModelDependencyInfo.fromAST(identifier, tree);
         final SourceIdentifier id = getSourceId(depInfo);
 
         final SemVerSourceIdentifier semVerId;