forked from jasder/antlr
simplify. no need for listeners as System.err can be reset.
This commit is contained in:
parent
49a8029985
commit
2a28a9b4f3
|
@ -33,9 +33,6 @@ package org.antlr.v4.runtime;
|
|||
import org.antlr.v4.runtime.misc.NotNull;
|
||||
import org.antlr.v4.runtime.misc.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
* This class provides access to the current version of the ANTLR 4 runtime
|
||||
* library as compile-time and runtime constants, along with methods for
|
||||
|
@ -53,14 +50,15 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
* in generated code, is provided in the documentation for the method.</p>
|
||||
*
|
||||
* <p>
|
||||
* By default, the {@link DefaultListener#INSTANCE} listener is automatically
|
||||
* registered. As long as the default listener is registered, it will always be
|
||||
* the last listener notified in the event of a version mismatch. This behavior
|
||||
* ensures that custom listeners registered by a user will be notified even in
|
||||
* the event the default listener throws an exception. This default listener may
|
||||
* be removed by calling {@link #removeListener} for
|
||||
* {@link DefaultListener#INSTANCE} or {@link #clearListeners}. If required, it
|
||||
* may be re-registered by calling {@link #addListener}.</p>
|
||||
* Version strings x.y and x.y.z are considered "compatible" and no error
|
||||
* would be generated. Likewise, version strings x.y-SNAPSHOT and x.y.z are
|
||||
* considered "compatible" because the major and minor components x.y
|
||||
* are the same in each.</p>
|
||||
*
|
||||
* <p>
|
||||
* To trap any error messages issued by this code, use System.setErr()
|
||||
* in your main() startup code.
|
||||
* </p>
|
||||
*
|
||||
* @since 4.3
|
||||
*/
|
||||
|
@ -72,104 +70,13 @@ public class RuntimeMetaData {
|
|||
* <p>
|
||||
* This compile-time constant value allows generated parsers and other
|
||||
* libraries to include a literal reference to the version of the ANTLR 4
|
||||
* runtime library the code was compiled against.</p>
|
||||
*/
|
||||
public static final String VERSION = "4.5";
|
||||
|
||||
/**
|
||||
* This class provides detailed information about a mismatch between the
|
||||
* version of the tool a parser was generated with, the version of the
|
||||
* runtime a parser was compiled against, and/or the currently executing
|
||||
* version of the runtime.
|
||||
* runtime library the code was compiled against. At each release, we
|
||||
* change this value.</p>
|
||||
*
|
||||
* @see #checkVersion
|
||||
*/
|
||||
public static class VersionMismatchException extends RuntimeException {
|
||||
/**
|
||||
* The version of the ANTLR 4 Tool a parser was generated with. This
|
||||
* value may be {@code null} if {@link #checkVersion} was called from
|
||||
* user-defined code instead of a call automatically included in the
|
||||
* generated parser.
|
||||
*/
|
||||
@Nullable
|
||||
public final String generatingToolVersion;
|
||||
/**
|
||||
* The version of the ANTLR 4 Runtime library the parser and/or user
|
||||
* code was compiled against.
|
||||
*/
|
||||
@NotNull
|
||||
public final String compileTimeRuntimeVersion;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of the {@link VersionMismatchException}
|
||||
* class with the specified detailed information about a mismatch
|
||||
* between ANTLR tool and runtime versions used by a parser.
|
||||
*
|
||||
* @param message the detail message. The detail message is saved for
|
||||
* later retrieval by the {@link #getMessage()} method.
|
||||
* @param generatingToolVersion The version of the ANTLR 4 Tool a parser
|
||||
* was generated with, or {@code null} if the version check was not part
|
||||
* of the automatically-generated parser code
|
||||
* @param compileTimeRuntimeVersion The version of the ANTLR 4 Runtime
|
||||
* library the code was compiled against
|
||||
*/
|
||||
VersionMismatchException(@NotNull String message, @Nullable String generatingToolVersion, @NotNull String compileTimeRuntimeVersion) {
|
||||
super(message);
|
||||
this.generatingToolVersion = generatingToolVersion;
|
||||
this.compileTimeRuntimeVersion = compileTimeRuntimeVersion;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This interface defines a listener which handles notifications about
|
||||
* mismatched ANTLR Tool and/or Runtime versions.
|
||||
*/
|
||||
public interface Listener {
|
||||
/**
|
||||
* Report a version mismatch which was detected by
|
||||
* {@link #checkVersion}.
|
||||
*
|
||||
* <p>
|
||||
* Implementations of this method may, but are not required to, throw
|
||||
* the provided exception. Note that if a registered listener throws the
|
||||
* provided exception during the handling of this event, the following
|
||||
* will be impacted:</p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>The lexer or parser which called {@link #checkVersion} will be
|
||||
* unusable due to throwing an exception in a static initializer
|
||||
* block.</li>
|
||||
* <li>No additional registered listeners will be notified about the
|
||||
* version mismatch. Since the default {@link DefaultListener} instance
|
||||
* is always the last listener called (unless it is unregistered), it
|
||||
* will not affect the execution of any other registered listeners, even
|
||||
* in the case where it throws an exception.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param ex a {@link VersionMismatchException} instance containing
|
||||
* detailed information about the specific version mismatch detected
|
||||
*/
|
||||
void reportVersionMismatch(@NotNull VersionMismatchException ex)
|
||||
throws VersionMismatchException;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class provides a default implementation of {@link Listener} which
|
||||
* responds to mismatched versions by throwing the provided
|
||||
* {@link VersionMismatchException} if the reported version mismatch
|
||||
* indicates the versions differ by more than the <em>major</em> and
|
||||
* <em>minor</em> version components.
|
||||
* <p>Version numbers are assumed to have the form
|
||||
*
|
||||
* <p>
|
||||
* For example, version strings x.y and x.y.z are considered "compatible",
|
||||
* and this listener will not throw an exception. Likewise, version strings
|
||||
* x.y-SNAPSHOT and x.y.z are considered "compatible" because the major and
|
||||
* minor components x.y are the same in each.</p>
|
||||
*
|
||||
* <p>
|
||||
* For the purposes of this listener, version numbers are assumed to have
|
||||
* the form
|
||||
* <em>major</em>.<em>minor</em>.<em>patch</em>.<em>revision</em>-<em>suffix</em>,
|
||||
*
|
||||
* with the individual components defined as follows.</p>
|
||||
*
|
||||
* <ul>
|
||||
|
@ -187,100 +94,7 @@ public class RuntimeMetaData {
|
|||
* omitted.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static class DefaultListener implements Listener {
|
||||
/**
|
||||
* A default instance of {@link DefaultListener} which is automatically
|
||||
* registered to receive version mismatch events.
|
||||
*/
|
||||
public static final DefaultListener INSTANCE = new DefaultListener();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>
|
||||
* The default implementation only throws an exception when the reported
|
||||
* version mismatch contains a mismatched <em>major</em> or
|
||||
* <em>minor</em> version component. For details about the syntax of the
|
||||
* input {@code version}, see the documentation for
|
||||
* {@link DefaultListener}.</p>
|
||||
*/
|
||||
@Override
|
||||
public void reportVersionMismatch(@NotNull VersionMismatchException ex) throws VersionMismatchException {
|
||||
if (!isMinorVersionMatch(ex)) {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the reported version mismatch are a match when
|
||||
* considering only the <em>major</em> and <em>minor</em> version
|
||||
* components of the version strings.
|
||||
*
|
||||
* @param ex a {@link VersionMismatchException} instance containing
|
||||
* detailed information about the specific version mismatch detected
|
||||
* @return {@code true} if the <em>major</em> and <em>minor</em> version
|
||||
* components of the version strings match; otherwise, {@code false}.
|
||||
*/
|
||||
protected boolean isMinorVersionMatch(@NotNull VersionMismatchException ex) {
|
||||
String generatingToolVersion = ex.generatingToolVersion;
|
||||
if (generatingToolVersion != null) {
|
||||
if (!getMajorMinorVersion(VERSION).equals(getMajorMinorVersion(generatingToolVersion))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return getMajorMinorVersion(VERSION).equals(getMajorMinorVersion(ex.compileTimeRuntimeVersion));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of listeners registered to receive notifications of mismatched
|
||||
* ANTLR versions.
|
||||
*/
|
||||
private static final Collection<Listener> listeners = new CopyOnWriteArraySet<Listener>();
|
||||
static {
|
||||
listeners.add(DefaultListener.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a listener to receive notifications of mismatched ANTLR
|
||||
* versions. This method ensures that as long as
|
||||
* {@link DefaultListener#INSTANCE} is registered as a listener, it will
|
||||
* always be the last listener notified of mismatched versions.
|
||||
*
|
||||
* @param listener the listener to notify if mismatched ANTLR versions are
|
||||
* detected
|
||||
*
|
||||
* @see #checkVersion
|
||||
*/
|
||||
public static synchronized void addListener(@NotNull Listener listener) {
|
||||
boolean containedDefault = listeners.remove(DefaultListener.INSTANCE);
|
||||
listeners.add(listener);
|
||||
if (containedDefault) {
|
||||
listeners.add(DefaultListener.INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a specific listener registered to receive notifications of
|
||||
* mismatched ANTLR versions.
|
||||
*
|
||||
* @param listener the listener to remove
|
||||
* @return {@code true} if the listener was removed; otherwise,
|
||||
* {@code false} if the specified listener was not found in the list of
|
||||
* registered listeners
|
||||
*/
|
||||
public static synchronized boolean removeListener(@NotNull Listener listener) {
|
||||
return listeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all listeners registered to receive notifications of mismatched
|
||||
* ANTLR versions.
|
||||
*/
|
||||
public static synchronized void clearListeners() {
|
||||
listeners.clear();
|
||||
}
|
||||
public static final String VERSION = "4.5";
|
||||
|
||||
/**
|
||||
* Gets the currently executing version of the ANTLR 4 runtime library.
|
||||
|
@ -324,19 +138,18 @@ public class RuntimeMetaData {
|
|||
*
|
||||
* <p>
|
||||
* This method does not perform any detection or filtering of semantic
|
||||
* changes between tool and runtime versions. It simply checks for a simple
|
||||
* version match and notifies the registered listeners any time a difference
|
||||
* is detected. A default instance of {@link DefaultListener} is notified
|
||||
* unless it is explicitly removed.</p>
|
||||
* changes between tool and runtime versions. It simply checks for a
|
||||
* version match and emits an error to stderr if a difference
|
||||
* is detected.</p>
|
||||
*
|
||||
* <p>
|
||||
* Note that some breaking changes between releases could result in other
|
||||
* types of runtime exceptions, such as a {@link LinkageError}, prior to
|
||||
* calling this method. In these cases, the underlying version mismatch will
|
||||
* not be reported to the listeners. This method is primarily intended to
|
||||
* not be reported here. This method is primarily intended to
|
||||
* notify users of potential semantic changes between releases that do not
|
||||
* result in binary compatibility problems which would be detected by the
|
||||
* class loader. As with semantic changes, changes which break binary
|
||||
* class loader. As with semantic changes, changes that break binary
|
||||
* compatibility between releases are mentioned in the release notes
|
||||
* accompanying the affected release.</p>
|
||||
*
|
||||
|
@ -348,37 +161,41 @@ public class RuntimeMetaData {
|
|||
* of that target's known execution environment, which may or may not
|
||||
* resemble the design provided for the Java target.</p>
|
||||
*
|
||||
* @param toolVersion The version of the tool used to generate a parser.
|
||||
* @param generatingToolVersion The version of the tool used to generate a parser.
|
||||
* This value may be null when called from user code that was not generated
|
||||
* by, and does not reference, the ANTLR 4 Tool itself.
|
||||
* @param compileTimeVersion The version of the runtime the parser was
|
||||
* compiled against. This should always be passed using a direct reference
|
||||
* to {@link #VERSION}.
|
||||
*/
|
||||
public static void checkVersion(@Nullable String toolVersion, @NotNull String compileTimeVersion) {
|
||||
boolean report = false;
|
||||
String message = null;
|
||||
if (toolVersion != null && !VERSION.equals(toolVersion)) {
|
||||
report = true;
|
||||
message = String.format("ANTLR Tool version %s used for code generation does not match the current runtime version %s", toolVersion, VERSION);
|
||||
}
|
||||
else if (!VERSION.equals(compileTimeVersion)) {
|
||||
report = true;
|
||||
message = String.format("ANTLR Runtime version %s used for parser compilation does not match the current runtime version %s", compileTimeVersion, VERSION);
|
||||
public static void checkVersion(@Nullable String generatingToolVersion, @NotNull String compileTimeVersion) {
|
||||
String runtimeVersion = VERSION;
|
||||
boolean runtimeConflictsWithGeneratingTool = false;
|
||||
boolean runtimeConflictsWithCompileTimeTool = false;
|
||||
|
||||
if ( generatingToolVersion!=null ) {
|
||||
runtimeConflictsWithGeneratingTool =
|
||||
!runtimeVersion.equals(generatingToolVersion) &&
|
||||
!getMajorMinorVersion(runtimeVersion).equals(getMajorMinorVersion(generatingToolVersion));
|
||||
}
|
||||
|
||||
if (report) {
|
||||
VersionMismatchException ex = new VersionMismatchException(message, toolVersion, compileTimeVersion);
|
||||
for (Listener listener : listeners) {
|
||||
listener.reportVersionMismatch(ex);
|
||||
}
|
||||
runtimeConflictsWithCompileTimeTool =
|
||||
!runtimeVersion.equals(compileTimeVersion) &&
|
||||
!getMajorMinorVersion(runtimeVersion).equals(getMajorMinorVersion(compileTimeVersion));
|
||||
|
||||
if ( runtimeConflictsWithGeneratingTool ) {
|
||||
System.err.printf("ANTLR Tool version %s used for code generation does not match the current runtime version %s",
|
||||
generatingToolVersion, runtimeVersion);
|
||||
}
|
||||
if ( runtimeConflictsWithCompileTimeTool ) {
|
||||
System.err.printf("ANTLR Runtime version %s used for parser compilation does not match the current runtime version %s",
|
||||
compileTimeVersion, runtimeVersion);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the major and minor version numbers from a version string. For
|
||||
* details about the syntax of the input {@code version}, see the
|
||||
* documentation for {@link org.antlr.v4.runtime.RuntimeMetaData.DefaultListener}.
|
||||
* details about the syntax of the input {@code version}.
|
||||
* E.g., from x.y.z return x.y.
|
||||
*
|
||||
* @param version The complete version string.
|
||||
|
|
|
@ -51,7 +51,6 @@ import org.antlr.v4.parse.ToolANTLRParser;
|
|||
import org.antlr.v4.parse.v3TreeGrammarException;
|
||||
import org.antlr.v4.runtime.RuntimeMetaData;
|
||||
import org.antlr.v4.runtime.misc.LogManager;
|
||||
import org.antlr.v4.runtime.misc.NotNull;
|
||||
import org.antlr.v4.runtime.misc.Nullable;
|
||||
import org.antlr.v4.semantics.SemanticPipeline;
|
||||
import org.antlr.v4.tool.ANTLRMessage;
|
||||
|
@ -95,18 +94,6 @@ public class Tool {
|
|||
// Assigned in a static{} block to prevent the field from becoming a
|
||||
// compile-time constant
|
||||
VERSION = RuntimeMetaData.VERSION;
|
||||
RuntimeMetaData.clearListeners();
|
||||
RuntimeMetaData.addListener(new RuntimeMetaData.DefaultListener() {
|
||||
@Override
|
||||
public void reportVersionMismatch(@NotNull RuntimeMetaData.VersionMismatchException ex) throws RuntimeMetaData.VersionMismatchException {
|
||||
if ( ex.generatingToolVersion.equals("4.4") && VERSION.equals("4.5") ) {
|
||||
// this is ok
|
||||
}
|
||||
else {
|
||||
super.reportVersionMismatch(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static final String GRAMMAR_EXTENSION = ".g4";
|
||||
|
|
Loading…
Reference in New Issue