All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
gw.lang.parser.exceptions.ParseIssue Maven / Gradle / Ivy
/*
* Copyright 2014 Guidewire Software, Inc.
*/
package gw.lang.parser.exceptions;
import gw.lang.parser.IExpression;
import gw.lang.parser.ISource;
import gw.lang.parser.expressions.IProgram;
import gw.lang.reflect.gs.IGosuClass;
import gw.lang.parser.resources.ResourceKey;
import gw.lang.parser.IParseIssue;
import gw.lang.parser.ISymbolTable;
import gw.lang.parser.IParsedElement;
import gw.lang.parser.IParserState;
import gw.lang.parser.IFullParserState;
import gw.lang.parser.IParserPart;
import gw.lang.parser.IScriptPartId;
import gw.lang.reflect.IType;
import gw.config.CommonServices;
public abstract class ParseIssue extends Exception implements IParseIssue
{
private static final String SOURCE_DELIMITER = "\nat line ";
private static final int CONTEXT_LINES = 3;
private Integer _lineNumber;
private Integer _lineOffset;
private Integer _tokenColumn;
private Integer _tokenStart;
private Integer _tokenEnd;
private ResourceKey _messageKey;
private Object[] _messageArgs;
private ISymbolTable _symbolTable;
private IParsedElement _parentElement;
private String _stateSource;
private IGosuClass _parentClass;
private void debug() {
// if (toString().contains("PXLOGGER")) {
// int uuuu = 0;
// }
}
protected ParseIssue( IParserState parserState, ResourceKey key, Object... msgArgs )
{
super( "" );
_messageKey = key;
_messageArgs = normalizeMessageArgs(msgArgs);
initFieldsFromParserState( parserState );
debug();
}
protected ParseIssue( Integer lineNumber, Integer lineOffset, Integer tokenColumn,
Integer tokenStart, Integer tokenEnd,
ISymbolTable symbolTable, ResourceKey key, Object... msgArgs )
{
super( "" );
_messageKey = key;
_messageArgs = normalizeMessageArgs(msgArgs);
_symbolTable = symbolTable;
_lineNumber = lineNumber;
_lineOffset = lineOffset == null ? 1 : Math.max( 1, lineOffset );
_tokenColumn = tokenColumn;
_tokenStart = tokenStart;
_tokenEnd = tokenEnd;
debug();
}
protected ParseIssue( IParserState state, Throwable t )
{
super( t );
initFieldsFromParserState( state );
debug();
}
/**
* Don't fill in stack trace since parse issues are not really "exceptional"
* in terms of the parser's Java implementation; we don't care much about the
* Java stack trace when these are thrown. Rather parse issues provide a means
* to tag parsed elements with issues discovered during parsing, such as
* syntax warnings and errors. Hence, the ParseIssue interface.
*
* Note this method is otherwise very costly from a performance standpoint.
*
*/
public Throwable fillInStackTrace()
{
return this;
}
private void initFieldsFromParserState( IParserState parserState )
{
if( parserState != null )
{
if( parserState instanceof IFullParserState )
{
IFullParserState fullParserState = (IFullParserState)parserState;
_symbolTable = fullParserState.getSymbolTable();
}
_lineNumber = parserState.getLineNumber();
_lineOffset = Math.max( 1, parserState.getLineOffset() );
_tokenColumn = parserState.getTokenColumn();
_tokenStart = parserState.getTokenStart();
_tokenEnd = parserState.getTokenEnd();
// Copy the value because the source is a string built from a StringBuffer which will have the whole array allocated.
String parserSource = parserState.getSource();
setStateSource( parserSource );
}
}
/**
* Normalize all non string & non number args to string types to prevent
* race conditions wrt/ the TypeSystem lock when the message is formatted.
*/
private Object [] normalizeMessageArgs(Object [] args) {
Object [] result = args;
if(args != null && args.length > 0) {
result = new Object[args.length];
for(int i = 0; i < args.length; i++) {
if(args[i] == null || args[i] instanceof CharSequence || args[i] instanceof Number) {
result[i] = args[i];
} else {
result[i] = args[i].toString();
}
}
}
return result;
}
protected static String formatError( ResourceKey key, Object... msgArgs )
{
if( key != null )
{
return CommonServices.getGosuLocalizationService().localize( key, msgArgs );
}
else
{
return "";
}
}
public Integer getLineNumber()
{
return _lineNumber;
}
public Integer getLineOffset()
{
return _lineOffset;
}
public void addLineOffset( int offset )
{
_lineOffset += offset;
}
public Integer getTokenColumn()
{
return _tokenColumn;
}
public Integer getTokenEnd()
{
return _tokenEnd;
}
public Integer getTokenStart()
{
return _tokenStart;
}
public String getContextString()
{
if( getStateSource() != null )
{
return makeContextString( _lineNumber, getStateSource(), getLineReportingOffset() );
}
else
{
return null;
}
}
public String getContextStringNoLineNumbers() {
if( getStateSource() != null )
{
return makeContextString( _lineNumber, getStateSource(), getLineReportingOffset(), false );
}
else
{
return null;
}
}
public String getStateSource()
{
if( _stateSource == null && _parentClass != null )
{
ISource source = _parentClass.getSourceFileHandle().getSource();
return source == null ? null : source.getSource();
}
return _stateSource;
}
public void setStateSource( String parserSource )
{
_stateSource = parserSource;
}
private String getMyMessage() {
if (_messageKey != null) {
return formatError(_messageKey, _messageArgs);
} else if (getCause() != null){
return getCause().getMessage();
} else {
return "";
}
}
public String getPlainMessage()
{
return getMyMessage();
}
public String getConsoleMessage()
{
StringBuilder retVal = new StringBuilder();
retVal.append( getMyMessage() );
if( _lineNumber != null )
{
retVal.append( " [line:" ).append( _lineNumber - getLineReportingOffset() ).append( " col:" ).append( _tokenColumn );
retVal.append( "]" );
if( getStateSource() != null )
{
retVal.append( " in\n" );
retVal.append( getContextString() );
}
}
return (retVal.toString());
}
public static String makeContextString( int lineOfError, String source, int lineReportingOffset )
{
return makeContextString(lineOfError, source, lineReportingOffset, true);
}
private static String makeContextString( int lineOfError, String source, int lineReportingOffset, boolean showLineNumbers )
{
int offset = (CONTEXT_LINES - 1) / 2;
int minLine = Math.max( lineOfError - offset, 1 );
int maxLine = lineOfError + offset;
int padding = maxLine <= 0 ? 1 : ((int)Math.log10( maxLine ) + 1);
StringBuilder sb = new StringBuilder();
int pos = 0;
int currentLine = 1;
while( pos < source.length() && currentLine < minLine )
{
char c = source.charAt( pos );
if( c == '\n' )
{
++currentLine;
}
++pos;
}
if( showLineNumbers )
{
sb.append( String.format( "line %1$" + padding + "s: ", currentLine - lineReportingOffset ) );
}
while( pos < source.length() && currentLine <= maxLine )
{
char c = source.charAt( pos );
if( c == '\n' )
{
++currentLine;
if( currentLine <= maxLine )
{
sb.append( '\n' );
if( showLineNumbers )
{
sb.append( String.format( "line %1$" + padding + "s: ", currentLine - lineReportingOffset ) );
}
}
}
else
{
sb.append( c );
}
++pos;
}
return sb.toString();
}
public String getUIMessage()
{
String strMessage = getMyMessage();
if( strMessage != null )
{
int iIndex = strMessage.indexOf( SOURCE_DELIMITER );
if( iIndex >= 0 )
{
strMessage = strMessage.substring( 0, iIndex );
}
}
return strMessage;
}
public int getLine()
{
Integer lineNumber = getLineNumber();
return lineNumber == null ? -1 : lineNumber;
}
public int getColumn()
{
return getTokenColumn();
}
/**
* Warning: Only valid if called from the parser thread. Otherwise we null it out.
*/
public IParsedElement getSource()
{
return _parentElement;
}
public void setSource( IParsedElement sourceOfError )
{
_parentElement = sourceOfError;
}
/**
* Warning: Only valid if called from the parser thread. Otherwise we null it out.
*/
public ISymbolTable getSymbolTable()
{
return _symbolTable;
}
public boolean appliesToPosition( int iPos )
{
Integer tokenStart = getTokenStart();
Integer tokenEnd = getTokenEnd();
return iPos >= tokenStart && iPos <= tokenEnd;
}
public ResourceKey getMessageKey()
{
return _messageKey;
}
public void resolve( IParserPart parserBase )
{
if( parserBase != null )
{
IScriptPartId scriptPart = parserBase.getOwner().getScriptPart();
IType parentType = scriptPart == null ? null : scriptPart.getContainingType();
if( parentType instanceof IGosuClass )
{
_parentClass = (IGosuClass)parentType;
_stateSource = null;
}
}
if( _parentElement != null )
{
resetPositions();
if( parserBase != null && !parserBase.getOwner().isEditorParser() )
{
_parentElement = null;
_symbolTable = null;
}
}
}
public void resetPositions()
{
if( _parentElement == null )
{
return;
}
boolean bForce = _parentElement instanceof IExpression && !(_parentElement instanceof IProgram);
if( bForce || _lineNumber == null )
{
_lineNumber = _parentElement.getLineNum();
}
if( bForce || _lineOffset == null )
{
_lineOffset = _parentElement.getLocation().getOffset() - _parentElement.getLocation().getColumn();
}
if( bForce || _tokenColumn == null )
{
_tokenColumn = _parentElement.getColumn();
}
if( bForce || _tokenStart == null )
{
_tokenStart = _parentElement.getLocation().getOffset();
}
if( bForce || _tokenEnd == null )
{
_tokenEnd = _parentElement.getLocation().getExtent() + 1;
}
}
public void adjustOffset(int offset, int lineNumOffset, int columnOffset) {
_tokenStart += offset;
_tokenEnd += offset;
_lineNumber += lineNumOffset;
_tokenColumn += columnOffset;
}
public void setMessage( ResourceKey key, Object... args )
{
_messageKey = key;
_messageArgs = normalizeMessageArgs(args);
}
public Object[] getMessageArgs()
{
return _messageArgs;
}
public int getLineReportingOffset()
{
return 0;
}
public IType getExpectedType()
{
return null;
}
}