package org.xpect.ui.services;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.diagnostics.Severity;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.util.IAcceptor;
import org.eclipse.xtext.util.ITextRegion;
import org.eclipse.xtext.validation.CheckType;
import org.eclipse.xtext.validation.Issue;
import org.junit.ComparisonFailure;
import org.xpect.XpectInvocation;
public class LiveTestIssueFactory {
private final static String _PREF = "org.xpect.live_test_execution.";
public final static String ISSUE_CODE_TEST_ERROR = _PREF + "test_error";
public final static String ISSUE_CODE_TEST_EXP_CHANGE = _PREF + "expectation_change";
public final static String ISSUE_CODE_TEST_EXP_DELETE = _PREF + "expectation_delete";
public final static String ISSUE_CODE_TEST_EXP_INSERT = _PREF + "expectation_insert";
public final static String ISSUE_CODE_TEST_FAIL = _PREF + "test_fail";
public final static String ISSUE_CODE_TEST_IGNORE = _PREF + "test_ignore";
public final static String ISSUE_CODE_TEST_SUCCESS = _PREF + "test_success";
protected Issue.IssueImpl createIssue(XpectInvocation inv) {
Issue.IssueImpl issue = new Issue.IssueImpl();
issue.setType(CheckType.FAST);
issue.setUriToProblem(EcoreUtil.getURI(inv));
return issue;
}
protected Issue.IssueImpl createIssueOnInvocation(XpectInvocation inv) {
Issue.IssueImpl issue = createIssue(inv);
ITextRegion region = findXPECTKeywordRegion(inv);
if (region != null) {
issue.setOffset(region.getOffset());
issue.setLength(region.getLength());
} else {
issue.setOffset(0);
issue.setLength(1);
}
return issue;
}
public Issue createSuccessIssue(XpectInvocation inv) {
Issue.IssueImpl issue = createIssueOnInvocation(inv);
issue.setMessage("Xpect test passed successfully.");
issue.setCode(ISSUE_CODE_TEST_SUCCESS);
issue.setSeverity(Severity.INFO);
return issue;
}
protected void exceptionToIssues(XpectInvocation inv, AssertionError exception, IAcceptor<Issue> result) {
Issue.IssueImpl issue = createIssueOnInvocation(inv);
issue.setMessage("Xpect test failed: " + exception.getMessage());
issue.setCode(ISSUE_CODE_TEST_FAIL);
issue.setSeverity(Severity.ERROR);
result.accept(issue);
}
protected void exceptionToIssues(XpectInvocation inv, ComparisonFailure exception, IAcceptor<Issue> result) {
ComparisonFailure cf = (ComparisonFailure) exception;
String actualDoc = cf.getActual();
String expectedDoc = inv.getFile().getDocument();
int fromStart = 0, fromEnd = 1, length = Math.min(actualDoc.length(), expectedDoc.length());
while (fromStart < length && actualDoc.charAt(fromStart) == expectedDoc.charAt(fromStart)) {
fromStart++;
}
while (fromEnd < length && actualDoc.charAt(actualDoc.length() - fromEnd) == expectedDoc.charAt(expectedDoc.length() - fromEnd)) {
fromEnd++;
}
while (fromStart > 0 && (!Character.isWhitespace(expectedDoc.charAt(fromStart)) || expectedDoc.charAt(fromStart) == '\n' || expectedDoc.charAt(fromStart) == '\r')) {
fromStart--;
}
while (fromEnd > 0 && !Character.isWhitespace(expectedDoc.charAt(expectedDoc.length() - fromEnd))) {
fromEnd--;
}
if (fromStart + fromEnd >= expectedDoc.length()) {
String text = actualDoc.substring(fromStart, actualDoc.length() - fromEnd + 1);
Issue.IssueImpl issue = createIssue(inv);
issue.setMessage("Xpect test failed because the actual test result has '" + text + "' here.");
issue.setOffset(fromStart);
issue.setLength(0);
issue.setCode(ISSUE_CODE_TEST_EXP_INSERT);
issue.setData(new String[] { text });
result.accept(issue);
} else {
fromStart++;
int endIndex = actualDoc.length() - fromEnd;
if (endIndex <= fromStart) {
Issue.IssueImpl issue = createIssue(inv);
issue.setMessage("Xpect test failed because this text is not part of the actual test result.");
issue.setOffset(fromStart);
issue.setLength(expectedDoc.length() - fromStart - fromEnd);
issue.setCode(ISSUE_CODE_TEST_EXP_DELETE);
result.accept(issue);
} else {
String text = actualDoc.substring(fromStart, endIndex);
Issue.IssueImpl issue = createIssue(inv);
issue.setMessage("Xpect test failed because in the actual test result this text is: " + text);
issue.setOffset(fromStart);
issue.setLength(expectedDoc.length() - fromStart - fromEnd);
issue.setCode(ISSUE_CODE_TEST_EXP_CHANGE);
issue.setData(new String[] { text });
result.accept(issue);
}
}
}
public void exceptionToIssues(XpectInvocation inv, Throwable exception, IAcceptor<Issue> result) {
if (exception instanceof ComparisonFailure) {
exceptionToIssues(inv, (ComparisonFailure) exception, result);
} else if (exception instanceof AssertionError) {
exceptionToIssues(inv, (AssertionError) exception, result);
} else {
Issue.IssueImpl issue = createIssueOnInvocation(inv);
issue.setMessage("Xpect test failed: " + exception.getMessage());
issue.setCode(ISSUE_CODE_TEST_ERROR);
issue.setSeverity(Severity.ERROR);
result.accept(issue);
}
}
protected ITextRegion findXPECTKeywordRegion(XpectInvocation inv) {
ICompositeNode node = NodeModelUtils.getNode(inv);
for (ILeafNode l : node.getLeafNodes()) {
if (l.getGrammarElement() instanceof Keyword && l.getText().equals("XPECT")) {
return l.getTextRegion();
}
}
return null;
}
}