blob: 3f4d8d1363055b2f0b0c8d30c6055c022545d595 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013, 2015 Ericsson
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Alexandre Montplaisir - Initial API and implementation
* Matthew Khouzam - Addition to have more descriptive errors
*******************************************************************************/
package org.eclipse.tracecompass.internal.ctf.core.event.metadata;
import java.lang.reflect.Field;
import org.antlr.runtime.MismatchedTokenException;
import org.antlr.runtime.RecognitionException;
import org.eclipse.tracecompass.ctf.core.CTFException;
import org.eclipse.tracecompass.ctf.parser.CTFLexer;
/**
* CTF Reader exception but dealing with Antlr-specific parsing problems.
*
* It is separated from the main {@link CTFException} - and is not part of the
* API - to isolate the Antlr-specific classes and avoid pushing that dependency
* to the users of this plugin.
*
* @author Matthew Khouzam
*/
public class CtfAntlrException extends CTFException {
private static final long serialVersionUID = -7078624493350073777L;
private final int fErrorLine;
private final String fFile;
private String fExpectingName = ""; //$NON-NLS-1$
private int fExpectedValue = -1;
private String fActualName = ""; //$NON-NLS-1$
private int fActualValue = -1;
private final int fCharPositionInLine;
/**
* Re-throw the exception but read its data
*
* @param e
* the previous recognition exception (Antlr specific)
*/
public CtfAntlrException(MismatchedTokenException e) {
super(e);
fErrorLine = e.line;
fCharPositionInLine = e.charPositionInLine;
fFile = "metadata"; //$NON-NLS-1$ // we're in CTF, the only thing using antlr is metadata
parseMismatchedException(e);
}
/**
* Re-throw the exception but read its data
*
* @param e
* the previous recognition exception (Antlr specific)
*/
public CtfAntlrException(RecognitionException e) {
super(e);
fErrorLine = e.line;
fCharPositionInLine = e.charPositionInLine;
fFile = "metadata"; //$NON-NLS-1$ // we're in CTF, the only thing using antlr is metadata
}
/**
* Re-throw the exception but read its data
*
* @param e
* the previous rewrite exception (Antlr specific)
*/
public CtfAntlrException(Exception e) {
super(e);
fErrorLine = -1;
fCharPositionInLine = -1;
fFile = "metadata"; //$NON-NLS-1$ // we're in CTF, the only thing using antlr is metadata
}
private void parseMismatchedException(MismatchedTokenException m) {
// Iterate through the tokens that are hidden in the CTFLexer
// They are private static final int fields.
for (Field f : CTFLexer.class.getDeclaredFields()) {
f.setAccessible(true);
String name;
int value;
try {
name = f.getName();
final boolean isInt = (f.getType().isPrimitive());
if (isInt) {
value = ((Integer) f.get(null)).intValue();
if (value == m.expecting) {
fExpectingName = name;
fExpectedValue = value;
}
if (value == m.getUnexpectedType()) {
fActualName = name;
fActualValue = value;
}
}
} catch (NullPointerException e1) {
// Pokemon, gotta catch em all!
// actually useful since f may not have a
// value
} catch (IllegalArgumentException | IllegalAccessException e1) {
// Catch these exceptions (reflexion)
}
if (!this.fExpectingName.isEmpty() && !this.fActualName.isEmpty()) {
return;
}
}
}
@Override
public String getMessage() {
final String message = super.getMessage();
if (fErrorLine == -1) {
return message;
}
String expected = Integer.toString(fExpectedValue);
String actual = Integer.toString(fActualValue);
String newMessage = message.replaceAll(expected, fExpectingName);
newMessage = newMessage.replaceAll(actual, fActualName);
return newMessage + " at " + fFile + ":" + fErrorLine + ":" + fCharPositionInLine; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}