@Override
  public void visitField(PsiField field) {
    // There is a possible case that more than one field is declared for the same type like 'int i,
    // j;'. We want to process only
    // the first one then.
    PsiElement fieldPrev = getPreviousNonWsComment(field.getPrevSibling(), 0);
    if (fieldPrev instanceof PsiJavaToken
        && ((PsiJavaToken) fieldPrev).getTokenType() == JavaTokenType.COMMA) {
      return;
    }

    // There is a possible case that fields which share the same type declaration are located on
    // different document lines, e.g.:
    //    int i1,
    //        i2;
    // We want to consider only the first declaration then but need to expand its range to all
    // affected lines (up to semicolon).
    TextRange range = field.getTextRange();
    PsiElement child = field.getLastChild();
    boolean needSpecialProcessing = true;
    if (isSemicolon(child)) {
      needSpecialProcessing = false;
    } else if (child instanceof PsiComment) {
      // There is a possible field definition like below:
      //   int f; // my comment.
      // The comment goes into field PSI here, that's why we need to handle it properly.
      PsiElement prev = getPreviousNonWsComment(child, range.getStartOffset());
      needSpecialProcessing = prev != null && !isSemicolon(prev);
    }

    if (needSpecialProcessing) {
      for (PsiElement e = field.getNextSibling(); e != null; e = e.getNextSibling()) {
        if (e instanceof PsiWhiteSpace || e instanceof PsiComment) { // Skip white space and comment
          continue;
        } else if (e instanceof PsiJavaToken) {
          if (((PsiJavaToken) e).getTokenType() == JavaTokenType.COMMA) { // Skip comma
            continue;
          } else {
            break;
          }
        } else if (e instanceof PsiField) {
          PsiElement c = e.getLastChild();
          if (c != null) {
            c = getPreviousNonWsComment(c, range.getStartOffset());
          }
          // Stop if current field ends by a semicolon.
          if (c instanceof PsiErrorElement // Incomplete field without trailing semicolon
              || (c instanceof PsiJavaToken
                  && ((PsiJavaToken) c).getTokenType() == JavaTokenType.SEMICOLON)) {
            range = TextRange.create(range.getStartOffset(), c.getTextRange().getEndOffset());
          } else {
            continue;
          }
        }
        break;
      }
    }
    JavaElementArrangementEntry entry = createNewEntry(field, range, FIELD, field.getName(), true);
    processEntry(entry, field, field.getInitializer());
  }
Esempio n. 2
0
 @Override
 public boolean flip(PsiElement left, PsiElement right) {
   if (left instanceof PsiVariable && right instanceof PsiVariable) {
     final PsiElement first = left.getFirstChild();
     if (!(first instanceof PsiModifierList)) {
       return false;
     }
     final PsiElement child = PsiTreeUtil.skipSiblingsForward(first, PsiWhiteSpace.class);
     if (!(child instanceof PsiTypeElement)) {
       return false;
     }
     final PsiElement last = child.getNextSibling();
     if (!(last instanceof PsiWhiteSpace)) {
       return false;
     }
     final PsiElement anchor = right.getFirstChild();
     if (!(anchor instanceof PsiIdentifier)) {
       return false;
     }
     final PsiElement semiColon = right.getLastChild();
     if (!(semiColon instanceof PsiJavaToken)) {
       return false;
     }
     right.addRangeBefore(first, last, anchor);
     left.deleteChildRange(first, last);
     left.add(semiColon);
     semiColon.delete();
     final PsiElement copy = left.copy();
     left.replace(right);
     right.replace(copy);
     return true;
   }
   return false;
 }
  private static void generateElseBranchTextAndRemoveTailStatements(
      @NotNull GrIfStatement ifStatement, @NotNull GrIfStatement newIf) {
    final GrStatement thenBranch = newIf.getThenBranch();
    assert thenBranch != null;

    GrStatement elseBranch = ifStatement.getElseBranch();
    if (elseBranch != null) {
      thenBranch.replaceWithStatement(elseBranch);
      return;
    }

    PsiElement parent = ifStatement.getParent();
    if (!(parent instanceof GrStatementOwner)) return;

    if (!isTailAfterIf(ifStatement, ((GrStatementOwner) parent))) return;

    final PsiElement start = ifStatement.getNextSibling();
    PsiElement end =
        parent instanceof GrCodeBlock
            ? ((GrCodeBlock) parent).getRBrace().getPrevSibling()
            : parent.getLastChild();

    final GrOpenBlock block = ((GrBlockStatement) thenBranch).getBlock();
    block.addRangeAfter(start, end, block.getLBrace());
    parent.deleteChildRange(start, end);
  }
  public static void initOffsets(final PsiFile file, final OffsetMap offsetMap) {
    int offset =
        Math.max(
            offsetMap.getOffset(CompletionInitializationContext.SELECTION_END_OFFSET),
            offsetMap.getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET));

    PsiElement element = file.findElementAt(offset);
    if (element instanceof PsiWhiteSpace
        && (!element.textContains('\n')
            || CodeStyleSettingsManager.getSettings(file.getProject())
                .getCommonSettings(JavaLanguage.INSTANCE)
                .METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE)) {
      element = file.findElementAt(element.getTextRange().getEndOffset());
    }
    if (element == null) return;

    if (LEFT_PAREN.accepts(element)) {
      offsetMap.addOffset(LPAREN_OFFSET, element.getTextRange().getStartOffset());
      PsiElement list = element.getParent();
      PsiElement last = list.getLastChild();
      if (last instanceof PsiJavaToken
          && ((PsiJavaToken) last).getTokenType() == JavaTokenType.RPARENTH) {
        offsetMap.addOffset(RPAREN_OFFSET, last.getTextRange().getStartOffset());
      }

      offsetMap.addOffset(ARG_LIST_END_OFFSET, list.getTextRange().getEndOffset());
    }
  }
 private static boolean isBlockElement(@NotNull PsiElement element) {
   PsiElement firstChild = element.getFirstChild();
   PsiElement lastChild = element.getLastChild();
   return firstChild != null
       && "{".equals(firstChild.getText())
       && lastChild != null
       && "}".equals(lastChild.getText());
 }
 private String replaceParamsWithArgs(
     Project project, JSArgumentList argumentList, PsiElement signal) {
   String signalText = signal.getLastChild().getText();
   String signalHandlerName =
       "on"
           + signalText.substring(0, 1).toUpperCase()
           + signalText.substring(1, signalText.length());
   PsiElement signalHandler =
       JSChangeUtil.createJSTreeFromText(project, "(" + signalHandlerName + ")").getPsi();
   argumentList.replace(signalHandler);
   return signalHandlerName;
 }
  @Nullable
  public static String getNameByReference(@Nullable PsiElement expression) {
    if (!(expression instanceof GrReferenceExpression)) return null;

    PsiElement firstChild = expression.getFirstChild();
    if (firstChild != expression.getLastChild()
        || !PsiImplUtil.isLeafElementOfType(firstChild, GroovyTokenTypes.mIDENT)) return null;

    GrReferenceExpression ref = (GrReferenceExpression) expression;
    if (ref.isQualified()) return null;

    return ref.getReferenceName();
  }
Esempio n. 8
0
  public static boolean processChildren(
      PsiElement element,
      PsiScopeProcessor processor,
      ResolveState substitutor,
      PsiElement lastParent,
      PsiElement place) {
    PsiElement run = lastParent == null ? element.getLastChild() : lastParent.getPrevSibling();
    while (run != null) {
      if (PsiTreeUtil.findCommonParent(place, run) != run
          && !run.processDeclarations(processor, substitutor, null, place)) return false;
      run = run.getPrevSibling();
    }

    return true;
  }
Esempio n. 9
0
  @Nullable
  private static PsiElement getMovableElement(@NotNull PsiElement element, boolean lookRight) {
    //noinspection unchecked
    PsiElement movableElement =
        PsiUtilPackage.getParentByTypesAndPredicate(
            element, false, MOVABLE_ELEMENT_CLASSES, MOVABLE_ELEMENT_CONSTRAINT);
    if (movableElement == null) return null;

    if (isBracelessBlock(movableElement)) {
      movableElement =
          firstNonWhiteElement(
              lookRight ? movableElement.getLastChild() : movableElement.getFirstChild(),
              !lookRight);
    }

    return movableElement;
  }
  private static PsiElement getMatchExpr(PsiElement replacement, PsiElement elementToReplace) {
    if (replacement instanceof PsiExpressionStatement
        && !(replacement.getLastChild() instanceof PsiJavaToken)
        && !(replacement.getLastChild() instanceof PsiComment)) {
      // replacement is expression (and pattern should be so)
      // assert ...
      replacement = ((PsiExpressionStatement) replacement).getExpression();
    } else if (replacement instanceof PsiDeclarationStatement
        && ((PsiDeclarationStatement) replacement).getDeclaredElements().length == 1) {
      return ((PsiDeclarationStatement) replacement).getDeclaredElements()[0];
    } else if (replacement instanceof PsiBlockStatement
        && elementToReplace instanceof PsiCodeBlock) {
      return ((PsiBlockStatement) replacement).getCodeBlock();
    }

    return replacement;
  }
  /** "DateTime", DateTime::class */
  @Nullable
  public static PhpClass resolvePhpClassOnPsiElement(@NotNull PsiElement psiElement) {

    String dataClass = null;
    if (psiElement instanceof ClassConstantReference) {
      PsiElement lastChild = psiElement.getLastChild();
      // @TODO: FOO::class find PhpElementTyp: toString provides "class"
      if ("class".equals(lastChild.getText())) {
        PhpExpression classReference = ((ClassConstantReference) psiElement).getClassReference();
        if (classReference instanceof PhpReference) {
          dataClass = ((PhpReference) classReference).getFQN();
        }
      }
    } else {
      dataClass = getStringValue(psiElement);
    }

    if (dataClass == null) {
      return null;
    }

    return getClassInterface(psiElement.getProject(), dataClass);
  }
Esempio n. 12
0
 @Nullable
 public static PsiExpression findExpressionInRange(PsiFile file, int startOffset, int endOffset) {
   if (!file.getViewProvider().getLanguages().contains(StdLanguages.JAVA)) return null;
   PsiExpression expression =
       findElementInRange(file, startOffset, endOffset, PsiExpression.class);
   if (expression == null && findStatementsInRange(file, startOffset, endOffset).length == 0) {
     PsiElement element2 = file.getViewProvider().findElementAt(endOffset - 1, StdLanguages.JAVA);
     if (element2 instanceof PsiJavaToken) {
       final PsiJavaToken token = (PsiJavaToken) element2;
       final IElementType tokenType = token.getTokenType();
       if (tokenType.equals(JavaTokenType.SEMICOLON)) {
         expression =
             findElementInRange(
                 file, startOffset, element2.getTextRange().getStartOffset(), PsiExpression.class);
       }
     }
   }
   if (expression == null && findStatementsInRange(file, startOffset, endOffset).length == 0) {
     PsiElement element =
         PsiTreeUtil.skipSiblingsBackward(file.findElementAt(endOffset), PsiWhiteSpace.class);
     if (element != null) {
       element =
           PsiTreeUtil.skipSiblingsBackward(
               element.getLastChild(), PsiWhiteSpace.class, PsiComment.class);
       if (element != null) {
         final int newEndOffset = element.getTextRange().getEndOffset();
         if (newEndOffset < endOffset) {
           expression = findExpressionInRange(file, startOffset, newEndOffset);
         }
       }
     }
   }
   if (expression instanceof PsiReferenceExpression
       && expression.getParent() instanceof PsiMethodCallExpression) return null;
   return expression;
 }
Esempio n. 13
0
  public Result beforeCharTyped(
      final char c,
      final Project project,
      final Editor editor,
      final PsiFile editedFile,
      final FileType fileType) {
    final XmlEditorOptions xmlEditorOptions = XmlEditorOptions.getInstance();
    if (c == '>'
        && xmlEditorOptions != null
        && xmlEditorOptions.isAutomaticallyInsertClosingTag()
        && (editedFile.getLanguage() instanceof XMLLanguage
            || editedFile.getViewProvider().getBaseLanguage() instanceof XMLLanguage)) {
      PsiDocumentManager.getInstance(project).commitAllDocuments();

      PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
      FileViewProvider provider = editedFile.getViewProvider();
      int offset = editor.getCaretModel().getOffset();

      PsiElement element, elementAtCaret = null;

      if (offset < editor.getDocument().getTextLength()) {
        elementAtCaret = element = provider.findElementAt(offset, XMLLanguage.class);

        if (!(element instanceof PsiWhiteSpace)) {
          boolean nonAcceptableDelimiter = true;

          if (element instanceof XmlToken) {
            IElementType tokenType = ((XmlToken) element).getTokenType();

            if (tokenType == XmlTokenType.XML_START_TAG_START
                || tokenType == XmlTokenType.XML_END_TAG_START) {
              if (offset > 0) {
                PsiElement previousElement = provider.findElementAt(offset - 1, XMLLanguage.class);

                if (previousElement instanceof XmlToken) {
                  tokenType = ((XmlToken) previousElement).getTokenType();
                  element = previousElement;
                  nonAcceptableDelimiter = false;
                }
              }
            } else if (tokenType == XmlTokenType.XML_NAME) {
              if (element.getNextSibling() instanceof PsiErrorElement) {
                nonAcceptableDelimiter = false;
              }
            }

            if (tokenType == XmlTokenType.XML_TAG_END
                || tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END
                    && element.getTextOffset() == offset - 1) {
              editor.getCaretModel().moveToOffset(offset + 1);
              editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
              return Result.STOP;
            }
          }
          if (nonAcceptableDelimiter) return Result.CONTINUE;
        } else {
          // check if right after empty end
          PsiElement previousElement = provider.findElementAt(offset - 1, XMLLanguage.class);
          if (previousElement instanceof XmlToken) {
            final IElementType tokenType = ((XmlToken) previousElement).getTokenType();

            if (tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END) {
              return Result.STOP;
            }
          }
        }

        PsiElement parent = element.getParent();
        if (parent instanceof XmlText) {
          final String text = parent.getText();
          // check /
          final int index = offset - parent.getTextOffset() - 1;

          if (index >= 0 && text.charAt(index) == '/') {
            return Result.CONTINUE; // already seen /
          }
          element = parent.getPrevSibling();
        } else if (parent instanceof XmlTag && !(element.getPrevSibling() instanceof XmlTag)) {
          element = parent;
        } else if (parent instanceof XmlAttributeValue) {
          element = parent;
        }
      } else {
        element =
            provider.findElementAt(editor.getDocument().getTextLength() - 1, XMLLanguage.class);
        if (element == null) return Result.CONTINUE;
        element = element.getParent();
      }

      if (offset > 0 && offset <= editor.getDocument().getTextLength()) {
        if (editor.getDocument().getCharsSequence().charAt(offset - 1)
            == '/') { // Some languages (e.g. GSP) allow character '/' in tag name.
          return Result.CONTINUE;
        }
      }

      if (element instanceof XmlAttributeValue) {
        element = element.getParent().getParent();
      }

      while (element instanceof PsiWhiteSpace) element = element.getPrevSibling();
      if (element instanceof XmlDocument) { // hack for closing tags in RHTML
        element = element.getLastChild();
      }
      if (element == null) return Result.CONTINUE;
      if (!(element instanceof XmlTag)) {
        if (element instanceof XmlTokenImpl
            && element.getPrevSibling() != null
            && element.getPrevSibling().getText().equals("<")) {
          // tag is started and there is another text in the end
          editor.getDocument().insertString(offset, "</" + element.getText() + ">");
        }
        return Result.CONTINUE;
      }

      XmlTag tag = (XmlTag) element;
      if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_TAG_END) != null) return Result.CONTINUE;
      if (XmlUtil.getTokenOfType(tag, XmlTokenType.XML_EMPTY_ELEMENT_END) != null)
        return Result.CONTINUE;
      final XmlToken startToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_START_TAG_START);
      if (startToken == null || !startToken.getText().equals("<")) return Result.CONTINUE;

      String name = tag.getName();
      if (elementAtCaret instanceof XmlToken
          && ((XmlToken) elementAtCaret).getTokenType() == XmlTokenType.XML_NAME) {
        name = name.substring(0, offset - elementAtCaret.getTextOffset());
      }
      if (tag instanceof HtmlTag && HtmlUtil.isSingleHtmlTag(name)) return Result.CONTINUE;
      if ("".equals(name)) return Result.CONTINUE;

      int tagOffset = tag.getTextRange().getStartOffset();

      final XmlToken nameToken = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_NAME);
      if (nameToken != null && nameToken.getTextRange().getStartOffset() > offset)
        return Result.CONTINUE;

      HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(tagOffset);
      if (BraceMatchingUtil.matchBrace(
          editor.getDocument().getCharsSequence(),
          editedFile.getFileType(),
          iterator,
          true,
          true)) {
        PsiElement parent = tag.getParent();
        boolean hasBalance = true;

        while (parent instanceof XmlTag && name.equals(((XmlTag) parent).getName())) {
          ASTNode astNode = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(parent.getNode());
          if (astNode == null) {
            hasBalance = false;
            break;
          }

          parent = parent.getParent();
        }

        if (hasBalance) {
          hasBalance = false;
          for (ASTNode node = parent.getNode().getLastChildNode();
              node != null;
              node = node.getTreePrev()) {
            ASTNode leaf = node;
            if (leaf.getElementType() == TokenType.ERROR_ELEMENT) {
              ASTNode firstChild = leaf.getFirstChildNode();
              if (firstChild != null) leaf = firstChild;
              else {
                PsiElement psiElement = PsiTreeUtil.nextLeaf(leaf.getPsi());
                leaf = psiElement != null ? psiElement.getNode() : null;
              }
              if (leaf != null && leaf.getElementType() == TokenType.WHITE_SPACE) {
                PsiElement psiElement = PsiTreeUtil.nextLeaf(leaf.getPsi());
                if (psiElement != null) leaf = psiElement.getNode();
              }
            }

            if (leaf != null && leaf.getElementType() == XmlTokenType.XML_END_TAG_START) {
              ASTNode treeNext = leaf.getTreeNext();
              IElementType treeNextType;
              if (treeNext != null
                  && ((treeNextType = treeNext.getElementType()) == XmlTokenType.XML_NAME
                      || treeNextType == XmlTokenType.XML_TAG_NAME)) {
                if (name.equals(treeNext.getText())) {
                  ASTNode parentEndName =
                      parent instanceof XmlTag
                          ? XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(parent.getNode())
                          : null;
                  hasBalance =
                      !(parent instanceof XmlTag)
                          || parentEndName != null && !parentEndName.getText().equals(name);
                  break;
                }
              }
            }
          }
        }

        if (hasBalance) return Result.CONTINUE;
      }

      TextRange cdataReformatRange = null;
      final XmlElementDescriptor descriptor = tag.getDescriptor();

      if (descriptor instanceof XmlElementDescriptorWithCDataContent) {
        final XmlElementDescriptorWithCDataContent cDataContainer =
            (XmlElementDescriptorWithCDataContent) descriptor;

        if (cDataContainer.requiresCdataBracesInContext(tag)) {
          int rangeStart = offset;
          @NonNls final String cDataStart = "><![CDATA[";
          final String inserted = cDataStart + "\n]]>";
          editor.getDocument().insertString(offset, inserted);
          final int newoffset = offset + cDataStart.length();
          editor.getCaretModel().moveToOffset(newoffset);
          offset += inserted.length();
          cdataReformatRange = new TextRange(rangeStart, offset + 1);
        }
      }

      editor.getDocument().insertString(offset, "</" + name + ">");

      if (cdataReformatRange != null) {
        PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
        try {
          CodeStyleManager.getInstance(project)
              .reformatText(
                  file, cdataReformatRange.getStartOffset(), cdataReformatRange.getEndOffset());
        } catch (IncorrectOperationException e) {
          LOG.error(e);
        }
      }
      return cdataReformatRange != null ? Result.STOP : Result.CONTINUE;
    }
    return Result.CONTINUE;
  }
  public void replace(final ReplacementInfo info, ReplaceOptions options) {
    PsiElement elementToReplace = info.getMatch(0);
    PsiElement elementParent = elementToReplace.getParent();
    String replacementToMake = info.getReplacement();
    Project project = myContext.getProject();
    PsiElement el = findRealSubstitutionElement(elementToReplace);
    boolean listContext = isListContext(el);

    if (el instanceof PsiAnnotation && !StringUtil.startsWithChar(replacementToMake, '@')) {
      replacementToMake = "@" + replacementToMake;
    }

    PsiElement[] statements =
        ReplacerUtil.createTreeForReplacement(
            replacementToMake,
            el instanceof PsiMember && !isSymbolReplacement(el)
                ? PatternTreeContext.Class
                : PatternTreeContext.Block,
            myContext);

    if (listContext) {
      if (statements.length > 1) {
        elementParent.addRangeBefore(
            statements[0], statements[statements.length - 1], elementToReplace);
      } else if (statements.length == 1) {
        PsiElement replacement = getMatchExpr(statements[0], elementToReplace);

        handleModifierList(el, replacement);
        replacement = handleSymbolReplacement(replacement, el);

        if (replacement instanceof PsiTryStatement) {
          final List<PsiCatchSection> unmatchedCatchSections =
              el.getUserData(JavaMatchingVisitor.UNMATCHED_CATCH_SECTION_CONTENT_VAR_KEY);
          final PsiCatchSection[] catches = ((PsiTryStatement) replacement).getCatchSections();

          if (unmatchedCatchSections != null) {
            for (int i = unmatchedCatchSections.size() - 1; i >= 0; --i) {
              final PsiParameter parameter = unmatchedCatchSections.get(i).getParameter();
              final PsiElementFactory elementFactory =
                  JavaPsiFacade.getInstance(project).getElementFactory();
              final PsiCatchSection catchSection =
                  elementFactory.createCatchSection(parameter.getType(), parameter.getName(), null);

              catchSection.getCatchBlock().replace(unmatchedCatchSections.get(i).getCatchBlock());
              replacement.addAfter(catchSection, catches[catches.length - 1]);
              replacement.addBefore(createWhiteSpace(replacement), replacement.getLastChild());
            }
          }
        }

        try {
          final PsiElement inserted = elementParent.addBefore(replacement, elementToReplace);

          if (replacement instanceof PsiComment
              && (elementParent instanceof PsiIfStatement
                  || elementParent instanceof PsiLoopStatement)) {
            elementParent.addAfter(createSemicolon(replacement), inserted);
          }
        } catch (IncorrectOperationException e) {
          elementToReplace.replace(replacement);
        }
      }
    } else if (statements.length > 0) {
      PsiElement replacement =
          ReplacerUtil.copySpacesAndCommentsBefore(
              elementToReplace, statements, replacementToMake, elementParent);

      replacement = getMatchExpr(replacement, elementToReplace);

      if (replacement instanceof PsiStatement
          && !(replacement.getLastChild() instanceof PsiJavaToken)
          && !(replacement.getLastChild() instanceof PsiComment)) {
        // assert w/o ;
        final PsiElement prevLastChildInParent = replacement.getLastChild().getPrevSibling();

        if (prevLastChildInParent != null) {
          elementParent.addRangeBefore(replacement.getFirstChild(), prevLastChildInParent, el);
        } else {
          elementParent.addBefore(replacement.getFirstChild(), el);
        }

        el.getNode().getTreeParent().removeChild(el.getNode());
      } else {
        // preserve comments
        handleModifierList(el, replacement);

        if (replacement instanceof PsiClass) {
          // modifier list
          final PsiStatement[] searchStatements = getCodeBlock().getStatements();
          if (searchStatements.length > 0
              && searchStatements[0] instanceof PsiDeclarationStatement
              && ((PsiDeclarationStatement) searchStatements[0]).getDeclaredElements()[0]
                  instanceof PsiClass) {
            final PsiClass replaceClazz = (PsiClass) replacement;
            final PsiClass queryClazz =
                (PsiClass) ((PsiDeclarationStatement) searchStatements[0]).getDeclaredElements()[0];
            final PsiClass clazz = (PsiClass) el;

            if (replaceClazz.getExtendsList().getTextLength() == 0
                && queryClazz.getExtendsList().getTextLength() == 0
                && clazz.getExtendsList().getTextLength() != 0) {
              replaceClazz.addBefore(
                  clazz.getExtendsList().getPrevSibling(),
                  replaceClazz.getExtendsList()); // whitespace
              replaceClazz
                  .getExtendsList()
                  .addRange(
                      clazz.getExtendsList().getFirstChild(),
                      clazz.getExtendsList().getLastChild());
            }

            if (replaceClazz.getImplementsList().getTextLength() == 0
                && queryClazz.getImplementsList().getTextLength() == 0
                && clazz.getImplementsList().getTextLength() != 0) {
              replaceClazz.addBefore(
                  clazz.getImplementsList().getPrevSibling(),
                  replaceClazz.getImplementsList()); // whitespace
              replaceClazz
                  .getImplementsList()
                  .addRange(
                      clazz.getImplementsList().getFirstChild(),
                      clazz.getImplementsList().getLastChild());
            }

            if (replaceClazz.getTypeParameterList().getTextLength() == 0
                && queryClazz.getTypeParameterList().getTextLength() == 0
                && clazz.getTypeParameterList().getTextLength() != 0) {
              // skip < and >
              replaceClazz.getTypeParameterList().replace(clazz.getTypeParameterList());
            }
          }
        }

        replacement = handleSymbolReplacement(replacement, el);

        el.replace(replacement);
      }
    } else {
      final PsiElement nextSibling = el.getNextSibling();
      el.delete();
      if (nextSibling instanceof PsiWhiteSpace && nextSibling.isValid()) {
        nextSibling.delete();
      }
    }

    if (listContext) {
      final int matchSize = info.getMatchesCount();

      for (int i = 0; i < matchSize; ++i) {
        PsiElement matchElement = info.getMatch(i);
        PsiElement element = findRealSubstitutionElement(matchElement);

        if (element == null) continue;
        PsiElement firstToDelete = element;
        PsiElement lastToDelete = element;
        PsiElement prevSibling = element.getPrevSibling();
        PsiElement nextSibling = element.getNextSibling();

        if (prevSibling instanceof PsiWhiteSpace) {
          firstToDelete = prevSibling;
          prevSibling = prevSibling != null ? prevSibling.getPrevSibling() : null;
        } else if (prevSibling == null && nextSibling instanceof PsiWhiteSpace) {
          lastToDelete = nextSibling;
        }

        if (nextSibling instanceof XmlText && i + 1 < matchSize) {
          final PsiElement next = info.getMatch(i + 1);
          if (next != null && next == nextSibling.getNextSibling()) {
            lastToDelete = nextSibling;
          }
        }

        if (element instanceof PsiExpression) {
          final PsiElement parent = element.getParent().getParent();
          if ((parent instanceof PsiCall || parent instanceof PsiAnonymousClass)
              && prevSibling instanceof PsiJavaToken
              && ((PsiJavaToken) prevSibling).getTokenType() == JavaTokenType.COMMA) {
            firstToDelete = prevSibling;
          }
        } else if (element instanceof PsiParameter
            && prevSibling instanceof PsiJavaToken
            && ((PsiJavaToken) prevSibling).getTokenType() == JavaTokenType.COMMA) {
          firstToDelete = prevSibling;
        }

        element.getParent().deleteChildRange(firstToDelete, lastToDelete);
      }
    }
  }