use of com.intellij.util.ThreeState in project intellij-community by JetBrains.
the class Breakpoint method evaluateCondition.
public boolean evaluateCondition(final EvaluationContextImpl context, LocatableEvent event) throws EvaluateException {
DebugProcessImpl debugProcess = context.getDebugProcess();
if (isCountFilterEnabled() && !isConditionEnabled()) {
debugProcess.getVirtualMachineProxy().suspend();
debugProcess.getRequestsManager().deleteRequest(this);
createRequest(debugProcess);
debugProcess.getVirtualMachineProxy().resume();
}
if (isInstanceFiltersEnabled()) {
Value value = context.getThisObject();
if (value != null) {
// non-static
ObjectReference reference = (ObjectReference) value;
if (!hasObjectID(reference.uniqueID())) {
return false;
}
}
}
if (isClassFiltersEnabled() && !typeMatchesClassFilters(calculateEventClass(context, event), getClassFilters(), getClassExclusionFilters())) {
return false;
}
if (isConditionEnabled()) {
TextWithImports condition = getCondition();
if (condition.isEmpty()) {
return true;
}
StackFrameProxyImpl frame = context.getFrameProxy();
if (frame != null) {
Location location = frame.location();
if (location != null) {
ThreeState result = debugProcess.getPositionManager().evaluateCondition(context, frame, location, condition.getText());
if (result != ThreeState.UNSURE) {
return result == ThreeState.YES;
}
}
}
try {
SourcePosition contextSourcePosition = ContextUtil.getSourcePosition(context);
ExpressionEvaluator evaluator = DebuggerInvocationUtil.commitAndRunReadAction(myProject, () -> {
// IMPORTANT: calculate context psi element basing on the location where the exception
// has been hit, not on the location where it was set. (For line breakpoints these locations are the same, however,
// for method, exception and field breakpoints these locations differ)
PsiElement contextElement = ContextUtil.getContextElement(contextSourcePosition);
// as a last resort
PsiElement contextPsiElement = contextElement != null ? contextElement : getEvaluationElement();
return EvaluatorCache.cacheOrGet("ConditionEvaluator", event.request(), contextPsiElement, condition, () -> createExpressionEvaluator(myProject, contextPsiElement, contextSourcePosition, condition, this::createConditionCodeFragment));
});
if (!DebuggerUtilsEx.evaluateBoolean(evaluator, context)) {
return false;
}
} catch (EvaluateException ex) {
if (ex.getCause() instanceof VMDisconnectedException) {
return false;
}
throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("error.failed.evaluating.breakpoint.condition", condition, ex.getMessage()));
}
}
if (isCountFilterEnabled() && isConditionEnabled()) {
Long hitCount = ObjectUtils.notNull((Long) event.request().getProperty(HIT_COUNTER), 0L) + 1;
event.request().putProperty(HIT_COUNTER, hitCount);
return hitCount % getCountFilter() == 0;
}
return true;
}
use of com.intellij.util.ThreeState 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.util.ThreeState in project intellij-community by JetBrains.
the class MethodCandidateInfo method isPotentiallyCompatible.
/**
* 15.12.2.1 Identify Potentially Applicable Methods
*/
public ThreeState isPotentiallyCompatible() {
if (myArgumentList instanceof PsiExpressionList) {
final PsiMethod method = getElement();
final PsiParameter[] parameters = method.getParameterList().getParameters();
final PsiExpression[] expressions = ((PsiExpressionList) myArgumentList).getExpressions();
if (!isVarargs() && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
if (expressions.length != parameters.length) {
return ThreeState.NO;
}
} else {
if (expressions.length < parameters.length - 1) {
return ThreeState.NO;
}
if (parameters.length == 0 && expressions.length != parameters.length) {
return ThreeState.NO;
}
}
boolean unsure = false;
for (int i = 0; i < expressions.length; i++) {
final PsiExpression expression = expressions[i];
PsiType formalParameterType = i < parameters.length ? parameters[i].getType() : parameters[parameters.length - 1].getType();
if (formalParameterType instanceof PsiEllipsisType && isVarargs()) {
formalParameterType = ((PsiEllipsisType) formalParameterType).getComponentType();
}
ThreeState compatible = isPotentialCompatible(expression, getSiteSubstitutor().substitute(formalParameterType), method);
if (compatible == ThreeState.NO) {
return ThreeState.NO;
}
if (compatible == ThreeState.UNSURE) {
unsure = true;
}
}
if (unsure)
return ThreeState.UNSURE;
if (method.hasTypeParameters() && myTypeArguments != null) {
//todo
return ThreeState.fromBoolean(method.getTypeParameters().length == myTypeArguments.length);
}
}
return ThreeState.YES;
}
use of com.intellij.util.ThreeState in project intellij-community by JetBrains.
the class MethodCandidateInfo method isPotentialCompatible.
private static ThreeState isPotentialCompatible(PsiExpression expression, PsiType formalType, PsiMethod method) {
if (expression instanceof PsiFunctionalExpression) {
final PsiClass targetTypeParameter = PsiUtil.resolveClassInClassTypeOnly(formalType);
if (targetTypeParameter instanceof PsiTypeParameter && method.equals(((PsiTypeParameter) targetTypeParameter).getOwner())) {
return ThreeState.YES;
}
if (!LambdaUtil.isFunctionalType(formalType)) {
return ThreeState.NO;
}
if (!((PsiFunctionalExpression) expression).isPotentiallyCompatible(formalType)) {
return ThreeState.UNSURE;
}
} else if (expression instanceof PsiParenthesizedExpression) {
return isPotentialCompatible(((PsiParenthesizedExpression) expression).getExpression(), formalType, method);
} else if (expression instanceof PsiConditionalExpression) {
ThreeState thenCompatible = isPotentialCompatible(((PsiConditionalExpression) expression).getThenExpression(), formalType, method);
ThreeState elseCompatible = isPotentialCompatible(((PsiConditionalExpression) expression).getElseExpression(), formalType, method);
if (thenCompatible == ThreeState.NO || elseCompatible == ThreeState.NO) {
return ThreeState.NO;
}
if (thenCompatible == ThreeState.UNSURE || elseCompatible == ThreeState.UNSURE) {
return ThreeState.UNSURE;
}
}
return ThreeState.YES;
}
use of com.intellij.util.ThreeState in project intellij-community by JetBrains.
the class FileUtilLightTest method testCheckImmediateChildren.
@Test
public void testCheckImmediateChildren() {
String root = "/a";
String[] data = { "/a/b/c", "/a", "/a/b", "/d/e", "/b/c", "/a/d", "/a/b/c/d/e" };
ThreeState[] expected1 = { ThreeState.UNSURE, ThreeState.YES, ThreeState.YES, ThreeState.NO, ThreeState.NO, ThreeState.YES, ThreeState.UNSURE };
ThreeState[] expected2 = { ThreeState.UNSURE, ThreeState.NO, ThreeState.YES, ThreeState.NO, ThreeState.NO, ThreeState.YES, ThreeState.UNSURE };
for (int i = 0; i < data.length; i++) {
ThreeState state = FileUtil.isAncestorThreeState(root, data[i], false);
assertEquals(String.valueOf(i), expected1[i], state);
}
for (int i = 0; i < data.length; i++) {
ThreeState state = FileUtil.isAncestorThreeState(root, data[i], true);
assertEquals(String.valueOf(i), expected2[i], state);
}
}
Aggregations