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)