Repository: spyder-ide/spyder

Issue:
Don't show "No documentation available" tooltip on hover
## Problem Description

hold the mouse cursor over almost anything in the editor. a "No ducumentation available" tooltip will appear. which is extremely distracting and sometomes the tooltip will appear over other windows.

example code:
  ``` a = "Asd" ```
  hold cursor over the "Asd". the tooltip will appear.
This is not a helpfull tooltip, It appears all the time just by having the mouse cursor over almost anything in the editor
  
## Versions
(this is a spyder 4 problem)
4.0.1
(tested on two machines, one spyder 4.0.0 another 4.0.1)

Python 3.7.5 64-bit | Qt 5.9.6 | PyQt5 5.9.2 | Windows 10 
### Dependencies
```
cloudpickle >=0.5.0          :  1.2.2 (OK)
pygments >=2.0               :  2.4.2 (OK)
qtconsole >=4.6.0            :  4.6.0 (OK)
nbconvert >=4.0              :  5.6.1 (OK)
sphinx >=0.6.6               :  2.2.1 (OK)
pylint >=0.25                :  2.4.3 (OK)
psutil >=0.3                 :  5.6.3 (OK)
qtawesome >=0.5.7            :  0.6.0 (OK)
qtpy >=1.5.0                 :  1.9.0 (OK)
pickleshare >=0.4            :  0.7.5 (OK)
zmq >=17                     :  18.1.0 (OK)
chardet >=2.0.0              :  3.0.4 (OK)
numpydoc >=0.6.0             :  0.9.1 (OK)
spyder_kernels >=1.8.1;<2.0.0:  1.8.1 (OK)
qdarkstyle >=2.7             :  2.7 (OK)
atomicwrites >=1.2.0         :  1.3.0 (OK)
diff_match_patch >=20181111  :  20181111 (OK)
intervaltree                 :  None (OK)
watchdog                     :  None (OK)
keyring                      :  None (OK)
pexpect >=4.4.0              :  4.7.0 (OK)
pympler                      :  None (OK)
sympy >=0.7.3                :  None (NOK)
cython >=0.21                :  0.29.14 (OK)
IPython >=4.0                :  7.9.0 (OK)
matplotlib >=2.0.0           :  3.1.1 (OK)
pandas >=0.13.1              :  0.25.2 (OK)
numpy >=1.7                  :  1.17.3 (OK)
scipy >=0.17.0               :  1.3.1 (OK)
pyls >=0.31.2;<0.32.0        :  0.31.2 (OK)
rtree >=0.8.3                :  0.8.3 (OK)

```



Discussion:
I agree with your suggestion. @goanpeca, please take a look at this one.
I cannot reproduce this @ccordoba12 
@talkaminker, please post a screenshot of what you're seeing.

@dalthviz, can you reproduce this one on Windows?
@ccordoba12 I can't reproduce this. Maybe something else, besides the `a = "Asd"`, is needed?:

![hover](https://user-images.githubusercontent.com/16781833/72812258-30518600-3c2f-11ea-81d4-eb1ac519d61f.gif)

But there's the case of `paren_example` in your screenshot above, whose hover shouldn't be displayed because it's pointless.

@goanpeca, please take care of those cases for now.

Resolving patch:
diff --git a/spyder/plugins/editor/widgets/editor.py b/spyder/plugins/editor/widgets/editor.py
--- a/spyder/plugins/editor/widgets/editor.py
+++ b/spyder/plugins/editor/widgets/editor.py
@@ -2395,11 +2395,6 @@ def __modify_stack_title(self):
             state = finfo.editor.document().isModified()
             self.set_stack_title(index, state)
 
-    def __reset_tooltip(self):
-        """Reset tooltip tip info for all the editors."""
-        for index, finfo in enumerate(self.data):
-            finfo.editor.reset_tooltip()
-
     def refresh(self, index=None):
         """Refresh tabwidget"""
         if index is None:
@@ -2416,7 +2411,6 @@ def refresh(self, index=None):
             self.__refresh_readonly(index)
             self.__check_file_status(index)
             self.__modify_stack_title()
-            self.__reset_tooltip()
             self.update_plugin_title.emit()
         else:
             editor = None
diff --git a/spyder/widgets/calltip.py b/spyder/widgets/calltip.py
--- a/spyder/widgets/calltip.py
+++ b/spyder/widgets/calltip.py
@@ -127,13 +127,6 @@ def show_tip(self, point, tip, cursor=None, completion_doc=None):
         """
         Attempts to show the specified tip at the current cursor location.
         """
-        # Don't attempt to show it if it's already visible and the text
-        # to be displayed is the same as the one displayed before.
-        if self.tip == tip:
-            if not self.isVisible():
-                self.show()
-            return
-
         # Set the text and resize the widget accordingly.
         self.tip = tip
         self.setText(tip)
@@ -200,10 +193,6 @@ def show_tip(self, point, tip, cursor=None, completion_doc=None):
             self.show()
         return True
 
-    def reset_tooltip(self):
-        """Reset tip to None."""
-        self.tip = None
-
     def mousePressEvent(self, event):
         """
         Reimplemented to hide it when focus goes out of the main window.
diff --git a/spyder/widgets/mixins.py b/spyder/widgets/mixins.py
--- a/spyder/widgets/mixins.py
+++ b/spyder/widgets/mixins.py
@@ -635,17 +635,20 @@ def show_hint(self, text, inspect_word, at_point,
         html_signature, extra_text, _ = res
         point = self.get_word_start_pos(at_point)
 
-        # This is needed to get hover hints
-        cursor = self.cursorForPosition(at_point)
-        cursor.movePosition(QTextCursor.StartOfWord, QTextCursor.MoveAnchor)
-        self._last_hover_cursor = cursor
-
-        self.show_tooltip(signature=html_signature, text=extra_text,
-                          at_point=point, inspect_word=inspect_word,
-                          display_link=True, max_lines=max_lines,
-                          max_width=max_width, cursor=cursor,
-                          text_new_line=text_new_line,
-                          completion_doc=completion_doc)
+        # Only display hover hint if there is documentation
+        if extra_text is not None:
+            # This is needed to get hover hints
+            cursor = self.cursorForPosition(at_point)
+            cursor.movePosition(QTextCursor.StartOfWord,
+                                QTextCursor.MoveAnchor)
+            self._last_hover_cursor = cursor
+
+            self.show_tooltip(signature=html_signature, text=extra_text,
+                              at_point=point, inspect_word=inspect_word,
+                              display_link=True, max_lines=max_lines,
+                              max_width=max_width, cursor=cursor,
+                              text_new_line=text_new_line,
+                              completion_doc=completion_doc)
 
     def hide_tooltip(self):
         """
@@ -661,10 +664,6 @@ def hide_tooltip(self):
         self._last_point = None
         self.tooltip_widget.hide()
 
-    def reset_tooltip(self):
-        """Reset tooltip tip."""
-        self.tooltip_widget.reset_tooltip()
-
     #------EOL characters
     def set_eol_chars(self, text):
         """Set widget end-of-line (EOL) characters from text (analyzes text)"""


Test patch:
diff --git a/spyder/plugins/editor/widgets/tests/test_hints_and_calltips.py b/spyder/plugins/editor/widgets/tests/test_hints_and_calltips.py
--- a/spyder/plugins/editor/widgets/tests/test_hints_and_calltips.py
+++ b/spyder/plugins/editor/widgets/tests/test_hints_and_calltips.py
@@ -130,9 +130,6 @@ def test_get_calltips(qtbot, lsp_codeeditor, params):
                     reason="Fails on Windows and Linux on CI")
 @pytest.mark.parametrize('params', [
             # Parameter, Expected Output
-            ('dict', '' if PY2 else 'dict'),
-            ('type', 'type'),
-            ('range', 'range'),
             ('"".format', '-> str'),
             ('import math', 'module'),
             (TEST_TEXT, TEST_DOCSTRING)
@@ -168,3 +165,27 @@ def test_get_hints(qtbot, lsp_codeeditor, params, capsys):
         # This checks that code_editor.log_lsp_handle_errors was not called
         captured = capsys.readouterr()
         assert captured.err == ''
+
+
+@pytest.mark.slow
+@pytest.mark.second
+@pytest.mark.skipif(sys.platform != 'darwin',
+                    reason="Fails on Windows and Linux")
+def test_get_hints_not_triggered(qtbot, lsp_codeeditor):
+    """Test that the editor is not returning hover hints for empty docs."""
+    code_editor, _ = lsp_codeeditor
+
+    # Set text in editor
+    code_editor.set_text('def test():\n    pass\n\ntest')
+
+    # Get cursor coordinates
+    code_editor.moveCursor(QTextCursor.End)
+    qtbot.keyPress(code_editor, Qt.Key_Left)
+    x, y = code_editor.get_coordinates('cursor')
+    point = code_editor.calculate_real_position(QPoint(x, y))
+
+    with qtbot.waitSignal(code_editor.sig_display_object_info, timeout=30000):
+        qtbot.mouseMove(code_editor, point)
+        qtbot.mouseClick(code_editor, Qt.LeftButton, pos=point)
+        qtbot.wait(1000)
+        assert not code_editor.tooltip_widget.isVisible()
diff --git a/spyder/plugins/editor/widgets/tests/test_introspection.py b/spyder/plugins/editor/widgets/tests/test_introspection.py
--- a/spyder/plugins/editor/widgets/tests/test_introspection.py
+++ b/spyder/plugins/editor/widgets/tests/test_introspection.py
@@ -525,7 +525,7 @@ def test_completions(lsp_codeeditor, qtbot):
 
 @pytest.mark.slow
 @pytest.mark.first
-@pytest.mark.skipif(not rtree_available or PY2,
+@pytest.mark.skipif(not rtree_available or PY2 or os.name == 'nt',
                     reason='Only works if rtree is installed')
 def test_code_snippets(lsp_codeeditor, qtbot):
     assert rtree_available