From a3d4ba53a36d65b00f8831343deae3f7591251e2 Mon Sep 17 00:00:00 2001
From: Terence Parr
Date: Mon, 19 May 2014 17:25:01 -0700
Subject: [PATCH] add tool-template and generatedcode-runtime version
compatibility check. Target authors add a VERSION template and supply a
RuntimeMetaData.checkVersion() method.
---
.../Java/src/org/antlr/v4/runtime/Parser.java | 14 +-----
.../org/antlr/v4/runtime/RuntimeMetaData.java | 16 ++++++
.../v4/tool/templates/codegen/Java/Java.stg | 11 ++++
tool/src/org/antlr/v4/Tool.java | 50 +++----------------
.../org/antlr/v4/codegen/CodeGenerator.java | 7 ++-
tool/src/org/antlr/v4/tool/ErrorType.java | 8 ++-
6 files changed, 49 insertions(+), 57 deletions(-)
create mode 100644 runtime/Java/src/org/antlr/v4/runtime/RuntimeMetaData.java
diff --git a/runtime/Java/src/org/antlr/v4/runtime/Parser.java b/runtime/Java/src/org/antlr/v4/runtime/Parser.java
index 79f781c87..662a1e639 100644
--- a/runtime/Java/src/org/antlr/v4/runtime/Parser.java
+++ b/runtime/Java/src/org/antlr/v4/runtime/Parser.java
@@ -29,13 +29,7 @@
*/
package org.antlr.v4.runtime;
-import org.antlr.v4.runtime.atn.ATN;
-import org.antlr.v4.runtime.atn.ATNDeserializationOptions;
-import org.antlr.v4.runtime.atn.ATNDeserializer;
-import org.antlr.v4.runtime.atn.ATNSimulator;
-import org.antlr.v4.runtime.atn.ATNState;
-import org.antlr.v4.runtime.atn.ParserATNSimulator;
-import org.antlr.v4.runtime.atn.RuleTransition;
+import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.misc.IntegerStack;
import org.antlr.v4.runtime.misc.IntervalSet;
@@ -48,11 +42,7 @@ import org.antlr.v4.runtime.tree.TerminalNode;
import org.antlr.v4.runtime.tree.pattern.ParseTreePattern;
import org.antlr.v4.runtime.tree.pattern.ParseTreePatternMatcher;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.WeakHashMap;
+import java.util.*;
/** This is all the parsing support code essentially; most of it is error recovery stuff. */
public abstract class Parser extends Recognizer {
diff --git a/runtime/Java/src/org/antlr/v4/runtime/RuntimeMetaData.java b/runtime/Java/src/org/antlr/v4/runtime/RuntimeMetaData.java
new file mode 100644
index 000000000..7e113af8f
--- /dev/null
+++ b/runtime/Java/src/org/antlr/v4/runtime/RuntimeMetaData.java
@@ -0,0 +1,16 @@
+package org.antlr.v4.runtime;
+
+public class RuntimeMetaData {
+ /** Must match version of tool that generated recognizers */
+ public static final String VERSION = "4.2"; // use just "x.y" and don't include bug fix release number
+
+ /** As parser or lexer class is loaded, it checks that the version used to generate the code
+ * is compatible with the runtime version. ANTLR tool generates recognizers with a hardcoded string created by
+ * the tool during code gen. That version is passed to checkVersion().
+ */
+ public static void checkVersion(String toolVersion) {
+ if ( !VERSION.equals(toolVersion) ) {
+ System.err.println("ANTLR runtime and generated code versions disagree: "+VERSION+"!="+toolVersion);
+ }
+ }
+}
diff --git a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg
index 6b0e9bc07..bcd937118 100644
--- a/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg
+++ b/tool/resources/org/antlr/v4/tool/templates/codegen/Java/Java.stg
@@ -28,6 +28,14 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/** ANTLR tool checks output templates are compatible with tool code generation.
+ * For now, a simple string match used on x.y of x.y.z scheme.
+ * Must match Tool.VERSION during load to templates.
+ *
+ * REQUIRED.
+ */
+VERSION() ::= "4.2" // use just "x.y" and don't include bug fix release number
+
javaTypeInitMap ::= [
"int":"0",
"long":"0",
@@ -214,6 +222,8 @@ Parser(parser, funcs, atn, sempredFuncs, superClass) ::= <<
Parser_(parser, funcs, atn, sempredFuncs, ctor, superClass) ::= <<
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class extends {
+ static { RuntimeMetaData.checkVersion(""); }
+
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
new PredictionContextCache();
@@ -848,6 +858,7 @@ import org.antlr.v4.runtime.misc.*;
Lexer(lexer, atn, actionFuncs, sempredFuncs, superClass) ::= <<
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class extends {
+ static { RuntimeMetaData.checkVersion(""); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
new PredictionContextCache();
diff --git a/tool/src/org/antlr/v4/Tool.java b/tool/src/org/antlr/v4/Tool.java
index 3ef1f3a3b..28c7d8246 100644
--- a/tool/src/org/antlr/v4/Tool.java
+++ b/tool/src/org/antlr/v4/Tool.java
@@ -30,67 +30,31 @@
package org.antlr.v4;
-import org.antlr.runtime.ANTLRFileStream;
-import org.antlr.runtime.ANTLRStringStream;
-import org.antlr.runtime.CharStream;
-import org.antlr.runtime.CommonTokenStream;
-import org.antlr.runtime.ParserRuleReturnScope;
-import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.*;
import org.antlr.v4.analysis.AnalysisPipeline;
import org.antlr.v4.automata.ATNFactory;
import org.antlr.v4.automata.LexerATNFactory;
import org.antlr.v4.automata.ParserATNFactory;
import org.antlr.v4.codegen.CodeGenPipeline;
import org.antlr.v4.misc.Graph;
-import org.antlr.v4.parse.ANTLRParser;
-import org.antlr.v4.parse.GrammarASTAdaptor;
-import org.antlr.v4.parse.GrammarTreeVisitor;
-import org.antlr.v4.parse.ToolANTLRLexer;
-import org.antlr.v4.parse.ToolANTLRParser;
-import org.antlr.v4.parse.v3TreeGrammarException;
+import org.antlr.v4.parse.*;
import org.antlr.v4.runtime.misc.LogManager;
import org.antlr.v4.runtime.misc.Nullable;
import org.antlr.v4.semantics.SemanticPipeline;
-import org.antlr.v4.tool.ANTLRMessage;
-import org.antlr.v4.tool.ANTLRToolListener;
-import org.antlr.v4.tool.BuildDependencyGenerator;
-import org.antlr.v4.tool.DOTGenerator;
-import org.antlr.v4.tool.DefaultToolListener;
-import org.antlr.v4.tool.ErrorManager;
-import org.antlr.v4.tool.ErrorType;
-import org.antlr.v4.tool.Grammar;
-import org.antlr.v4.tool.GrammarTransformPipeline;
-import org.antlr.v4.tool.LexerGrammar;
-import org.antlr.v4.tool.Rule;
-import org.antlr.v4.tool.ast.ActionAST;
-import org.antlr.v4.tool.ast.GrammarAST;
-import org.antlr.v4.tool.ast.GrammarASTErrorNode;
-import org.antlr.v4.tool.ast.GrammarRootAST;
-import org.antlr.v4.tool.ast.RuleAST;
-import org.antlr.v4.tool.ast.TerminalAST;
+import org.antlr.v4.tool.*;
+import org.antlr.v4.tool.ast.*;
import org.stringtemplate.v4.STGroup;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.StringWriter;
-import java.io.Writer;
+import java.io.*;
import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class Tool {
public static final String VERSION;
static {
String version = Tool.class.getPackage().getImplementationVersion();
- VERSION = version != null ? version : "4.x";
+ VERSION = version != null ? version : "4.2";
}
public static final String GRAMMAR_EXTENSION = ".g4";
diff --git a/tool/src/org/antlr/v4/codegen/CodeGenerator.java b/tool/src/org/antlr/v4/codegen/CodeGenerator.java
index 2d2ae3b42..3191b1ed6 100644
--- a/tool/src/org/antlr/v4/codegen/CodeGenerator.java
+++ b/tool/src/org/antlr/v4/codegen/CodeGenerator.java
@@ -88,7 +88,12 @@ public class CodeGenerator {
}
public STGroup getTemplates() {
- return getTarget().getTemplates();
+ STGroup templates = getTarget().getTemplates();
+ ST version = templates.getInstanceOf("VERSION");
+ if ( version==null || !version.render().equals(Tool.VERSION) ) {
+ tool.errMgr.toolError(ErrorType.INCOMPATIBLE_TOOL_AND_TEMPLATES, version, Tool.VERSION, language);
+ }
+ return templates;
}
protected void loadLanguageTarget(String language) {
diff --git a/tool/src/org/antlr/v4/tool/ErrorType.java b/tool/src/org/antlr/v4/tool/ErrorType.java
index eb4bf5824..a512fe691 100644
--- a/tool/src/org/antlr/v4/tool/ErrorType.java
+++ b/tool/src/org/antlr/v4/tool/ErrorType.java
@@ -169,6 +169,12 @@ public enum ErrorType {
* no mapping to template name for output model class 'class'
*/
NO_MODEL_TO_TEMPLATE_MAPPING(34, "no mapping to template name for output model class ''", ErrorSeverity.ERROR),
+ /**
+ * Compiler Error 35.
+ *
+ * templates and tool aren't compatible
+ */
+ INCOMPATIBLE_TOOL_AND_TEMPLATES(35, " code generation templates and tool versions disagree: != ", ErrorSeverity.ERROR),
/*
* Grammar errors
@@ -694,7 +700,7 @@ public enum ErrorType {
* Some lexer commands require an argument.
*
* The following rule produces this error.
- *
+ *
*
* X : 'foo' -> type(Foo); // ok
* Y : 'foo' -> type; // error 150 (the type command requires an argument)