RefactoringRope/CodeAssistServer.py

changeset 283
d98e971d9e4c
parent 280
45f0a0511acd
child 285
247d62c682dc
--- a/RefactoringRope/CodeAssistServer.py	Sun Sep 16 13:17:08 2018 +0200
+++ b/RefactoringRope/CodeAssistServer.py	Sun Oct 28 12:30:45 2018 +0100
@@ -21,12 +21,15 @@
 
 import Globals
 import Preferences
+import Utilities
 
 
 class CodeAssistServer(JsonServer):
     """
     Class implementing the autocompletion interface to rope.
     """
+    IdProject = "Project"
+    
     def __init__(self, plugin, parent=None):
         """
         Constructor
@@ -42,6 +45,7 @@
         self.__plugin = plugin
         self.__ui = parent
         self.__vm = e5App().getObject("ViewManager")
+        self.__e5project = e5App().getObject("Project")
         
         self.__editorLanguageMapping = {}
         self.__clientConfigs = {}
@@ -100,6 +104,40 @@
                     "Pygments|Python 3": "Python3",
                 })
     
+    def isSupportedLanguage(self, language):
+        """
+        Public method to check, if the given language is supported.
+        
+        @param language editor programming language to check
+        @type str
+        @return flag indicating the support status
+        @rtype bool
+        """
+        return language in self.__editorLanguageMapping
+    
+    def __idString(self, editor):
+        """
+        Private method to determine the ID string for the back-end.
+        
+        @param editor reference to the editor to determine the ID string for
+        @type QScintilla.Editor
+        @return ID string
+        @rtype str
+        """
+        idString = ""
+        
+        language = editor.getLanguage()
+        if self.__e5project.isOpen() and \
+           self.__e5project.getProjectLanguage() == language:
+            filename = editor.getFileName()
+            if self.__e5project.isProjectSource(filename):
+                idString = CodeAssistServer.IdProject
+        
+        if not idString and language in self.__editorLanguageMapping:
+            idString = self.__editorLanguageMapping[language]
+        
+        return idString
+    
     def __getConfigs(self):
         """
         Private method to get the configurations of all connected clients.
@@ -170,17 +208,6 @@
                 self.tr("""The Rope configuration file '{0}' does"""
                         """ not exist.""").format(configfile))
     
-    def isSupportedLanguage(self, language):
-        """
-        Public method to check, if the given language is supported.
-        
-        @param language editor programming language to check
-        @type str
-        @return flag indicating the support status
-        @rtype bool
-        """
-        return language in self.__editorLanguageMapping
-    
     def getCompletions(self, editor, context):
         """
         Public method to calculate the possible completions.
@@ -197,8 +224,7 @@
         # reset the completions buffer
         self.__completions = None
         
-        language = editor.getLanguage()
-        if language not in self.__editorLanguageMapping:
+        if not self.__idString(editor):
             return []
         
         self.requestCompletions(editor, context, "")
@@ -226,10 +252,9 @@
         @param acText text to be completed
         @type str
         """
-        language = editor.getLanguage()
-        if language not in self.__editorLanguageMapping:
+        idString = self.__idString(editor)
+        if not idString:
             return
-        idString = self.__editorLanguageMapping[language]
         
         filename = editor.getFileName()
         line, index = editor.getCursorPosition()
@@ -284,10 +309,9 @@
         # reset the calltips buffer
         self.__calltips = None
         
-        language = editor.getLanguage()
-        if language not in self.__editorLanguageMapping:
+        idString = self.__idString(editor)
+        if not idString:
             return []
-        idString = self.__editorLanguageMapping[language]
         
         filename = editor.getFileName()
         source = editor.text()
@@ -336,10 +360,8 @@
         """
         editor = self.__vm.getOpenEditor(filename)
         if editor is not None:
-            language = editor.getLanguage()
-            if language in self.__editorLanguageMapping:
-                idString = self.__editorLanguageMapping[language]
-                
+            idString = self.__idString(editor)
+            if idString:
                 self.__ensureActive(idString)
                 self.sendJson("reportChanged", {
                     "FileName": filename,
@@ -359,7 +381,7 @@
             return
         
         language = editor.getLanguage()
-        if language not in self.__editorLanguageMapping:
+        if not self.isSupportedLanguage(language):
             if Preferences.getDocuViewer("ShowInfoAsRichText"):
                 warning = self.tr("Language <b>{0}</b> is not supported.")\
                     .format(language)
@@ -370,7 +392,9 @@
                 warning, isWarning=True)
             return
         
-        idString = self.__editorLanguageMapping[language]
+        idString = self.__idString(editor)
+        if not idString:
+            return
         
         filename = editor.getFileName()
         source = editor.text()
@@ -496,7 +520,11 @@
         ok = False
         
         if interpreter:
-            configDir = os.path.join(Globals.getConfigDir(), "rope", idString)
+            if idString == CodeAssistServer.IdProject:
+                configDir = self.__e5project.getProjectPath()
+            else:
+                configDir = os.path.join(Globals.getConfigDir(), "rope",
+                                         idString)
             if not os.path.exists(configDir):
                 os.makedirs(configDir)
             
@@ -531,50 +559,112 @@
         ok = idString in self.connectionNames()
         if not ok:
             # client is not running
-            try:
-                # new code using virtual environments
-                venvManager = e5App().getObject("VirtualEnvManager")
-                if idString == "Python2":
-                    # Python 2
-                    venvName = Preferences.getDebugger("Python2VirtualEnv")
-                    if not venvName and sys.version_info[0] == 2:
-                        try:
-                            venvName, _ = venvManager.getDefaultEnvironment()
-                        except AttributeError:
-                            # ignore for eric6 < 18.10
-                            pass
-                elif idString == "Python3":
-                    # Python 3
-                    venvName = Preferences.getDebugger("Python3VirtualEnv")
-                    if not venvName and sys.version_info[0] == 3:
-                        try:
-                            venvName, _ = venvManager.getDefaultEnvironment()
-                        except AttributeError:
-                            # ignore for eric6 < 18.10
-                            pass
-                else:
-                    venvName = ""
-                if venvName:
-                    interpreter = e5App().getObject("VirtualEnvManager")\
-                        .getVirtualenvInterpreter(venvName)
-                else:
-                    interpreter = ""
-            except KeyError:
-                # backward compatibility (eric <18.07)
-                if idString == "Python2":
-                    # Python 2
-                    interpreter = Preferences.getDebugger("PythonInterpreter")
-                elif idString == "Python3":
-                    # Python 3
-                    interpreter = Preferences.getDebugger("Python3Interpreter")
-                else:
-                    interpreter = ""
+            if idString == CodeAssistServer.IdProject:
+                interpreter = self.__interpreterForProject()
+            else:
+                interpreter = ""
+                venvName = ""
+                try:
+                    # new code using virtual environments
+                    venvManager = e5App().getObject("VirtualEnvManager")
+                    if idString == "Python2":
+                        # Python 2
+                        venvName = Preferences.getDebugger("Python2VirtualEnv")
+                        if not venvName and sys.version_info[0] == 2:
+                            try:
+                                venvName, _ = \
+                                    venvManager.getDefaultEnvironment()
+                            except AttributeError:
+                                # ignore for eric6 < 18.10
+                                pass
+                    elif idString == "Python3":
+                        # Python 3
+                        venvName = Preferences.getDebugger("Python3VirtualEnv")
+                        if not venvName and sys.version_info[0] == 3:
+                            try:
+                                venvName, _ = \
+                                    venvManager.getDefaultEnvironment()
+                            except AttributeError:
+                                # ignore for eric6 < 18.10
+                                pass
+                    if venvName:
+                        interpreter = \
+                            venvManager.getVirtualenvInterpreter(venvName)
+                except KeyError:
+                    # backward compatibility (eric <18.07)
+                    if idString == "Python2":
+                        # Python 2
+                        interpreter = \
+                            Preferences.getDebugger("PythonInterpreter")
+                    elif idString == "Python3":
+                        # Python 3
+                        interpreter = \
+                            Preferences.getDebugger("Python3Interpreter")
             if interpreter:
                 ok = self.__startCodeAssistClient(interpreter, idString)
             else:
                 ok = False
         return ok
     
+    def __interpreterForProject(self):
+        """
+        Private method to determine the interpreter for the current project.
+        
+        @return interpreter of the current project
+        @rtype str
+        """
+        interpreter = ""
+        projectLanguage = self.__e5project.getProjectLanguage()
+        
+        if projectLanguage.startswith("Python"):
+            try:
+                # new code using virtual environments
+                venvManager = e5App().getObject("VirtualEnvManager")
+                
+                # get virtual environment from project first
+                venvName = self.__e5project.getDebugProperty("VIRTUALENV")
+                if not venvName:
+                    # get it from debugger settings next
+                    if projectLanguage == "Python2":
+                        # Python 2
+                        venvName = Preferences.getDebugger("Python2VirtualEnv")
+                        if not venvName and sys.version_info[0] == 2:
+                            try:
+                                venvName, _ = \
+                                    venvManager.getDefaultEnvironment()
+                            except AttributeError:
+                                # ignore for eric6 < 18.10
+                                pass
+                    elif projectLanguage == "Python3":
+                        # Python 3
+                        venvName = Preferences.getDebugger("Python3VirtualEnv")
+                        if not venvName and sys.version_info[0] == 3:
+                            try:
+                                venvName, _ = \
+                                    venvManager.getDefaultEnvironment()
+                            except AttributeError:
+                                # ignore for eric6 < 18.10
+                                pass
+                    else:
+                        venvName = ""
+                if venvName:
+                    interpreter = \
+                        venvManager.getVirtualenvInterpreter(venvName)
+            except KeyError:
+                # backward compatibility (eric < 18.07)
+                # get interpreter from project first
+                interpreter = self.__e5project.getDebugProperty("INTERPRETER")
+                if not interpreter or not Utilities.isinpath(interpreter):
+                    # get it from debugger settings second
+                    if projectLanguage == "Python2":
+                        interpreter = Preferences.getDebugger(
+                            "PythonInterpreter")
+                    elif projectLanguage == "Python3":
+                        interpreter = Preferences.getDebugger(
+                            "Python3Interpreter")
+        
+        return interpreter
+    
     @pyqtSlot()
     def handleNewConnection(self):
         """
@@ -599,6 +689,8 @@
         except AttributeError:
             # eric6 before 17.11 doesn't have this
             pass
+        
+        self.__e5project.projectClosed.connect(self.__projectClosed)
     
     def deactivate(self):
         """
@@ -613,8 +705,21 @@
         for idString in self.connectionNames():
             self.sendJson("closeProject", {}, flush=True, idString=idString)
         
+        try:
+            self.__e5project.projectClosed.disconnect(self.__projectClosed)
+        except TypeError:
+            # ignore it, the signal may be disconnected already
+            pass
+        
         self.stopAllClients()
     
+    @pyqtSlot()
+    def __projectClosed(self):
+        """
+        Private slot to handle the projectClosed signal.
+        """
+        self.stopClient(idString=CodeAssistServer.IdProject)
+    
     #######################################################################
     ## Methods below handle setting/unsetting the hook methods
     #######################################################################

eric ide

mercurial