blob: b8fc055afc9bbc0f5a3764cfbac3a203b4c58930 [file] [log] [blame]
package org.intellij.plugins.xsltDebugger.impl;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.ColoredTextContainer;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.PlatformIcons;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
import com.intellij.xdebugger.frame.*;
import org.intellij.plugins.xsltDebugger.VMPausedException;
import org.intellij.plugins.xsltDebugger.XsltDebuggerSession;
import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
import org.intellij.plugins.xsltDebugger.rt.engine.DebuggerStoppedException;
import org.intellij.plugins.xsltDebugger.rt.engine.Value;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.net.URI;
import java.util.List;
public class XsltStackFrame extends XStackFrame {
private final Debugger.Frame myFrame;
private final XsltDebuggerSession myDebuggerSession;
private final XSourcePosition myPosition;
public XsltStackFrame(Debugger.Frame frame, XsltDebuggerSession debuggerSession) {
myFrame = frame;
myDebuggerSession = debuggerSession;
myPosition = XsltSourcePosition.create(frame);
}
@Override
public Object getEqualityObject() {
return XsltStackFrame.class;
}
@Override
public XDebuggerEvaluator getEvaluator() {
return myFrame instanceof Debugger.StyleFrame ? new MyEvaluator((Debugger.StyleFrame)myFrame) : null;
}
@Override
public XSourcePosition getSourcePosition() {
return myPosition;
}
@Override
public void customizePresentation(@NotNull ColoredTextContainer component) {
if (myDebuggerSession.getCurrentState() == Debugger.State.SUSPENDED) {
try {
_customizePresentation(component);
}
catch (VMPausedException ignore) {
}
catch (DebuggerStoppedException ignore) {
}
}
}
private void _customizePresentation(ColoredTextContainer component) {
final Debugger.Frame frame = myFrame;
if (frame instanceof Debugger.StyleFrame) {
component.append(((Debugger.StyleFrame)frame).getInstruction(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
} else if (frame instanceof Debugger.SourceFrame) {
component.append(((Debugger.SourceFrame)frame).getXPath(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
}
component.append(" ", SimpleTextAttributes.REGULAR_ATTRIBUTES);
try {
final VirtualFile file = VfsUtil.findFileByURL(new URI(frame.getURI()).toURL());
if (file != null) {
component.append(file.getName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
if (frame.getLineNumber() > 0) {
component.append(":" + frame.getLineNumber(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
component.setToolTipText(file.getPresentableUrl());
} else {
component.append(frame.getURI() + ":" + frame.getLineNumber(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
} catch (Exception ignored) {
component.append(frame.getURI() + ":" + frame.getLineNumber(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
}
@Override
public void computeChildren(@NotNull XCompositeNode node) {
try {
if (myFrame instanceof Debugger.StyleFrame) {
final List<Debugger.Variable> variables = ((Debugger.StyleFrame)myFrame).getVariables();
final XValueChildrenList list = new XValueChildrenList();
for (final Debugger.Variable variable : variables) {
list.add(variable.getName(), new MyValue(variable));
}
node.addChildren(list, true);
} else {
super.computeChildren(node);
}
} catch (VMPausedException ignored) {
node.setErrorMessage(VMPausedException.MESSAGE);
}
}
public Debugger.Frame getFrame() {
return myFrame;
}
private static class MyValue extends XValue {
private final Debugger.Variable myVariable;
public MyValue(Debugger.Variable variable) {
myVariable = variable;
}
@Override
public void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) {
final Debugger.Variable.Kind kind = myVariable.getKind();
Icon icon = null;
if (myVariable.isGlobal()) {
if (kind == Debugger.Variable.Kind.VARIABLE) {
icon = PlatformIcons.FIELD_ICON;
} else {
icon = PlatformIcons.PROPERTY_ICON;
}
} else if (kind == Debugger.Variable.Kind.VARIABLE) {
icon = PlatformIcons.VARIABLE_ICON;
} else if (kind == Debugger.Variable.Kind.PARAMETER) {
icon = PlatformIcons.PARAMETER_ICON;
}
final Value v = myVariable.getValue();
if (v.getType() == Value.XPathType.STRING) {
node.setPresentation(icon, v.getType().getName(), "'" + String.valueOf(v.getValue()) + "'", false);
} else {
final boolean hasChildren = myVariable.getValue().getValue() instanceof Value.NodeSet;
node.setPresentation(icon, v.getType().getName(), String.valueOf(v.getValue()), hasChildren);
}
}
@Override
public void computeChildren(@NotNull XCompositeNode node) {
if (myVariable.getValue().getValue() instanceof Value.NodeSet) {
final Value.NodeSet set = (Value.NodeSet)myVariable.getValue().getValue();
final XValueChildrenList list = new XValueChildrenList();
for (final Value.Node n : set.getNodes()) {
list.add(n.myXPath, new NodeValue(n));
}
node.addChildren(list, false);
}
super.computeChildren(node);
}
@Override
public String getEvaluationExpression() {
return "$" + myVariable.getName();
}
@Override
public void computeSourcePosition(@NotNull XNavigatable navigatable) {
navigatable.setSourcePosition(XsltSourcePosition.create(myVariable));
}
static String clipValue(String stringValue) {
return stringValue.length() < 100 ? stringValue : stringValue.substring(0, 100) + "...";
}
private static class NodeValue extends XValue {
private final Value.Node myNode;
public NodeValue(Value.Node n) {
myNode = n;
}
@Override
public void computeSourcePosition(@NotNull XNavigatable navigatable) {
navigatable.setSourcePosition(XsltSourcePosition.create(myNode));
}
@Override
public void computePresentation(@NotNull XValueNode node, @NotNull XValuePlace place) {
node.setPresentation(null, "node", myNode.myStringValue, false);
}
}
}
private static class MyEvaluator extends XDebuggerEvaluator {
private final Debugger.StyleFrame myFrame;
public MyEvaluator(Debugger.StyleFrame frame) {
myFrame = frame;
}
@Override
public boolean isCodeFragmentEvaluationSupported() {
return false;
}
@Override
public void evaluate(@NotNull String expression, @NotNull XEvaluationCallback callback, @Nullable XSourcePosition expressionPosition) {
try {
final Value eval = myFrame.eval(expression);
callback.evaluated(new MyValue(new ExpressionResult(eval)));
} catch (VMPausedException ignored) {
callback.errorOccurred(VMPausedException.MESSAGE);
} catch (Debugger.EvaluationException e) {
callback.errorOccurred(e.getMessage() != null ? e.getMessage() : e.toString());
}
}
private static class ExpressionResult implements Debugger.Variable {
private final Value myValue;
public ExpressionResult(Value value) {
myValue = value;
}
@Override
@SuppressWarnings({ "ConstantConditions" })
public String getURI() {
return null;
}
@Override
public int getLineNumber() {
return -1;
}
@Override
public boolean isGlobal() {
return false;
}
@Override
public Kind getKind() {
return Kind.EXPRESSION;
}
@Override
public String getName() {
return "result";
}
@Override
public Value getValue() {
return myValue;
}
}
}
}