package org.erlide.test_support.ui.trace;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.IAnnotationModelExtension;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.editors.text.TextEditor;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.erlide.util.ErlLogger;
public class TraceEditor extends TextEditor {
private Annotation callMatchingLine = null;
public TraceEditor() {
}
@Override
protected void initializeEditor() {
super.initializeEditor();
final TraceEditorConfiguration cfg = new TraceEditorConfiguration(
getPreferenceStore(), this);
setSourceViewerConfiguration(cfg);
}
@Override
public void createPartControl(final Composite parent) {
super.createPartControl(parent);
getSourceViewer().getTextWidget().addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(final MouseEvent e) {
super.mouseDown(e);
markCall();
}
});
}
@Override
public boolean isEditable() {
return false;
}
@Override
public boolean isEditorInputModifiable() {
return false;
}
@Override
public boolean isEditorInputReadOnly() {
return true;
}
@Override
public boolean isDirty() {
return false;
}
public void markCall() {
final IDocumentProvider documentProvider = getDocumentProvider();
final IAnnotationModel annotationModel = documentProvider
.getAnnotationModel(getEditorInput());
final ITextSelection pos = (ITextSelection) getSelectionProvider().getSelection();
final MarkCallLocation location = new MarkCallLocation(
getSourceViewer().getDocument(), pos.getStartLine());
final Position position = new Position(location.getOffset(),
location.getLength());
final String description = location.getDescription();
final Annotation oldAnnotation = callMatchingLine;
if (position.getOffset() != 0) {
callMatchingLine = new Annotation("org.erlide.test_support.trace.call", false,
description);
} else {
callMatchingLine = null;
}
if (annotationModel instanceof IAnnotationModelExtension) {
final Map<Annotation, Position> annotationMap = new HashMap<>();
if (callMatchingLine != null) {
annotationMap.put(callMatchingLine, position);
}
((IAnnotationModelExtension) annotationModel).replaceAnnotations(
new Annotation[] { oldAnnotation }, annotationMap);
} else {
annotationModel.addAnnotation(callMatchingLine, position);
}
}
private class MarkCallLocation {
private String description;
private int length;
private int offset;
public MarkCallLocation(final IDocument doc, final int line) {
try {
final IRegion info = doc.getLineInformation(line);
final String lineStr = doc.get(info.getOffset(), info.getLength());
try {
final String cmd = lineStr.substring(26, 32);
if ("return".equals(cmd)) {
String ref = lineStr.substring(34, lineStr.indexOf(" ->"));
ref = ref.substring(0, ref.length() - 2);
// find call before it
for (int ln = line - 1; ln > 0; ln--) {
final IRegion li = doc.getLineInformation(ln);
final String ls = doc.get(li.getOffset(), li.getLength());
if (ls.contains(ref)) {
offset = li.getOffset();
length = li.getLength();
description = ref;
break;
}
}
} else if (" call".equals(cmd)) {
final String ref = lineStr.substring(34, lineStr.indexOf('('));
// find return after it
for (int ln = line + 1; ln < doc.getNumberOfLines(); ln++) {
final IRegion li = doc.getLineInformation(ln);
final String ls = doc.get(li.getOffset(), li.getLength());
if (ls.contains(ref)) {
offset = li.getOffset();
length = li.getLength();
description = ref;
break;
}
}
} else {
// do nothing
}
} catch (final Exception e) {
// ignore
}
} catch (final BadLocationException e) {
ErlLogger.error(e);
}
}
public int getOffset() {
return offset;
}
public int getLength() {
return length;
}
public String getDescription() {
return description;
}
}
}