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): """