add tool-template and generatedcode-runtime version compatibility check. Target authors add a VERSION template and supply a RuntimeMetaData.checkVersion() method.

This commit is contained in:
Terence Parr 2014-05-19 17:25:01 -07:00
parent 3111db7a76
commit a3d4ba53a3
6 changed files with 49 additions and 57 deletions

View File

@ -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<Token, ParserATNSimulator> {

View File

@ -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);
}
}
}

View File

@ -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 <parser.name> extends <superClass> {
static { RuntimeMetaData.checkVersion("<file.ANTLRVersion>"); }
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 <lexer.name> extends <superClass> {
static { RuntimeMetaData.checkVersion("<lexerFile.ANTLRVersion>"); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
new PredictionContextCache();

View File

@ -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";

View File

@ -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) {

View File

@ -169,6 +169,12 @@ public enum ErrorType {
* no mapping to template name for output model class '<em>class</em>'</p>
*/
NO_MODEL_TO_TEMPLATE_MAPPING(34, "no mapping to template name for output model class '<arg>'", ErrorSeverity.ERROR),
/**
* Compiler Error 35.
*
* <p>templates and tool aren't compatible</p>
*/
INCOMPATIBLE_TOOL_AND_TEMPLATES(35, "<arg3> code generation templates and tool versions disagree: <arg> != <arg2>", ErrorSeverity.ERROR),
/*
* Grammar errors
@ -694,7 +700,7 @@ public enum ErrorType {
* <p>Some lexer commands require an argument.</p>
*
* <p>The following rule produces this error.</p>
*
*
* <pre>
* X : 'foo' -> type(Foo); // ok
* Y : 'foo' -> type; // error 150 (the type command requires an argument)