/**
* <copyright>
*
* Copyright (c) 2008,2010 Eclipse Modeling Project and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* E.D.Willink - initial API and implementation
*
* </copyright>
*
* $Id: CommonProblemHandler.java,v 1.1 2010/03/11 14:51:19 ewillink Exp $
*/
package org.eclipse.ocl.examples.editor.ui.imp;
import lpg.runtime.IToken;
import org.eclipse.core.resources.IMarker;
import org.eclipse.imp.parser.IMessageHandler;
import org.eclipse.ocl.examples.editor.ui.OCLExamplesEditorPlugin;
import org.eclipse.ocl.examples.editor.ui.builder.MarkerProblemHandler;
import org.eclipse.ocl.examples.editor.ui.builder.ProblemLimit;
import org.eclipse.ocl.lpg.AbstractParser;
import org.eclipse.ocl.lpg.AbstractProblemHandler;
import org.eclipse.ocl.lpg.DerivedPrsStream;
/**
* A CommonProblemHandler arranges for errors, reported via the MDT OCL
* ProblemHandler API, to be redirected to an IMP IMessageHandler.
*/
public class CommonProblemHandler extends AbstractProblemHandler
{
protected final IMessageHandler handler;
private ProblemLimit problemLimit = null;
public CommonProblemHandler(AbstractParser parser, IMessageHandler handler) {
super(parser);
this.handler = handler;
handler.clearMessages();
}
public IToken getNearestTokenAtCharacter(int offset) { // FIXME Move to AbstractParser
AbstractParser parser = getParser();
DerivedPrsStream parseStream = parser.getIPrsStream();
int maxIndex = parseStream.getSize();
if (maxIndex <= 0)
return null;
int tokenIndex = parseStream.getTokenIndexAtCharacter(offset);
if (tokenIndex >= 0)
return parseStream.getTokenAt(tokenIndex >= maxIndex ? (maxIndex-1) : tokenIndex);
tokenIndex = -tokenIndex + 1; // offset is between tokens
IToken prevToken = parseStream.getTokenAt(tokenIndex >= maxIndex ? (maxIndex-1) : tokenIndex);
IToken nextToken = parseStream.getTokenAt((tokenIndex+1) >= maxIndex ? (maxIndex-1) : (tokenIndex+1));
int prevEndOffset = prevToken.getEndOffset();
int nextStartOffset = nextToken.getStartOffset();
int postEnd = offset - prevEndOffset;
int preStart = nextStartOffset - offset;
if (postEnd >= 0) {
if (preStart >= 0)
return preStart < postEnd ? prevToken : nextToken;
else
return prevToken;
}
else {
if (preStart >= 0)
return nextToken;
else
return nextToken; // Anything is better than null
}
}
@Override
public void handleProblem(Severity problemSeverity,
Phase processingPhase, String problemMessage,
String processingContext, int startOffset, int endOffset) {
try {
if (startOffset < 0)
startOffset = 0;
if (endOffset < 0)
endOffset = 0;
IToken startToken = getNearestTokenAtCharacter(startOffset);
IToken endToken = getNearestTokenAtCharacter(endOffset);
int startLine = startToken != null ? startToken.getLine() : 0;
int startCol = startToken != null ? startToken.getColumn() : 0;
int endLine = endToken != null ? endToken.getLine() : 0;
int endCol = endToken != null ? endToken.getColumn() : 0;
String adjustedMessage = problemMessage;
if (problemLimit != null) {
Integer severity = MarkerProblemHandler.severityMap.get(problemSeverity);
adjustedMessage = problemLimit.check(severity != null ? severity.intValue() : IMarker.SEVERITY_ERROR, adjustedMessage);
if (adjustedMessage == null)
return;
}
// FIXME Get Annotation to display alternate severities
String prefixedMessage = problemSeverity != null ? (problemSeverity.name() + ": " + problemMessage) : problemMessage;
handler.handleSimpleMessage(prefixedMessage, startOffset, endOffset,
startCol, endCol, startLine, endLine);
if (adjustedMessage != problemMessage)
throw new ProblemLimit.LimitExceededException(adjustedMessage);
} catch(Throwable e) {
OCLExamplesEditorPlugin.logError("Failed to handleProblem", e);
}
}
public void setProblemLimit(ProblemLimit problemLimit) {
this.problemLimit = problemLimit;
}
}