Tue, 05 Oct 2021 18:13:40 +0200
Continued implementing the Jedi refactoring interface.
--- a/eric7/JediInterface/AssistantJedi.py Mon Oct 04 19:59:59 2021 +0200 +++ b/eric7/JediInterface/AssistantJedi.py Tue Oct 05 18:13:40 2021 +0200 @@ -226,6 +226,12 @@ self.__menu.addAction( self.tr("Rename Variable"), self.__jediServer.refactoringRenameVariable) + self.__menu.addAction( + self.tr("Extract Variable"), + self.__jediServer.refactoringExtractNewVariable) + self.__menu.addAction( + self.tr("Inline Variable"), + self.__jediServer.refactoringInlineVariable) def __editorShowMenu(self, menuName, menu, editor): """
--- a/eric7/JediInterface/JediClient.py Mon Oct 04 19:59:59 2021 +0200 +++ b/eric7/JediInterface/JediClient.py Tue Oct 05 18:13:40 2021 +0200 @@ -42,7 +42,6 @@ super().__init__(host, port, idString) # TODO: add additional methods for these topics - # - rename variable # - extract function # - extract variable # - inline variable @@ -58,6 +57,8 @@ "gotoReferences": self.__getReferences, "renameVariable": self.__renameVariable, + "extractVariable": self.__extractVariable, + "inlineVariable": self.__inlineVariable, "applyRefactoring": self.__applyRefactoring, "cancelRefactoring": self.__cancelRefactoring, } @@ -444,7 +445,79 @@ } result.update(errorDict) - self.sendJson("RenameVariableDiff", result) + self.sendJson("RefactoringDiff", result) + + def __extractVariable(self, params): + """ + Private method to extract a statement to a new variable. + + @param params dictionary containing the method parameters + @type dict + """ + filename = params["FileName"] + source = params["Source"] + line = params["Line"] + index = params["Index"] + endLine = params["EndLine"] + endIndex = params["EndIndex"] + uid = params["Uuid"] + newName = params["NewName"] + + errorDict = {} + diff = "" + + script = jedi.Script(source, path=filename, project=self.__project) + + try: + refactoring = script.extract_variable( + line, index, new_name=newName, + until_line=endLine, until_column=endIndex + ) + self.__refactorings[uid] = refactoring + diff = refactoring.get_diff() + except SuppressedException as err: + errorDict = self.__handleError(err) + + result = { + "Diff": diff, + "Uuid": uid, + } + result.update(errorDict) + + self.sendJson("RefactoringDiff", result) + + def __inlineVariable(self, params): + """ + Private method to inline a variable statement. + + @param params dictionary containing the method parameters + @type dict + """ + filename = params["FileName"] + source = params["Source"] + line = params["Line"] + index = params["Index"] + uid = params["Uuid"] + + errorDict = {} + diff = "" + + script = jedi.Script(source, path=filename, project=self.__project) + + try: + refactoring = script.inline(line, index) + self.__refactorings[uid] = refactoring + diff = refactoring.get_diff() + except SuppressedException as err: + errorDict = self.__handleError(err) + + result = { + "Diff": diff, + "Uuid": uid, + } + result.update(errorDict) + + self.sendJson("RefactoringDiff", result) def __applyRefactoring(self, params): """
--- a/eric7/JediInterface/JediServer.py Mon Oct 04 19:59:59 2021 +0200 +++ b/eric7/JediInterface/JediServer.py Tue Oct 05 18:13:40 2021 +0200 @@ -90,7 +90,7 @@ "GotoDefinitionResult": self.__processGotoDefinitionResult, "GotoReferencesResult": self.__processGotoReferencesResult, - "RenameVariableDiff": self.__showRenameVariableDiff, + "RefactoringDiff": self.__showRefactoringDiff, "RefactoringApplyResult": self.__checkRefactoringResult, "ClientException": self.__processClientException, @@ -511,7 +511,6 @@ if ok and newName: filename = editor.getFileName() line, index = editor.getCursorPosition() - line += 1 # jedi line numbers are 1 based source = editor.text() self.__ensureActive(idString) @@ -522,21 +521,89 @@ self.sendJson("renameVariable", { "FileName": filename, "Source": source, - "Line": line, + "Line": line + 1, "Index": index, "Uuid": euuid, "NewName": newName, }, idString=idString) - def __showRenameVariableDiff(self, result): + @pyqtSlot() + def refactoringExtractNewVariable(self): + """ + Public slot to extract a statement to a new variable. """ - Private method to show the diff of the Rename Variable refactoring. + editor = self.__vm.activeWindow() + if editor: + idString = self.__idString(editor) + if not idString: + return + + newName, ok = QInputDialog.getText( + None, + self.tr("Extract Variable"), + self.tr("Enter the name for the new variable:"), + QLineEdit.EchoMode.Normal + ) + + if ok and newName: + filename = editor.getFileName() + sLine, sIndex, eLine, eIndex = editor.getSelection() + source = editor.text() + + self.__ensureActive(idString) + + euuid = str(uuid.uuid4()) + self.__editors[euuid] = editor + + self.sendJson("extractVariable", { + "FileName": filename, + "Source": source, + "Line": sLine + 1, + "Index": sIndex, + "EndLine": eLine + 1, + "EndIndex": eIndex, + "Uuid": euuid, + "NewName": newName, + }, idString=idString) + + @pyqtSlot() + def refactoringInlineVariable(self): + """ + Public slot to inline the selected variable. + + Note: This is the opposite to Extract New Variable. + """ + editor = self.__vm.activeWindow() + if editor: + idString = self.__idString(editor) + if not idString: + return + + filename = editor.getFileName() + line, index = editor.getCursorPosition() + source = editor.text() + + self.__ensureActive(idString) + + euuid = str(uuid.uuid4()) + self.__editors[euuid] = editor + + self.sendJson("inlineVariable", { + "FileName": filename, + "Source": source, + "Line": line + 1, + "Index": index, + "Uuid": euuid, + }, idString=idString) + + def __showRefactoringDiff(self, result): + """ + Private method to show the diff of a refactoring. @param result dictionary containing the result data @type dict """ if "Error" not in result: - # ignore errors silently euuid = result["Uuid"] diff = result["Diff"] dlg = RefactoringPreviewDialog(self.tr("Rename Variable"), diff) @@ -544,6 +611,13 @@ self.__applyRefactoring(euuid) else: self.__cancelRefactoring(euuid) + else: + EricMessageBox.critical( + None, + self.tr("Refactoring"), + self.tr("<p>The refactoring could not be performed.</p>" + "<p>Reason: {0}</p>").format(result["ErrorString"]) + ) def __applyRefactoring(self, uid): """ @@ -588,7 +662,7 @@ """ if "Error" in result: EricMessageBox.critical( - self, + None, self.tr("Apply Refactoring"), self.tr("<p>The refactoring could not be applied.</p>" "<p>Reason: {0}</p>").format(result["ErrorString"])