From c48c4d75a874a7d19cc0c14ba86754f5a71323b4 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Tue, 28 Apr 2015 14:55:31 +0300 Subject: [PATCH] IDEA-139741 Support position highlighting of exact lambda/method --- .../debugger/engine/PositionManagerImpl.java | 71 ++++++++++++++----- .../debugger/impl/DebuggerUtilsEx.java | 15 +++- .../impl/ui/ExecutionPointHighlighter.java | 21 ++++-- 3 files changed, 83 insertions(+), 24 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java index e1507093b103..d341409e98f7 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java @@ -26,11 +26,12 @@ import com.intellij.execution.filters.LineNumbersMapping; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.impl.DocumentMarkupModel; +import com.intellij.openapi.editor.markup.HighlighterTargetArea; +import com.intellij.openapi.editor.markup.RangeHighlighter; +import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.NullableComputable; -import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -38,6 +39,8 @@ import com.intellij.psi.search.FilenameIndex; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.containers.EmptyIterable; +import com.intellij.xdebugger.impl.ui.ExecutionPointHighlighter; +import com.intellij.xdebugger.ui.DebuggerColors; import com.sun.jdi.AbsentInformationException; import com.sun.jdi.Location; import com.sun.jdi.Method; @@ -179,7 +182,7 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio return new JavaSourcePosition(SourcePosition.createFromLine(psiFile, lineNumber), location.declaringType(), location.method()); } - private static class JavaSourcePosition extends RemappedSourcePosition { + private static class JavaSourcePosition extends RemappedSourcePosition implements ExecutionPointHighlighter.HighlighterProvider { private final String myExpectedClassName; private final String myExpectedMethodName; @@ -189,31 +192,63 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio myExpectedMethodName = method != null ? method.name() : null; } + private PsiElement remapElement(PsiElement element) { + PsiClass aClass = getEnclosingClass(element); + if (!Comparing.equal(myExpectedClassName, JVMNameUtil.getClassVMName(aClass))) { + return null; + } + NavigatablePsiElement method = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiLambdaExpression.class); + if (!StringUtil.isEmpty(myExpectedMethodName)) { + if (method == null) { + return null; + } + else if ((method instanceof PsiMethod && myExpectedMethodName.equals(((PsiMethod)method).getName()))) { + return element; + } + else if (method instanceof PsiLambdaExpression && myExpectedMethodName.startsWith(LambdaMethodFilter.LAMBDA_METHOD_PREFIX)) { + return ((PsiLambdaExpression)method).getBody(); + } + } + return null; + } + @Override public SourcePosition mapDelegate(final SourcePosition original) { return ApplicationManager.getApplication().runReadAction(new Computable() { @Override public SourcePosition compute() { // There may be more than one class/method code on the line, so we need to find out the correct place - int lineNumber = original.getLine(); - PsiElement element = original.getElementAt(); - PsiClass aClass = getEnclosingClass(element); - if (aClass != null) { - if (Comparing.equal(myExpectedClassName, JVMNameUtil.getClassVMName(aClass))) { - return original; - } - //try to look for other elements in the line - PsiFile file = original.getFile(); - for (PsiElement elem : getLineElements(file, lineNumber)) { - if (Comparing.equal(myExpectedClassName, JVMNameUtil.getClassVMName(getEnclosingClass(elem)))) { - return SourcePosition.createFromElement(elem); - } + for (PsiElement elem : getLineElements(original.getFile(), original.getLine())) { + PsiElement remappedElement = remapElement(elem); + if (remappedElement != null) { + if (remappedElement.getTextOffset() <= original.getOffset()) break; + return SourcePosition.createFromElement(remappedElement); } } return original; } }); } + + @Nullable + @Override + public RangeHighlighter createHighlighter(Document document, Project project, TextAttributes attributes) { + PsiElement element = getElementAt(); + NavigatablePsiElement method = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiLambdaExpression.class); + if (method instanceof PsiLambdaExpression) { + TextRange range = method.getTextRange(); + int startOffset = document.getLineStartOffset(getLine()); + int endOffset = document.getLineEndOffset(getLine()); + int hlStart = Math.max(startOffset, range.getStartOffset()); + int hlEnd = Math.min(endOffset, range.getEndOffset()); + if (hlStart != startOffset || hlEnd != endOffset) { + return DocumentMarkupModel.forDocument(document, project, true). + addRangeHighlighter(hlStart, hlEnd, DebuggerColors.EXECUTION_LINE_HIGHLIGHTERLAYER, attributes, + HighlighterTargetArea.EXACT_RANGE); + } + } + return null; + } } private static Iterable getLineElements(final PsiFile file, int lineNumber) { diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java index 6c23c7f317e0..02883527f75b 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java @@ -43,7 +43,10 @@ import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.markup.RangeHighlighter; +import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; @@ -62,6 +65,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.frame.XValueNode; import com.intellij.xdebugger.impl.XSourcePositionImpl; +import com.intellij.xdebugger.impl.ui.ExecutionPointHighlighter; import com.sun.jdi.*; import com.sun.jdi.event.Event; import com.sun.jdi.event.EventSet; @@ -696,7 +700,7 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils { return new JavaXSourcePosition(position, file); } - private static class JavaXSourcePosition implements XSourcePosition { + private static class JavaXSourcePosition implements XSourcePosition, ExecutionPointHighlighter.HighlighterProvider { private final SourcePosition mySourcePosition; @NotNull private final VirtualFile myFile; @@ -726,6 +730,15 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils { public Navigatable createNavigatable(@NotNull Project project) { return XSourcePositionImpl.doCreateOpenFileDescriptor(project, this); } + + @Nullable + @Override + public RangeHighlighter createHighlighter(Document document, Project project, TextAttributes attributes) { + if (mySourcePosition instanceof ExecutionPointHighlighter.HighlighterProvider) { + return ((ExecutionPointHighlighter.HighlighterProvider)mySourcePosition).createHighlighter(document, project, attributes); + } + return null; + } } /** diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.java index 6e33a76aecff..9c9fd8c24535 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/ExecutionPointHighlighter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ import com.intellij.openapi.editor.impl.DocumentMarkupModel; import com.intellij.openapi.editor.impl.EditorImpl; import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.editor.markup.RangeHighlighter; +import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; @@ -195,10 +196,15 @@ public class ExecutionPointHighlighter { if (myRangeHighlighter != null) return; EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme(); - myRangeHighlighter = DocumentMarkupModel.forDocument(document, myProject, true).addLineHighlighter(line, DebuggerColors.EXECUTION_LINE_HIGHLIGHTERLAYER, - myNotTopFrame - ? scheme.getAttributes(DebuggerColors.NOT_TOP_FRAME_ATTRIBUTES) - : scheme.getAttributes(DebuggerColors.EXECUTIONPOINT_ATTRIBUTES)); + TextAttributes attributes = myNotTopFrame ? scheme.getAttributes(DebuggerColors.NOT_TOP_FRAME_ATTRIBUTES) + : scheme.getAttributes(DebuggerColors.EXECUTIONPOINT_ATTRIBUTES); + if (mySourcePosition instanceof HighlighterProvider) { + myRangeHighlighter = ((HighlighterProvider)mySourcePosition).createHighlighter(document, myProject, attributes); + } + if (myRangeHighlighter == null) { + myRangeHighlighter = DocumentMarkupModel.forDocument(document, myProject, true). + addLineHighlighter(line, DebuggerColors.EXECUTION_LINE_HIGHLIGHTERLAYER, attributes); + } myRangeHighlighter.putUserData(EXECUTION_POINT_HIGHLIGHTER_KEY, true); myRangeHighlighter.setGutterIconRenderer(myGutterIconRenderer); } @@ -217,4 +223,9 @@ public class ExecutionPointHighlighter { } }); } + + public interface HighlighterProvider { + @Nullable + RangeHighlighter createHighlighter(Document document, Project project, TextAttributes attributes); + } }