private static void replaceByTagContent(Project project, XmlTag tagToReplace, XmlTag tagToInline)
      throws AndroidRefactoringErrorException {
    final ASTNode node = tagToInline.getNode();

    if (node == null) {
      throw new AndroidRefactoringErrorException();
    }
    final ASTNode startTagEnd = XmlChildRole.START_TAG_END_FINDER.findChild(node);
    final ASTNode closingTagStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(node);

    if (startTagEnd == null || closingTagStart == null) {
      throw new AndroidRefactoringErrorException();
    }
    final int contentStart = startTagEnd.getTextRange().getEndOffset();
    final int contentEnd = closingTagStart.getTextRange().getStartOffset();

    if (contentStart < 0 || contentEnd < 0 || contentStart >= contentEnd) {
      throw new AndroidRefactoringErrorException();
    }
    final PsiFile file = tagToInline.getContainingFile();

    if (file == null) {
      throw new AndroidRefactoringErrorException();
    }
    final String textToInline = file.getText().substring(contentStart, contentEnd).trim();
    final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
    final Document document = documentManager.getDocument(tagToReplace.getContainingFile());

    if (document == null) {
      throw new AndroidRefactoringErrorException();
    }
    final TextRange range = tagToReplace.getTextRange();
    document.replaceString(range.getStartOffset(), range.getEndOffset(), textToInline);
    documentManager.commitDocument(document);
  }
 private static void generateRaw(final @NotNull XmlTag newTag) {
   XmlElementDescriptor selected = newTag.getDescriptor();
   if (selected == null) return;
   switch (selected.getContentType()) {
     case XmlElementDescriptor.CONTENT_TYPE_EMPTY:
       newTag.collapseIfEmpty();
       ASTNode node = newTag.getNode();
       assert node != null;
       ASTNode elementEnd = node.findChildByType(XmlTokenType.XML_EMPTY_ELEMENT_END);
       if (elementEnd == null) {
         LeafElement emptyTagEnd =
             Factory.createSingleLeafElement(
                 XmlTokenType.XML_EMPTY_ELEMENT_END, "/>", 0, 2, null, newTag.getManager());
         node.addChild(emptyTagEnd);
       }
       break;
     case XmlElementDescriptor.CONTENT_TYPE_MIXED:
       newTag.getValue().setText("");
   }
   for (XmlAttributeDescriptor descriptor : selected.getAttributesDescriptors(newTag)) {
     if (descriptor.isRequired()) {
       newTag.setAttribute(descriptor.getName(), "");
     }
   }
   List<XmlElementDescriptor> tags = getRequiredSubTags(selected);
   for (XmlElementDescriptor descriptor : tags) {
     if (descriptor == null) {
       XmlTag tag =
           XmlElementFactory.getInstance(newTag.getProject())
               .createTagFromText("<", newTag.getLanguage());
       newTag.addSubTag(tag, false);
     } else {
       XmlTag subTag = newTag.addSubTag(createTag(newTag, descriptor), false);
       generateRaw(subTag);
     }
   }
 }
 @Nullable
 private static Pair<TextRange, TextRange> getTagRanges(XmlTag tag) {
   final ASTNode tagNode = tag.getNode();
   return new Pair<TextRange, TextRange>(getStartTagRange(tagNode), getEndTagRange(tagNode));
 }
 @NotNull
 private static Pair<TextRange, TextRange> getTagRanges(XmlTag tag) {
   final ASTNode tagNode = tag.getNode();
   return Pair.create(getStartTagRange(tagNode), getEndTagRange(tagNode));
 }