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);
  }