use of com.intellij.debugger.engine.evaluation.EvaluateException in project intellij-community by JetBrains.
the class JavaSmartStepIntoHandler method findSmartStepTargets.
protected List<SmartStepTarget> findSmartStepTargets(final SourcePosition position, @Nullable SuspendContextImpl suspendContext, @NotNull DebuggerContextImpl debuggerContext) {
final int line = position.getLine();
if (line < 0) {
// the document has been changed
return Collections.emptyList();
}
final PsiFile file = position.getFile();
final VirtualFile vFile = file.getVirtualFile();
if (vFile == null) {
// the file is not physical
return Collections.emptyList();
}
final Document doc = FileDocumentManager.getInstance().getDocument(vFile);
if (doc == null)
return Collections.emptyList();
if (line >= doc.getLineCount()) {
// the document has been changed
return Collections.emptyList();
}
TextRange curLineRange = DocumentUtil.getLineTextRange(doc, line);
PsiElement element = position.getElementAt();
PsiElement body = DebuggerUtilsEx.getBody(DebuggerUtilsEx.getContainingMethod(element));
final TextRange lineRange = (body != null) ? curLineRange.intersection(body.getTextRange()) : curLineRange;
if (lineRange == null || lineRange.isEmpty()) {
return Collections.emptyList();
}
if (element != null && !(element instanceof PsiCompiledElement)) {
do {
final PsiElement parent = element.getParent();
if (parent == null || (parent.getTextOffset() < lineRange.getStartOffset())) {
break;
}
element = parent;
} while (true);
//noinspection unchecked
final List<SmartStepTarget> targets = new OrderedSet<>();
final Ref<TextRange> textRange = new Ref<>(lineRange);
final PsiElementVisitor methodCollector = new JavaRecursiveElementVisitor() {
final Deque<PsiMethod> myContextStack = new LinkedList<>();
final Deque<String> myParamNameStack = new LinkedList<>();
private int myNextLambdaExpressionOrdinal = 0;
private boolean myInsideLambda = false;
@Nullable
private String getCurrentParamName() {
return myParamNameStack.peekFirst();
}
@Override
public void visitAnonymousClass(PsiAnonymousClass aClass) {
for (PsiMethod psiMethod : aClass.getMethods()) {
targets.add(0, new MethodSmartStepTarget(psiMethod, getCurrentParamName(), psiMethod.getBody(), true, null));
}
}
public void visitLambdaExpression(PsiLambdaExpression expression) {
boolean inLambda = myInsideLambda;
myInsideLambda = true;
super.visitLambdaExpression(expression);
myInsideLambda = inLambda;
targets.add(0, new LambdaSmartStepTarget(expression, getCurrentParamName(), expression.getBody(), myNextLambdaExpressionOrdinal++, null, !myInsideLambda));
}
@Override
public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
PsiElement element = expression.resolve();
if (element instanceof PsiMethod) {
PsiElement navMethod = element.getNavigationElement();
if (navMethod instanceof PsiMethod) {
targets.add(0, new MethodSmartStepTarget(((PsiMethod) navMethod), null, expression, true, null));
}
}
}
@Override
public void visitField(PsiField field) {
if (checkTextRange(field, false)) {
super.visitField(field);
}
}
@Override
public void visitMethod(PsiMethod method) {
if (checkTextRange(method, false)) {
super.visitMethod(method);
}
}
@Override
public void visitStatement(PsiStatement statement) {
if (checkTextRange(statement, true)) {
super.visitStatement(statement);
}
}
@Override
public void visitIfStatement(PsiIfStatement statement) {
visitConditional(statement.getCondition(), statement.getThenBranch(), statement.getElseBranch());
}
@Override
public void visitConditionalExpression(PsiConditionalExpression expression) {
visitConditional(expression.getCondition(), expression.getThenExpression(), expression.getElseExpression());
}
private void visitConditional(@Nullable PsiElement condition, @Nullable PsiElement thenBranch, @Nullable PsiElement elseBranch) {
if (condition != null && checkTextRange(condition, true)) {
condition.accept(this);
}
ThreeState conditionRes = evaluateCondition(condition);
if (conditionRes != ThreeState.NO && thenBranch != null && checkTextRange(thenBranch, true)) {
thenBranch.accept(this);
}
if (conditionRes != ThreeState.YES && elseBranch != null && checkTextRange(elseBranch, true)) {
elseBranch.accept(this);
}
}
private ThreeState evaluateCondition(@Nullable PsiElement condition) {
if (condition != null && !DebuggerUtils.hasSideEffects(condition)) {
try {
ExpressionEvaluator evaluator = EvaluatorBuilderImpl.getInstance().build(condition, position);
return ThreeState.fromBoolean(DebuggerUtilsEx.evaluateBoolean(evaluator, debuggerContext.createEvaluationContext()));
} catch (EvaluateException e) {
LOG.info(e);
}
}
return ThreeState.UNSURE;
}
@Override
public void visitExpression(PsiExpression expression) {
checkTextRange(expression, true);
super.visitExpression(expression);
}
boolean checkTextRange(@NotNull PsiElement expression, boolean expand) {
TextRange range = expression.getTextRange();
if (lineRange.intersects(range)) {
if (expand) {
textRange.set(textRange.get().union(range));
}
return true;
}
return false;
}
public void visitExpressionList(PsiExpressionList expressionList) {
PsiMethod psiMethod = myContextStack.peekFirst();
if (psiMethod != null) {
final String methodName = psiMethod.getName();
final PsiExpression[] expressions = expressionList.getExpressions();
final PsiParameter[] parameters = psiMethod.getParameterList().getParameters();
for (int idx = 0; idx < expressions.length; idx++) {
final String paramName = (idx < parameters.length && !parameters[idx].isVarArgs()) ? parameters[idx].getName() : "arg" + (idx + 1);
myParamNameStack.push(methodName + ": " + paramName + ".");
final PsiExpression argExpression = expressions[idx];
try {
argExpression.accept(this);
} finally {
myParamNameStack.pop();
}
}
} else {
super.visitExpressionList(expressionList);
}
}
@Override
public void visitCallExpression(final PsiCallExpression expression) {
final PsiMethod psiMethod = expression.resolveMethod();
if (psiMethod != null) {
myContextStack.push(psiMethod);
targets.add(new MethodSmartStepTarget(psiMethod, null, expression instanceof PsiMethodCallExpression ? ((PsiMethodCallExpression) expression).getMethodExpression().getReferenceNameElement() : expression instanceof PsiNewExpression ? ((PsiNewExpression) expression).getClassOrAnonymousClassReference() : expression, myInsideLambda, null));
}
try {
super.visitCallExpression(expression);
} finally {
if (psiMethod != null) {
myContextStack.pop();
}
}
}
};
element.accept(methodCollector);
for (PsiElement sibling = element.getNextSibling(); sibling != null; sibling = sibling.getNextSibling()) {
if (!lineRange.intersects(sibling.getTextRange())) {
break;
}
sibling.accept(methodCollector);
}
Range<Integer> lines = new Range<>(doc.getLineNumber(textRange.get().getStartOffset()), doc.getLineNumber(textRange.get().getEndOffset()));
targets.forEach(t -> t.setCallingExpressionLines(lines));
if (!targets.isEmpty()) {
StackFrameProxyImpl frameProxy = suspendContext != null ? suspendContext.getFrameProxy() : null;
if (frameProxy != null) {
try {
Location location = frameProxy.location();
MethodBytecodeUtil.visit(location.method(), location.codeIndex(), new MethodVisitor(Opcodes.API_VERSION) {
boolean myLineMatch = false;
@Override
public void visitLineNumber(int line, Label start) {
myLineMatch = lines.isWithin(line - 1);
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (myLineMatch) {
targets.removeIf(t -> {
if (t instanceof MethodSmartStepTarget) {
return DebuggerUtilsEx.methodMatches(((MethodSmartStepTarget) t).getMethod(), owner.replace("/", "."), name, desc, suspendContext.getDebugProcess());
}
return false;
});
}
}
}, true);
} catch (Exception e) {
LOG.info(e);
}
}
return targets;
}
}
return Collections.emptyList();
}
use of com.intellij.debugger.engine.evaluation.EvaluateException in project intellij-community by JetBrains.
the class ContextUtil method getContextElement.
@Nullable
public static PsiElement getContextElement(final StackFrameContext context, final SourcePosition position) {
if (LOG.isDebugEnabled()) {
final SourcePosition sourcePosition = getSourcePosition(context);
LOG.assertTrue(Comparing.equal(sourcePosition, position));
}
return ReadAction.compute(() -> {
final PsiElement element = getContextElement(position);
if (element == null) {
return null;
}
// further code is java specific, actually
if (element.getLanguage().getAssociatedFileType() != DefaultCodeFragmentFactory.getInstance().getFileType()) {
return element;
}
final StackFrameProxyImpl frameProxy = (StackFrameProxyImpl) context.getFrameProxy();
if (frameProxy == null) {
return element;
}
try {
List<LocalVariableProxyImpl> list = frameProxy.visibleVariables();
PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(element.getProject()).getResolveHelper();
StringBuilder buf = null;
for (LocalVariableProxyImpl localVariable : list) {
final String varName = localVariable.name();
if (resolveHelper.resolveReferencedVariable(varName, element) == null) {
if (buf == null) {
buf = new StringBuilder("{");
}
buf.append(localVariable.getVariable().typeName()).append(" ").append(varName).append(";");
}
}
if (buf == null) {
return element;
}
buf.append('}');
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(element.getProject()).getElementFactory();
final PsiCodeBlock codeBlockFromText = elementFactory.createCodeBlockFromText(buf.toString(), element);
final PsiStatement[] statements = codeBlockFromText.getStatements();
for (PsiStatement statement : statements) {
if (statement instanceof PsiDeclarationStatement) {
PsiDeclarationStatement declStatement = (PsiDeclarationStatement) statement;
PsiElement[] declaredElements = declStatement.getDeclaredElements();
for (PsiElement declaredElement : declaredElements) {
declaredElement.putUserData(IS_JSP_IMPLICIT, Boolean.TRUE);
}
}
}
return codeBlockFromText;
} catch (IncorrectOperationException | EvaluateException ignored) {
return element;
}
});
}
use of com.intellij.debugger.engine.evaluation.EvaluateException in project intellij-community by JetBrains.
the class ForceEarlyReturnAction method actionPerformed.
public void actionPerformed(@NotNull AnActionEvent e) {
final Project project = e.getProject();
final JavaStackFrame stackFrame = PopFrameAction.getStackFrame(e);
if (stackFrame == null || project == null) {
return;
}
final DebuggerContextImpl debuggerContext = DebuggerAction.getDebuggerContext(e.getDataContext());
final DebugProcessImpl debugProcess = debuggerContext.getDebugProcess();
if (debugProcess == null) {
return;
}
final StackFrameProxyImpl proxy = stackFrame.getStackFrameProxy();
final ThreadReferenceProxyImpl thread = proxy.threadProxy();
debugProcess.getManagerThread().schedule(new DebuggerContextCommandImpl(debuggerContext, thread) {
@Override
public void threadAction() {
Method method;
try {
method = proxy.location().method();
} catch (EvaluateException e) {
showError(project, DebuggerBundle.message("error.early.return", e.getLocalizedMessage()));
return;
}
if ("void".equals(method.returnTypeName())) {
forceEarlyReturnWithFinally(thread.getVirtualMachine().mirrorOfVoid(), stackFrame, debugProcess, null);
} else {
ApplicationManager.getApplication().invokeLater(() -> new ReturnExpressionDialog(project, debugProcess.getXdebugProcess().getEditorsProvider(), debugProcess, stackFrame).show());
}
}
});
}
use of com.intellij.debugger.engine.evaluation.EvaluateException in project intellij-community by JetBrains.
the class BatchEvaluator method doEvaluateBatch.
@SuppressWarnings({ "HardCodedStringLiteral" })
private boolean doEvaluateBatch(List<ToStringCommand> requests, EvaluationContext evaluationContext) {
try {
DebugProcess debugProcess = evaluationContext.getDebugProcess();
List<Value> values = new ArrayList<>();
for (ToStringCommand toStringCommand : requests) {
Value value = toStringCommand.getValue();
values.add(value instanceof ObjectReference ? ((ObjectReference) value) : value);
}
ArrayType objectArrayClass = (ArrayType) debugProcess.findClass(evaluationContext, "java.lang.Object[]", evaluationContext.getClassLoader());
if (objectArrayClass == null) {
return false;
}
ArrayReference argArray = debugProcess.newInstance(objectArrayClass, values.size());
// to avoid ObjectCollectedException
((SuspendContextImpl) evaluationContext.getSuspendContext()).keep(argArray);
argArray.setValues(values);
List argList = new ArrayList(1);
argList.add(argArray);
Value value = debugProcess.invokeMethod(evaluationContext, myBatchEvaluatorObject, myBatchEvaluatorMethod, argList);
if (value instanceof ArrayReference) {
// to avoid ObjectCollectedException for both the array and its elements
((SuspendContextImpl) evaluationContext.getSuspendContext()).keep((ArrayReference) value);
final ArrayReference strings = (ArrayReference) value;
final List<Value> allValuesArray = strings.getValues();
final Value[] allValues = allValuesArray.toArray(new Value[allValuesArray.size()]);
int idx = 0;
for (Iterator<ToStringCommand> iterator = requests.iterator(); iterator.hasNext(); idx++) {
ToStringCommand request = iterator.next();
final Value strValue = allValues[idx];
if (strValue == null || strValue instanceof StringReference) {
try {
String str = (strValue == null) ? null : ((StringReference) strValue).value();
request.evaluationResult(str);
} catch (ObjectCollectedException e) {
// ignored
}
} else if (strValue instanceof ObjectReference) {
request.evaluationError(EvaluateExceptionUtil.createEvaluateException(new InvocationException((ObjectReference) strValue)).getMessage());
} else {
LOG.assertTrue(false);
}
request.setEvaluated();
}
}
return true;
} catch (ClassNotLoadedException | ObjectCollectedException | EvaluateException | InvalidTypeException e) {
}
return false;
}
use of com.intellij.debugger.engine.evaluation.EvaluateException in project intellij-community by JetBrains.
the class BatchEvaluator method hasBatchEvaluator.
@SuppressWarnings({ "HardCodedStringLiteral" })
public boolean hasBatchEvaluator(EvaluationContext evaluationContext) {
if (!myBatchEvaluatorChecked) {
myBatchEvaluatorChecked = true;
if (DebuggerUtilsImpl.isRemote(myDebugProcess)) {
// optimization: for remote sessions the BatchEvaluator is not there for sure
return false;
}
ThreadReferenceProxy thread = evaluationContext.getSuspendContext().getThread();
if (thread == null) {
return false;
}
ThreadReference threadReference = thread.getThreadReference();
if (threadReference == null) {
return false;
}
ClassType batchEvaluatorClass = null;
try {
batchEvaluatorClass = (ClassType) myDebugProcess.findClass(evaluationContext, BatchEvaluatorServer.class.getName(), evaluationContext.getClassLoader());
} catch (EvaluateException e) {
}
if (batchEvaluatorClass != null) {
Method constructor = batchEvaluatorClass.concreteMethodByName(JVMNameUtil.CONSTRUCTOR_NAME, "()V");
if (constructor != null) {
ObjectReference evaluator = null;
try {
evaluator = myDebugProcess.newInstance(evaluationContext, batchEvaluatorClass, constructor, Collections.emptyList());
} catch (Exception e) {
LOG.debug(e);
}
myBatchEvaluatorObject = evaluator;
if (myBatchEvaluatorObject != null) {
myBatchEvaluatorMethod = batchEvaluatorClass.concreteMethodByName("evaluate", "([Ljava/lang/Object;)[Ljava/lang/Object;");
}
}
}
}
return myBatchEvaluatorMethod != null;
}
Aggregations