Repository: spyder-ide/spyder

Issue:
Some issues with code completion in the Editor
Last night I was testing things after PR #2337 and I found these problems (sorted by importance, from very serious to less so):
1. If you try to get completions of something that can't give none (e.g. `XX<tab>`), the completion machinery **stops** to work, i.e. you can't get completions on the current file, nor on any other (new or already open). This is also true for any file (i.e. be it a Python one or not :-)
2. `import n<Tab>` or `from a<Tab>` are not showing the new module icon on the completion widget
3. For non-Python files, we shouldn't show a transparent icon next to completions, but not icon at all. This is an aesthetic preference, but it seems a bit ugly to have all completions shown with (what appears to be) a wide margin to the right.



Discussion:

Resolving patch:
diff --git a/spyderlib/utils/introspection/fallback_plugin.py b/spyderlib/utils/introspection/fallback_plugin.py
--- a/spyderlib/utils/introspection/fallback_plugin.py
+++ b/spyderlib/utils/introspection/fallback_plugin.py
@@ -34,9 +34,15 @@ def get_completions(self, info):
         Simple completion based on python-like identifiers and whitespace
         """
         items = []
-        if (info.line.strip().startswith(('import ', 'from ')) and
-                info.is_python_like):
+        line = info.line.strip()
+        is_from = line.startswith('from')
+        if ((line.startswith('import') or is_from and ' import' not in line)
+                and info.is_python_like):
             items += module_completion(info.line, [info.filename])
+            return [(i, 'module') for i in sorted(items)]
+        elif is_from and info.is_python_like:
+            items += module_completion(info.line, [info.filename])
+            return [(i, '') for i in sorted(items)]
         elif info.obj:
             base = info.obj
             tokens = set(info.split_words(-1))
@@ -54,7 +60,7 @@ def get_completions(self, info):
             match = re.search('''[ "\']([\w\.\\\\/]+)\Z''', info.line)
             if match:
                 items += _complete_path(match.groups()[0])
-        return [(i, '') for i in sorted(items)]
+            return [(i, '') for i in sorted(items)]
 
     def get_definition(self, info):
         """
diff --git a/spyderlib/utils/introspection/plugin_manager.py b/spyderlib/utils/introspection/plugin_manager.py
--- a/spyderlib/utils/introspection/plugin_manager.py
+++ b/spyderlib/utils/introspection/plugin_manager.py
@@ -71,6 +71,9 @@ def _handle_incoming(self, name):
         if name == self.plugins[0].name or not self.waiting:
             if result:
                 self._finalize(name, result)
+            else:
+                debug_print('No valid responses acquired')
+                self.introspection_complete.emit()
         else:
             self.pending[name] = result
 
diff --git a/spyderlib/widgets/sourcecode/base.py b/spyderlib/widgets/sourcecode/base.py
--- a/spyderlib/widgets/sourcecode/base.py
+++ b/spyderlib/widgets/sourcecode/base.py
@@ -79,9 +79,12 @@ def show_list(self, completion_list, automatic=True):
                      'class': 'class.png',
                      'module': 'module.png'}
 
-        for (c, t) in zip(completion_list, types):
-            icon = icons_map.get(t, 'no_match.png')
-            self.addItem(QListWidgetItem(get_icon(icon), c))
+        if any(types):
+            for (c, t) in zip(completion_list, types):
+                icon = icons_map.get(t, 'no_match.png')
+                self.addItem(QListWidgetItem(get_icon(icon), c))
+        else:
+            self.addItems(completion_list)
 
         self.setCurrentRow(0)
 


Test patch: