RefactoringRope/Refactoring.py

branch
server_client_variant
changeset 166
6fc202183b3b
parent 165
ea41742015af
child 167
3c8e875d0326
diff -r ea41742015af -r 6fc202183b3b RefactoringRope/Refactoring.py
--- a/RefactoringRope/Refactoring.py	Fri Sep 15 19:50:07 2017 +0200
+++ b/RefactoringRope/Refactoring.py	Sat Sep 16 16:40:50 2017 +0200
@@ -58,6 +58,7 @@
         self.__projectpath = ''
         self.__projectLanguage = ""
         self.__projectopen = False
+        self.__ropeConfig = {}
         
         self.__mainMenu = None
         self.__helpDialog = None
@@ -911,7 +912,12 @@
         
         @param result dictionary containing the error information
         @type dict
+        @return flag indicating, that the error is to be ignored
+        @rtype bool
         """
+        if "Error" not in result:
+            return True
+        
         if result["Error"] == 'ModuleSyntaxError':
             res = E5MessageBox.warning(
                 self.__ui, result["Title"],
@@ -923,12 +929,16 @@
                     os.path.join(self.__e5project.getProjectPath(),
                                  result["ErrorFile"]),
                     result["ErrorLine"])
+        elif result["Error"] == "InterruptedTaskError":
+            return True
         else:
             E5MessageBox.warning(
                 self.__ui, result["Title"],
                 self.tr("Rope error: {0}").format(
                     result["ErrorString"])
             )
+        
+        return False
     
     def __getOffset(self, editor, line, index):
         r"""
@@ -1918,9 +1928,7 @@
         @param result dictionary containing the result data
         @type dict
         """
-        if "Error" in result:
-            self.__handleRopeError(result)
-        else:
+        if self.__handleRopeError(result):
             title = result["Title"]
             if result["EntriesCount"] > 0:
                 from MatchesDialog import MatchesDialog
@@ -1928,7 +1936,7 @@
                 self.dlg.show()
                 for occurrence in result["Entries"]:
                     self.dlg.addEntry(
-                        # resource, lineno, unsure
+                        # file name, lineno, unsure
                         occurrence[0], occurrence[1], occurrence[2])
             else:
                 E5MessageBox.warning(
@@ -1944,7 +1952,7 @@
         if aw is None:
             return
         
-        title = self.tr("Find &Definition")
+        title = self.tr("Find Definition")
         
         if not self.confirmAllBuffersSaved():
             return
@@ -1953,25 +1961,13 @@
         line, index = aw.getCursorPosition()
         offset = self.__getOffset(aw, line, index)
         
-        import rope.contrib.findit
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
-        try:
-            location = rope.contrib.findit.find_definition(
-                self.__project, aw.text(), offset, resource)
-        except Exception as err:
-            self.handleRopeError(err, title)
-            return
-        
-        if location is not None:
-            from MatchesDialog import MatchesDialog
-            self.dlg = MatchesDialog(self.__ui, False)
-            self.dlg.show()
-            self.dlg.addEntry(location.resource, location.lineno)
-        else:
-            E5MessageBox.warning(
-                self.__ui, title,
-                self.tr("No matching definition found."))
+        self.sendJson("QueryDefinition", {
+            "Title": title,
+            "FileName": filename,
+            "Offset": offset,
+            "Source": aw.text(),
+            "Subcommand": "Query",
+        })
     
     def gotoDefinition(self, editor):
         """
@@ -1986,27 +1982,52 @@
         line, index = editor.getCursorPosition()
         offset = self.__getOffset(editor, line, index)
         
-        import rope.contrib.findit
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
-        try:
-            location = rope.contrib.findit.find_definition(
-                self.__project, editor.text(), offset, resource)
-        except Exception:
-            # simply ignore them
-            return
+        self.sendJson("QueryDefinition", {
+            "Title": "",
+            "FileName": filename,
+            "Offset": offset,
+            "Source": editor.text(),
+            "Subcommand": "Goto",
+        })
+    
+    def __queryDefinitionResult(self, result):
+        """
+        Private method to handle the "Query Definition" result sent by
+        the client.
         
-        if location is not None:
-            try:
-                e5App().getObject("ViewManager").openSourceFile(
-                    location.resource.real_path, location.lineno, addNext=True)
-            except TypeError:
-                # backward compatibility; <= 17.03
-                e5App().getObject("ViewManager").openSourceFile(
-                    location.resource.real_path, location.lineno, next=True)
-        else:
-            e5App().getObject("UserInterface").statusBar().showMessage(
-                self.tr('No definition found'), 5000)
+        @param result dictionary containing the result data
+        @type dict
+        """
+        if result["Subcommand"] == "Query":
+            if self.__handleRopeError(result):
+                title = result["Title"]
+                if "Location" in result:
+                    location = result["Location"]
+                    
+                    from MatchesDialog import MatchesDialog
+                    self.dlg = MatchesDialog(self.__ui, False)
+                    self.dlg.show()
+                    self.dlg.addEntry(location[0], location[1])
+                    # file name, lineno
+                else:
+                    E5MessageBox.warning(
+                        self.__ui, title,
+                        self.tr("No matching definition found."))
+        elif result["Subcommand"] == "Goto":
+            if "Error" not in result:
+                # ignore errors silently
+                if "Location" in result:
+                    location = result["Location"]
+                    try:
+                        e5App().getObject("ViewManager").openSourceFile(
+                            location[0], location[1], addNext=True)
+                    except TypeError:
+                        # backward compatibility; <= 17.03
+                        e5App().getObject("ViewManager").openSourceFile(
+                            location[0], location[1], next=True)
+                else:
+                    e5App().getObject("UserInterface").statusBar().showMessage(
+                        self.tr('No definition found'), 5000)
     
     def __queryImplementations(self):
         """
@@ -2026,31 +2047,33 @@
         line, index = aw.getCursorPosition()
         offset = self.__getOffset(aw, line, index)
         
-        import rope.contrib.findit
-        from ProgressHandle import ProgressHandle
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
-        handle = ProgressHandle(title, True, self.__ui)
-        handle.show()
-        QApplication.processEvents()
-        try:
-            occurrences = rope.contrib.findit.find_implementations(
-                self.__project, resource, offset, task_handle=handle)
-        except Exception as err:
-            self.handleRopeError(err, title, handle)
-            return
-        handle.reset()
+        self.sendJson("QueryImplementations", {
+            "Title": title,
+            "FileName": filename,
+            "Offset": offset,
+        })
+    
+    def __queryImplementationsResult(self, result):
+        """
+        Private method to handle the "Query Implementations" result sent by
+        the client.
         
-        if occurrences:
-            from MatchesDialog import MatchesDialog
-            self.dlg = MatchesDialog(self.__ui, True)
-            self.dlg.show()
-            for occurrence in occurrences:
-                self.dlg.addEntry(
-                    occurrence.resource, occurrence.lineno, occurrence.unsure)
-        else:
-            E5MessageBox.warning(
-                self.__ui, title, self.tr("No occurrences found."))
+        @param result dictionary containing the result data
+        @type dict
+        """
+        if self.__handleRopeError(result):
+            title = result["Title"]
+            if result["EntriesCount"] > 0:
+                from MatchesDialog import MatchesDialog
+                self.dlg = MatchesDialog(self.__ui, True)
+                self.dlg.show()
+                for occurrence in result["Entries"]:
+                    self.dlg.addEntry(
+                        # file name, lineno, unsure
+                        occurrence[0], occurrence[1], occurrence[2])
+            else:
+                E5MessageBox.warning(
+                    self.__ui, title, self.tr("No implementations found."))
     
     #####################################################
     ## Various actions
@@ -2060,10 +2083,10 @@
         """
         Private slot to open the rope configuration file in an editor.
         """
-        ropedir = self.__project.ropefolder
+        ropedir = self.__ropeConfig["RopeFolderName"]
         configfile = ""
-        if ropedir is not None:
-            configfile = os.path.join(ropedir.real_path, "config.py")
+        if ropedir and os.path.exists(ropedir):
+            configfile = os.path.join(ropedir, "config.py")
             if os.path.exists(configfile):
                 from QScintilla.MiniEditor import MiniEditor
                 self.__editor = MiniEditor(configfile)
@@ -2114,15 +2137,9 @@
         """
         if self.__helpDialog is None:
             from HelpDialog import HelpDialog
-            if sys.version_info[0] >= 3:
-                directory = 'rope_py3'
-            else:
-                directory = 'rope_py2'
-            helpfile = os.path.join(os.path.dirname(__file__),
-                                    directory, "rope", "docs", "overview.txt")
             self.__helpDialog = \
                 HelpDialog(self.tr("Help about rope refactorings"),
-                           helpfile)
+                           self.__ropeConfig["RopeHelpFile"])
         self.__helpDialog.show()
     
     def __performSOA(self):
@@ -2136,21 +2153,27 @@
             self.tr("""This action might take some time. """
                     """Do you really want to perform SOA?"""))
         if res:
-            from ProgressHandle import ProgressHandle
-            handle = ProgressHandle(title, True, self.__ui)
-            handle.show()
-            QApplication.processEvents()
-            try:
-                rope.base.libutils.analyze_modules(
-                    self.__project, task_handle=handle)
-                handle.reset()
-                E5MessageBox.information(
-                    self.__ui,
-                    title,
-                    self.tr("""Static object analysis (SOA) done. """
-                            """SOA database updated."""))
-            except Exception as err:
-                self.handleRopeError(err, title, handle)
+        
+            self.sendJson("PerformSoa", {
+                "Title": title,
+            })
+    
+    def __soaFinished(self, result):
+        """
+        Private method to handle the "Soa Finished" result sent by
+        the client.
+        
+        @param result dictionary containing the result data
+        @type dict
+        """
+        if self.__handleRopeError(result):
+            title = result["Title"]
+            
+            E5MessageBox.information(
+                self.__ui,
+                title,
+                self.tr("""Static object analysis (SOA) done. """
+                        """SOA database updated."""))
     
     ##################################################################
     ## methods below are private utility methods
@@ -2163,10 +2186,10 @@
         @return name of the rope configuration file (string)
         """
         configfile = None
-        if self.__project is not None:
-            ropedir = self.__project.ropefolder
-            if ropedir is not None:
-                configfile = os.path.join(ropedir.real_path, "config.py")
+        if self.__ropeConfig:
+            ropedir = self.__ropeConfig["RopeFolderName"]
+            if ropedir:
+                configfile = os.path.join(ropedir, "config.py")
                 if not os.path.exists(configfile):
                     configfile = None
         return configfile
@@ -2175,10 +2198,7 @@
         """
         Private slot called, when the rope config file has changed.
         """
-        import rope.base.project
-        self.__project.close()
-        self.__project = rope.base.project.Project(
-            self.__projectpath, fscommands=self.__fsCommands)
+        self.sendJson("ConfigChanged", {})
     
     def __defaultConfig(self):
         """
@@ -2187,8 +2207,8 @@
         @return string containing the source of rope's default
             configuration (string)
         """
-        if self.__project is not None:
-            return self.__project._default_config()
+        if self.__ropeConfig and "DefaultConfig" in self.__ropeConfig:
+            return self.__ropeConfig["DefaultConfig"]
         else:
             return ""
     
@@ -2252,6 +2272,7 @@
         self.__projectopen = False
         self.__projectpath = ''
         self.__projectLanguage = ""
+        self.__ropeConfig = {}
     
     # TODO: delete this or move to client
 ##    def getProject(self):
@@ -2285,6 +2306,7 @@
         self.sendJson("Validate", {})
         return res
     
+    # TODO: port this
     def refreshEditors(self, changes):
         """
         Public method to refresh modified editors.
@@ -2295,9 +2317,9 @@
         vm = e5App().getObject("ViewManager")
         
         changedFiles = []
-        for resource in changes.get_changed_resources():
-            if not resource.is_folder():
-                changedFiles.append(resource.real_path)
+#        for resource in changes.get_changed_resources():
+#            if not resource.is_folder():
+#                changedFiles.append(resource.real_path)
         
         openFiles = [Utilities.normcasepath(f) for f in vm.getOpenFilenames()]
         
@@ -2320,14 +2342,12 @@
         @param filename file name of the changed source (string)
         @param oldSource source code before the change (string)
         """
-        if self.__project and self.__e5project.isProjectFile(filename):
-            try:
-                rope.base.libutils.report_change(
-                    self.__project, filename, oldSource)
-            except RuntimeError:
-                # this could come from trying to do PyQt4/PyQt5 mixed stuff
-                # simply ignore it
-                pass
+        if self.__e5project.isOpen() and \
+                self.__e5project.isProjectFile(filename):
+            self.sendJson("ReportChanged", {
+                "FileName": filename,
+                "OldSource": oldSource,
+            })
     
     #######################################################################
     ## Methods below handle the network connection
@@ -2345,8 +2365,9 @@
         @param params dictionary with method specific parameters
         @type dict
         """
-        if method == "pong":
-            pass
+        if method == "Config":
+            self.__ropeConfig = params
+            # keys: RopeFolderName, DefaultConfig
         
         elif method == "ClientException":
             if params["ExceptionType"] == "ProtocolError":
@@ -2401,6 +2422,15 @@
         
         elif method == "QueryReferencesResult":
             self.__queryReferencesResult(params)
+        
+        elif method == "QueryDefinitionResult":
+            self.__queryDefinitionResult(params)
+        
+        elif method == "QueryImplementationsResult":
+            self.__queryImplementationsResult(params)
+        
+        elif method == "SoaFinished":
+            self.__soaFinished(params)
     
     def __startRefactoringClient(self, interpreter):
         """

eric ide

mercurial