IDEA-136666 Inline debugger: parameters values are not sorted and don't follow declar...
authorEgor.Ushakov <egor.ushakov@jetbrains.com>
Fri, 29 May 2015 16:16:52 +0000 (19:16 +0300)
committerEgor.Ushakov <egor.ushakov@jetbrains.com>
Fri, 29 May 2015 16:18:48 +0000 (19:18 +0300)
java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextUtil.java
platform/xdebugger-api/src/com/intellij/xdebugger/frame/XInlineDebuggerDataCallback.java
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesViewBase.java
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java

index 19ec5f071b038708b95f422b8d73b8fc42861541..fb411b4c6318e7ec113e1703146b004f4ae76a49 100644 (file)
@@ -90,17 +90,19 @@ public class DebuggerContextUtil {
             ranges.addAll(usages.second);
             final int breakPointLine = position.getLine();
             int bestLine = -1;
-            boolean hasSameLine = false;
+            int bestOffset = -1;
             for (TextRange range : ranges) {
               final int line = editor.offsetToLogicalPosition(range.getStartOffset()).line;
               if (line > bestLine && line < breakPointLine) {
                 bestLine = line;
+                bestOffset = range.getStartOffset();
               } else if (line == breakPointLine) {
-                hasSameLine = true;
+                bestOffset = range.getStartOffset();
+                break;
               }
             }
-            if (bestLine > -1) {
-              return SourcePosition.createFromLine(file, hasSameLine ? breakPointLine : bestLine);
+            if (bestOffset > -1) {
+              return SourcePosition.createFromOffset(file, bestOffset);
             }
           }
         }
index 1227370877ee4009c665e8479d4102d3fd8b15ff..1f6ce2d854bfabb9639d6530cd2e396fd479a6d0 100644 (file)
@@ -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.
@@ -17,8 +17,18 @@ package com.intellij.xdebugger.frame;
 
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.xdebugger.XDebuggerUtil;
+import com.intellij.xdebugger.XSourcePosition;
 import org.jetbrains.annotations.NotNull;
 
 public abstract class XInlineDebuggerDataCallback {
-  public abstract void computed(@NotNull VirtualFile file, @NotNull Document document, int line);
+  /**
+   * @deprecated use {@link #computed(XSourcePosition)} instead
+   */
+  @Deprecated
+  public void computed(@NotNull VirtualFile file, @SuppressWarnings("UnusedParameters") @NotNull Document document, int line) {
+    computed(XDebuggerUtil.getInstance().createPosition(file, line));
+  }
+
+  public abstract void computed(XSourcePosition position);
 }
\ No newline at end of file
index 01821a3be2307d869af35e92213e60db73319731..f6bbb646c4b95e1fab2ade4b3e6fd6e5224ad2e4 100644 (file)
@@ -23,7 +23,6 @@ import com.intellij.openapi.editor.markup.TextAttributes;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -40,6 +39,7 @@ import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
 import com.intellij.xdebugger.impl.ui.tree.nodes.XValueTextRendererImpl;
 import com.intellij.xdebugger.ui.DebuggerColors;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.awt.*;
 import java.util.*;
@@ -60,11 +60,11 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter {
       return null;
     }
 
-    final Map<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>> map = project.getUserData(XVariablesView.DEBUG_VARIABLES);
+    XVariablesView.InlineVariablesInfo data = project.getUserData(XVariablesView.DEBUG_VARIABLES);
     final ObjectLongHashMap<VirtualFile> timestamps = project.getUserData(XVariablesView.DEBUG_VARIABLES_TIMESTAMPS);
     final Document doc = FileDocumentManager.getInstance().getDocument(file);
 
-    if (map == null || timestamps == null || doc == null) {
+    if (data == null || timestamps == null || doc == null) {
       return null;
     }
 
@@ -77,9 +77,13 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter {
     if (timestamp == -1 || timestamp < doc.getModificationStamp()) {
       return null;
     }
-    Set<XValueNodeImpl> values = map.get(Pair.create(file, lineNumber));
+    List<XValueNodeImpl> values = data.get(file, lineNumber);
     if (values != null && !values.isEmpty()) {
-      final int bpLine = getCurrentBreakPointLineInFile(values, file);
+      XDebugSession session = XDebugView.getSession(values.iterator().next().getTree());
+      final int bpLine = getCurrentBreakPointLineInFile(session, file);
+      boolean isTopFrame = session instanceof XDebugSessionImpl && ((XDebugSessionImpl)session).isTopFrameSelected();
+      final TextAttributes attributes = bpLine == lineNumber && isTopFrame ? getTopFrameSelectedAttributes() : getNormalAttributes();
+
       ArrayList<VariableText> result = new ArrayList<VariableText>();
       for (XValueNodeImpl value : values) {
         SimpleColoredText text = new SimpleColoredText();
@@ -103,9 +107,6 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter {
         catch (Exception ignored) {
           continue;
         }
-        XDebugSession session = XDebugView.getSession(values.iterator().next().getTree());
-        boolean isTopFrame = session instanceof XDebugSessionImpl && ((XDebugSessionImpl)session).isTopFrameSelected();
-        final TextAttributes attributes = bpLine == lineNumber && isTopFrame ? getTopFrameSelectedAttributes() : getNormalAttributes();
 
         final String name = value.getName();
         if (StringUtil.isEmpty(text.toString())) {
@@ -136,12 +137,6 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter {
           variableValue.produceChangedParts(res.infos);
         }
       }
-      Collections.sort(result, new Comparator<VariableText>() {
-        @Override
-        public int compare(VariableText o1, VariableText o2) {
-          return o1.length - o2.length;
-        }
-      });
       final List<LineExtensionInfo> infos = new ArrayList<LineExtensionInfo>();
       for (VariableText text : result) {
         infos.addAll(text.infos);
@@ -151,10 +146,8 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter {
     return null;
   }
 
-  private static int getCurrentBreakPointLineInFile(Set<XValueNodeImpl> values, VirtualFile file) {
+  private static int getCurrentBreakPointLineInFile(@Nullable XDebugSession session, VirtualFile file) {
     try {
-      final XValueNodeImpl node = values.iterator().next();
-      final XDebugSession session = XDebugView.getSession(node.getTree());
       if (session != null) {
         final XSourcePosition position = session.getCurrentPosition();
         if (position != null && position.getFile().equals(file)) {
index 4b5a5f8bca3e7075b2aa945ab24d8ceeb76304cc..637f71ad105d400a7b94ed51cf55f8da786947e7 100644 (file)
  */
 package com.intellij.xdebugger.impl.frame;
 
+import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Key;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.containers.ObjectLongHashMap;
 import com.intellij.xdebugger.XDebugProcess;
 import com.intellij.xdebugger.XDebugSession;
+import com.intellij.xdebugger.XSourcePosition;
 import com.intellij.xdebugger.frame.XStackFrame;
 import com.intellij.xdebugger.impl.XDebugSessionImpl;
 import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
 import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode;
 import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
+import gnu.trove.THashMap;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 
 import static com.intellij.xdebugger.impl.ui.tree.nodes.MessageTreeNode.createInfoMessage;
 
@@ -37,7 +45,7 @@ import static com.intellij.xdebugger.impl.ui.tree.nodes.MessageTreeNode.createIn
  * @author nik
  */
 public class XVariablesView extends XVariablesViewBase {
-  public static final Key<Map<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>>> DEBUG_VARIABLES = Key.create("debug.variables");
+  public static final Key<InlineVariablesInfo> DEBUG_VARIABLES = Key.create("debug.variables");
   public static final Key<ObjectLongHashMap<VirtualFile>> DEBUG_VARIABLES_TIMESTAMPS = Key.create("debug.variables.timestamps");
 
   public XVariablesView(@NotNull XDebugSessionImpl session) {
@@ -96,4 +104,54 @@ public class XVariablesView extends XVariablesViewBase {
     }
     tree.setRoot(node, true);
   }
+
+  public static class InlineVariablesInfo {
+    private final Map<Pair<VirtualFile, Integer>, Set<Entry>> myData
+      = new THashMap<Pair<VirtualFile, Integer>, Set<Entry>>();
+
+    @Nullable
+    public List<XValueNodeImpl> get(VirtualFile file, int line) {
+      synchronized (myData) {
+        Set<Entry> entries = myData.get(Pair.create(file, line));
+        if (entries == null) return null;
+        return ContainerUtil.map(entries, new Function<Entry, XValueNodeImpl>() {
+          @Override
+          public XValueNodeImpl fun(Entry entry) {
+            return entry.myNode;
+          }
+        });
+      }
+    }
+
+    public void put(VirtualFile file, XSourcePosition position, XValueNodeImpl node) {
+      synchronized (myData) {
+        Pair<VirtualFile, Integer> key = Pair.create(file, position.getLine());
+        Set<Entry> entries = myData.get(key);
+        if (entries == null) {
+          entries = new TreeSet<Entry>();
+          myData.put(key, entries);
+        }
+        entries.add(new Entry(position.getOffset(), node));
+      }
+    }
+
+    private static class Entry implements Comparable<Entry> {
+      private final long myOffset;
+      private final XValueNodeImpl myNode;
+
+      public Entry(long offset, XValueNodeImpl node) {
+        myOffset = offset;
+        myNode = node;
+      }
+
+      @Override
+      public int compareTo(Entry o) {
+        int res = Comparing.compare(myOffset, o.myOffset);
+        if (res == 0) {
+          return XValueNodeImpl.COMPARATOR.compare(myNode, o.myNode);
+        }
+        return res;
+      }
+    }
+  }
 }
index ef1e1c5048a522660bf5efa44b73b068fba32542..c8528c62670c568e9e625a78ccb39992cba36272 100644 (file)
@@ -24,7 +24,6 @@ import com.intellij.openapi.fileEditor.FileEditor;
 import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
 import com.intellij.openapi.fileEditor.impl.text.PsiAwareTextEditorImpl;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
@@ -45,14 +44,11 @@ import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel;
 import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeRestorer;
 import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeState;
 import com.intellij.xdebugger.impl.ui.tree.nodes.XStackFrameNode;
-import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
-import gnu.trove.THashMap;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import java.awt.*;
-import java.util.Set;
 
 /**
  * @author nik
@@ -76,7 +72,7 @@ public abstract class XVariablesViewBase extends XDebugView {
     tree.setSourcePosition(position);
     tree.setRoot(new XStackFrameNode(tree, stackFrame), false);
     final Project project = tree.getProject();
-    project.putUserData(XVariablesView.DEBUG_VARIABLES, new THashMap<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>>());
+    project.putUserData(XVariablesView.DEBUG_VARIABLES, new XVariablesView.InlineVariablesInfo());
     project.putUserData(XVariablesView.DEBUG_VARIABLES_TIMESTAMPS, new ObjectLongHashMap<VirtualFile>());
     Object newEqualityObject = stackFrame.getEqualityObject();
     if (myFrameEqualityObject != null && newEqualityObject != null && myFrameEqualityObject.equals(newEqualityObject)
index dc638dc682fdcccec673f57ee817a880a555cbf7..a652a9effb8f00c11825b6087391017d018835fc 100644 (file)
@@ -18,8 +18,6 @@ package com.intellij.xdebugger.impl.ui.tree.nodes;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.registry.Registry;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -47,9 +45,6 @@ import org.jetbrains.annotations.Nullable;
 import javax.swing.*;
 import java.awt.event.MouseEvent;
 import java.util.Comparator;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
 
 /**
  * @author nik
@@ -151,21 +146,21 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
 
       final XInlineDebuggerDataCallback callback = new XInlineDebuggerDataCallback() {
         @Override
-        public void computed(@NotNull VirtualFile file, @NotNull Document document, int line) {
-          final Map<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>> map = myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES);
+        public void computed(XSourcePosition position) {
+          if (position == null) return;
+          VirtualFile file = position.getFile();
+          final Document document = FileDocumentManager.getInstance().getDocument(file);
+          if (document == null) return;
+
+          XVariablesView.InlineVariablesInfo data = myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES);
           final TObjectLongHashMap<VirtualFile> timestamps = myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES_TIMESTAMPS);
-          if (map == null || timestamps == null) {
+          if (data == null || timestamps == null) {
             return;
           }
 
-          Pair<VirtualFile, Integer> key = Pair.create(file, line);
-          Set<XValueNodeImpl> presentations = new LinkedHashSet<XValueNodeImpl>();
-          Set<XValueNodeImpl> old = map.put(key, presentations);
+          data.put(file, position, XValueNodeImpl.this);
           timestamps.put(file, document.getModificationStamp());
-          presentations.add(XValueNodeImpl.this);
-          if (old != null) {
-            presentations.addAll(old);
-          }
+
           myTree.updateEditor();
         }
       };
@@ -174,16 +169,7 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
         class ValueDeclaration implements XInlineSourcePosition {
           @Override
           public void setSourcePosition(@Nullable XSourcePosition sourcePosition) {
-            final Map<Pair<VirtualFile, Integer>, Set<XValueNodeImpl>> map =
-              myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES);
-            final TObjectLongHashMap<VirtualFile> timestamps = myTree.getProject().getUserData(XVariablesView.DEBUG_VARIABLES_TIMESTAMPS);
-            if (map == null || timestamps == null || sourcePosition == null) return;
-            VirtualFile file = sourcePosition.getFile();
-            if (!Comparing.equal(debuggerPosition.getFile(), sourcePosition.getFile())) return;
-            final Document doc = FileDocumentManager.getInstance().getDocument(file);
-            if (doc == null) return;
-            int line = sourcePosition.getLine();
-            callback.computed(file, doc, line);
+            callback.computed(sourcePosition);
           }
         }
         class NearestValuePosition extends ValueDeclaration implements XNearestSourcePosition {}