private PsiElement performReplace( @NotNull final PsiElement declaration, final IntroduceOperation operation) { final PyExpression expression = operation.getInitializer(); final Project project = operation.getProject(); return new WriteCommandAction<PsiElement>(project, expression.getContainingFile()) { protected void run(final Result<PsiElement> result) throws Throwable { result.setResult(addDeclaration(operation, declaration)); PyExpression newExpression = createExpression(project, operation.getName(), declaration); if (operation.isReplaceAll()) { List<PsiElement> newOccurrences = new ArrayList<PsiElement>(); for (PsiElement occurrence : operation.getOccurrences()) { final PsiElement replaced = replaceExpression(occurrence, newExpression, operation); if (replaced != null) { newOccurrences.add(replaced); } } operation.setOccurrences(newOccurrences); } else { final PsiElement replaced = replaceExpression(expression, newExpression, operation); operation.setOccurrences(Collections.singletonList(replaced)); } postRefactoring(operation.getElement()); } }.execute().getResultObject(); }
protected static void ensureName(IntroduceOperation operation) { if (operation.getName() == null) { final Collection<String> suggestedNames = operation.getSuggestedNames(); if (suggestedNames.size() > 0) { operation.setName(suggestedNames.iterator().next()); } else { operation.setName("x"); } } }
public PyInplaceVariableIntroducer( PyTargetExpression target, IntroduceOperation operation, List<PsiElement> occurrences) { super( target, operation.getEditor(), operation.getProject(), "Introduce Variable", occurrences.toArray(new PsiElement[occurrences.size()]), null); myTarget = target; }
public PyAssignmentStatement createDeclaration(IntroduceOperation operation) { final Project project = operation.getProject(); final PyExpression initializer = operation.getInitializer(); InitializerTextBuilder builder = new InitializerTextBuilder(); initializer.accept(builder); String assignmentText = operation.getName() + " = " + builder.result(); PsiElement anchor = operation.isReplaceAll() ? findAnchor(operation.getOccurrences()) : PsiTreeUtil.getParentOfType(initializer, PyStatement.class); return createDeclaration(project, assignmentText, anchor); }
protected void performInplaceIntroduce(IntroduceOperation operation) { final PsiElement statement = performRefactoring(operation); if (statement instanceof PyAssignmentStatement) { PyTargetExpression target = (PyTargetExpression) ((PyAssignmentStatement) statement).getTargets()[0]; final List<PsiElement> occurrences = operation.getOccurrences(); final PsiElement occurrence = findOccurrenceUnderCaret(occurrences, operation.getEditor()); PsiElement elementForCaret = occurrence != null ? occurrence : target; operation .getEditor() .getCaretModel() .moveToOffset(elementForCaret.getTextRange().getStartOffset()); final InplaceVariableIntroducer<PsiElement> introducer = new PyInplaceVariableIntroducer(target, operation, occurrences); introducer.performInplaceRefactoring( new LinkedHashSet<String>(operation.getSuggestedNames())); } }
@Nullable public PsiElement addDeclaration(IntroduceOperation operation, PsiElement declaration) { final PsiElement expression = operation.getInitializer(); final Pair<PsiElement, TextRange> data = expression.getUserData(PyReplaceExpressionUtil.SELECTION_BREAKS_AST_NODE); if (data == null) { return addDeclaration(expression, declaration, operation); } else { return addDeclaration(data.first, declaration, operation); } }
private boolean smartIntroduce(final IntroduceOperation operation) { final Editor editor = operation.getEditor(); final PsiFile file = operation.getFile(); int offset = editor.getCaretModel().getOffset(); PsiElement elementAtCaret = file.findElementAt(offset); if (!checkIntroduceContext(file, editor, elementAtCaret)) return true; final List<PyExpression> expressions = new ArrayList<PyExpression>(); while (elementAtCaret != null) { if (elementAtCaret instanceof PyStatement || elementAtCaret instanceof PyFile) { break; } if (elementAtCaret instanceof PyExpression && isValidIntroduceVariant(elementAtCaret)) { expressions.add((PyExpression) elementAtCaret); } elementAtCaret = elementAtCaret.getParent(); } if (expressions.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) { operation.setElement(expressions.get(0)); performActionOnElement(operation); return true; } else if (expressions.size() > 1) { IntroduceTargetChooser.showChooser( editor, expressions, new Pass<PyExpression>() { @Override public void pass(PyExpression pyExpression) { operation.setElement(pyExpression); performActionOnElement(operation); } }, new Function<PyExpression, String>() { public String fun(PyExpression pyExpression) { return pyExpression.getText(); } }); return true; } return false; }
protected void performActionOnElementOccurrences(final IntroduceOperation operation) { final Editor editor = operation.getEditor(); if (editor.getSettings().isVariableInplaceRenameEnabled()) { ensureName(operation); if (operation.isReplaceAll() != null) { performInplaceIntroduce(operation); } else { OccurrencesChooser.simpleChooser(editor) .showChooser( operation.getElement(), operation.getOccurrences(), new Pass<OccurrencesChooser.ReplaceChoice>() { @Override public void pass(OccurrencesChooser.ReplaceChoice replaceChoice) { operation.setReplaceAll(replaceChoice == OccurrencesChooser.ReplaceChoice.ALL); performInplaceIntroduce(operation); } }); } } else { performIntroduceWithDialog(operation); } }
protected void performIntroduceWithDialog(IntroduceOperation operation) { final Project project = operation.getProject(); if (operation.getName() == null) { PyIntroduceDialog dialog = new PyIntroduceDialog(project, myDialogTitle, myValidator, getHelpId(), operation); dialog.show(); if (!dialog.isOK()) { return; } operation.setName(dialog.getName()); operation.setReplaceAll(dialog.doReplaceAllOccurrences()); operation.setInitPlace(dialog.getInitPlace()); } PsiElement declaration = performRefactoring(operation); final Editor editor = operation.getEditor(); editor.getCaretModel().moveToOffset(declaration.getTextRange().getEndOffset()); editor.getSelectionModel().removeSelection(); }
private void performActionOnElement(IntroduceOperation operation) { if (!checkEnabled(operation)) { return; } final PsiElement element = operation.getElement(); final PsiElement parent = element.getParent(); final PyExpression initializer = parent instanceof PyAssignmentStatement ? ((PyAssignmentStatement) parent).getAssignedValue() : (PyExpression) element; operation.setInitializer(initializer); if (initializer != null) { operation.setOccurrences(getOccurrences(element, initializer)); operation.setSuggestedNames(getSuggestedNames(initializer)); } if (operation.getOccurrences().size() == 0) { operation.setReplaceAll(false); } performActionOnElementOccurrences(operation); }
public void performAction(IntroduceOperation operation) { final PsiFile file = operation.getFile(); if (!CommonRefactoringUtil.checkReadOnlyStatus(file)) { return; } final Editor editor = operation.getEditor(); if (editor.getSettings().isVariableInplaceRenameEnabled()) { final TemplateState templateState = TemplateManagerImpl.getTemplateState(operation.getEditor()); if (templateState != null && !templateState.isFinished()) { return; } } PsiElement element1 = null; PsiElement element2 = null; final SelectionModel selectionModel = editor.getSelectionModel(); boolean singleElementSelection = false; if (selectionModel.hasSelection()) { element1 = file.findElementAt(selectionModel.getSelectionStart()); element2 = file.findElementAt(selectionModel.getSelectionEnd() - 1); if (element1 instanceof PsiWhiteSpace) { int startOffset = element1.getTextRange().getEndOffset(); element1 = file.findElementAt(startOffset); } if (element2 instanceof PsiWhiteSpace) { int endOffset = element2.getTextRange().getStartOffset(); element2 = file.findElementAt(endOffset - 1); } if (element1 == element2) { singleElementSelection = true; } } else { if (smartIntroduce(operation)) { return; } final CaretModel caretModel = editor.getCaretModel(); final Document document = editor.getDocument(); int lineNumber = document.getLineNumber(caretModel.getOffset()); if ((lineNumber >= 0) && (lineNumber < document.getLineCount())) { element1 = file.findElementAt(document.getLineStartOffset(lineNumber)); element2 = file.findElementAt(document.getLineEndOffset(lineNumber) - 1); } } final Project project = operation.getProject(); if (element1 == null || element2 == null) { showCannotPerformError(project, editor); return; } element1 = PyRefactoringUtil.getSelectedExpression(project, file, element1, element2); if (element1 == null) { showCannotPerformError(project, editor); return; } if (singleElementSelection && element1 instanceof PyStringLiteralExpression) { final PyStringLiteralExpression literal = (PyStringLiteralExpression) element1; // Currently introduce for substrings of a multi-part string literals is not supported if (literal.getStringNodes().size() > 1) { showCannotPerformError(project, editor); return; } final int offset = element1.getTextOffset(); final TextRange selectionRange = TextRange.create(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); final TextRange elementRange = element1.getTextRange(); if (!elementRange.equals(selectionRange) && elementRange.contains(selectionRange)) { final TextRange innerRange = literal.getStringValueTextRange(); final TextRange intersection = selectionRange.shiftRight(-offset).intersection(innerRange); final TextRange finalRange = intersection != null ? intersection : selectionRange; final String text = literal.getText(); if (getFormatValueExpression(literal) != null && breaksStringFormatting(text, finalRange) || getNewStyleFormatValueExpression(literal) != null && breaksNewStyleStringFormatting(text, finalRange) || breaksStringEscaping(text, finalRange)) { showCannotPerformError(project, editor); return; } element1.putUserData( PyReplaceExpressionUtil.SELECTION_BREAKS_AST_NODE, Pair.create(element1, finalRange)); } } if (!checkIntroduceContext(file, editor, element1)) { return; } operation.setElement(element1); performActionOnElement(operation); }