private static void doFix(@NotNull final PsiElement element) throws IncorrectOperationException { final XmlToken endNameToken = (XmlToken)element; final PsiElement tagElement = endNameToken.getParent(); if (!(tagElement instanceof XmlTag) && !(tagElement instanceof PsiErrorElement)) return; if (tagElement instanceof PsiErrorElement) { tagElement.delete(); } else { final ASTNode astNode = tagElement.getNode(); if (astNode != null) { final ASTNode endTagStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(astNode); if (endTagStart != null) { final Document document = PsiDocumentManager.getInstance(element.getProject()).getDocument(tagElement.getContainingFile()); if (document != null) { document.deleteString(endTagStart.getStartOffset(), tagElement.getLastChild().getTextRange().getEndOffset()); } } } } }
@Override @NotNull public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { return new XmlElementVisitor() { @Override public void visitXmlTag(final XmlTag tag) { if (!isTagWithEmptyEndNotAllowed(tag)) { return; } final ASTNode child = XmlChildRole.EMPTY_TAG_END_FINDER.findChild(tag.getNode()); if (child == null) { return; } final LocalQuickFix fix = new MyLocalQuickFix(); holder.registerProblem(tag, XmlBundle.message("html.inspections.check.empty.script.message"), tag.getContainingFile().getContext() != null ? ProblemHighlightType.INFORMATION: ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fix); } }; }
@Override @NotNull public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { return new XmlElementVisitor() { @Override public void visitXmlTag(final XmlTag tag) { if (!CheckEmptyTagInspection.isTagWithEmptyEndNotAllowed(tag)) { final ASTNode child = XmlChildRole.START_TAG_END_FINDER.findChild(tag.getNode()); if (child != null) { final ASTNode node = child.getTreeNext(); if (node != null && node.getElementType() == XmlTokenType.XML_END_TAG_START) { final LocalQuickFix localQuickFix = new Fix(); holder.registerProblem( tag, XmlBundle.message("xml.inspections.tag.empty.body"), isCollapsibleTag(tag) ? localQuickFix : null ); } } } } }; }
@Override public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) { final PsiElement tag = descriptor.getPsiElement(); if (!FileModificationService.getInstance().prepareFileForWrite(tag.getContainingFile())) { return; } PsiDocumentManager.getInstance(project).commitAllDocuments(); final ASTNode child = XmlChildRole.START_TAG_END_FINDER.findChild(tag.getNode()); if (child == null) return; final int offset = child.getTextRange().getStartOffset(); VirtualFile file = tag.getContainingFile().getVirtualFile(); final Document document = FileDocumentManager.getInstance().getDocument(file); new WriteCommandAction(project) { @Override protected void run(@NotNull final Result result) throws Throwable { document.replaceString(offset, tag.getTextRange().getEndOffset(),"/>"); } }.execute(); }
@Override public int getChildRole(ASTNode child) { LOG.assertTrue(child.getTreeParent() == this); IElementType i = child.getElementType(); if (i == XML_CONTENT_ANY) { return XmlChildRole.XML_CONTENT_ANY; } else if (i == XML_CONTENT_EMPTY) { return XmlChildRole.XML_CONTENT_EMPTY; } else if (i == XML_PCDATA) { return XmlChildRole.XML_PCDATA; } else { return ChildRoleBase.NONE; } }
@Nullable private static TextRange getStartTagRange(ASTNode tagNode) { final ASTNode startTagStart = XmlChildRole.START_TAG_START_FINDER.findChild(tagNode); if (startTagStart == null) { return null; } ASTNode tagName = startTagStart.getTreeNext(); if (tagName == null || tagName.getElementType() != XmlTokenType.XML_NAME) { return null; } ASTNode next = tagName.getTreeNext(); if (next != null && next.getElementType() == XmlTokenType.XML_TAG_END) { tagName = next; } return new TextRange(startTagStart.getStartOffset(), tagName.getTextRange().getEndOffset()); }
@Nullable private static TextRange getEndTagRange(ASTNode tagNode) { final ASTNode endTagStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(tagNode); if (endTagStart == null) { return null; } ASTNode endTagEnd = endTagStart; while (endTagEnd != null && endTagEnd.getElementType() != XmlTokenType.XML_TAG_END) { endTagEnd = endTagEnd.getTreeNext(); } if (endTagEnd == null) { return null; } return new TextRange(endTagStart.getStartOffset(), endTagEnd.getTextRange().getEndOffset()); }
@Override public PsiElement collectAffectedElements(PsiElement element, List<PsiElement> toExtract) { final TextRange range = element.getTextRange(); final ASTNode startTagNameEnd = XmlChildRole.START_TAG_END_FINDER.findChild(element.getNode()); final ASTNode endTagNameStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(element.getNode()); int start = startTagNameEnd != null ? startTagNameEnd.getTextRange().getEndOffset() : range.getStartOffset(); int end = endTagNameStart != null ? endTagNameStart.getTextRange().getStartOffset() : range.getEndOffset(); for (PsiElement child : element.getChildren()) { final TextRange childRange = child.getTextRange(); if (childRange.getStartOffset() >= start && childRange.getEndOffset() <= end) { toExtract.add(child); } } return element; }
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { if (!XsltSupport.isXsltFile(file)) return false; final int offset = editor.getCaretModel().getOffset(); final PsiElement element = file.findElementAt(offset); final XmlAttribute attr = PsiTreeUtil.getParentOfType(element, XmlAttribute.class, false); if (attr == null || attr.getValueElement() == null) { return false; } if (XsltSupport.isXsltTag(attr.getParent())) { return false; } final ASTNode node = attr.getNode(); if (node == null) return false; final ASTNode nameNode = XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(node); if (nameNode == null) { return false; } else { return nameNode.getTextRange().contains(offset); } }
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { if (!XsltSupport.isXsltFile(file)) return false; final int offset = editor.getCaretModel().getOffset(); final PsiElement element = file.findElementAt(offset); if (element == null) return false; final XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class); if (tag == null || tag.getParentTag() == null) return false; if (!tag.getLocalName().equals("if") || !XsltSupport.isXsltTag(tag)) return false; if (tag.getAttributeValue("test") == null) return false; final ASTNode node = tag.getNode(); if (node == null) return false; final ASTNode child = XmlChildRole.START_TAG_NAME_FINDER.findChild(node); return child != null && child.getTextRange().contains(offset); }
protected static boolean isAvailableAt(PsiElement element, XmlTag tag, int offset) { final ASTNode node = tag.getNode(); if (node != null) { final ASTNode child = XmlChildRole.START_TAG_NAME_FINDER.findChild(node); if (child != null && child.getTextRange().contains(offset)) { return true; } } // final XmlAttribute att = PsiTreeUtil.getParentOfType(element, XmlAttribute.class); // if (att != null && "name".equals(att.getName()) && att.getValueElement() != null) { // return att.getValueElement().getTextRange().contains(offset); // } return false; }
public int getChildRole(ASTNode child) { LOG.assertTrue(child.getTreeParent() == this); IElementType i = child.getElementType(); if (i == XML_CONTENT_ANY) { return XmlChildRole.XML_CONTENT_ANY; } else if (i == XML_CONTENT_EMPTY) { return XmlChildRole.XML_CONTENT_EMPTY; } else if (i == XML_PCDATA) { return XmlChildRole.XML_PCDATA; } else { return ChildRoleBase.NONE; } }
@NotNull public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { return new XmlElementVisitor() { @Override public void visitXmlTag(final XmlTag tag) { if (!isTagWithEmptyEndNotAllowed(tag)) { return; } final ASTNode child = XmlChildRole.EMPTY_TAG_END_FINDER.findChild(tag.getNode()); if (child == null) { return; } final LocalQuickFix fix = new MyLocalQuickFix(); holder.registerProblem(tag, XmlBundle.message("html.inspections.check.empty.script.message"), tag.getContainingFile().getContext() != null ? ProblemHighlightType.INFORMATION: ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fix); } }; }
@NotNull public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { return new XmlElementVisitor() { @Override public void visitXmlTag(final XmlTag tag) { if (!CheckEmptyTagInspection.isTagWithEmptyEndNotAllowed(tag)) { final ASTNode child = XmlChildRole.START_TAG_END_FINDER.findChild(tag.getNode()); if (child != null) { final ASTNode node = child.getTreeNext(); if (node != null && node.getElementType() == XmlTokenType.XML_END_TAG_START) { final LocalQuickFix localQuickFix = new ReplaceEmptyTagBodyByEmptyEndFix(); holder.registerProblem( tag, XmlBundle.message("xml.inspections.tag.empty.body"), isCollapsableTag(tag) ? localQuickFix : null ); } } } } }; }
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) { final PsiElement tag = descriptor.getPsiElement(); if (!FileModificationService.getInstance().prepareFileForWrite(tag.getContainingFile())) { return; } PsiDocumentManager.getInstance(project).commitAllDocuments(); final ASTNode child = XmlChildRole.START_TAG_END_FINDER.findChild(tag.getNode()); if (child == null) return; final int offset = child.getTextRange().getStartOffset(); VirtualFile file = tag.getContainingFile().getVirtualFile(); final Document document = FileDocumentManager.getInstance().getDocument(file); new WriteCommandAction(project) { protected void run(final Result result) throws Throwable { document.replaceString(offset, tag.getTextRange().getEndOffset(),"/>"); } }.execute(); }
@Override public int getChildRole(ASTNode child) { LOG.assertTrue(child.getTreeParent() == this); IElementType i = child.getElementType(); if(i == XmlElementType.XML_PROLOG) { return XmlChildRole.XML_PROLOG; } else if(i == XmlElementType.XML_TAG) { return XmlChildRole.XML_TAG; } else { return ChildRoleBase.NONE; } }
@Nullable private static TextRange getStartTagRange(ASTNode tagNode) { final ASTNode startTagStart = XmlChildRole.START_TAG_START_FINDER.findChild(tagNode); if(startTagStart == null) { return null; } ASTNode tagName = startTagStart.getTreeNext(); if(tagName == null || tagName.getElementType() != XmlTokenType.XML_NAME) { return null; } ASTNode next = tagName.getTreeNext(); if(next != null && next.getElementType() == XmlTokenType.XML_TAG_END) { tagName = next; } return new TextRange(startTagStart.getStartOffset(), tagName.getTextRange().getEndOffset()); }
@Nullable private static TextRange getEndTagRange(ASTNode tagNode) { final ASTNode endTagStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(tagNode); if(endTagStart == null) { return null; } ASTNode endTagEnd = endTagStart; while(endTagEnd != null && endTagEnd.getElementType() != XmlTokenType.XML_TAG_END) { endTagEnd = endTagEnd.getTreeNext(); } if(endTagEnd == null) { return null; } return new TextRange(endTagStart.getStartOffset(), endTagEnd.getTextRange().getEndOffset()); }
@Override public void apply(Editor editor, JavaSmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException { if (psiElement instanceof XmlTag) { final ASTNode emptyTagEnd = XmlChildRole.EMPTY_TAG_END_FINDER.findChild(psiElement.getNode()); final ASTNode endTagEnd = XmlChildRole.START_TAG_END_FINDER.findChild(psiElement.getNode()); if (emptyTagEnd != null || endTagEnd != null) return; int insertionOffset = psiElement.getTextRange().getEndOffset(); Document doc = editor.getDocument(); final int caretAt = editor.getCaretModel().getOffset(); final CharSequence text = doc.getCharsSequence(); final int probableCommaOffset = CharArrayUtil.shiftForward(text, insertionOffset, " \t"); //if (caretAt < probableCommaOffset) { // final CharSequence tagName = text.subSequence(psiElement.getTextRange().getStartOffset() + 1, caretAt); // doc.insertString(caretAt, ">"); // doc.insertString(probableCommaOffset + 1, "</" + tagName + ">"); // return; //} char ch; if (probableCommaOffset >= text.length() || ( (ch = text.charAt(probableCommaOffset)) != '/' && ch != '>' ) ) { doc.insertString(insertionOffset, "/>"); } } }
@Override public int getChildRole(ASTNode child) { LOG.assertTrue(child.getTreeParent() == this); if (child.getElementType() == HTML_DOCUMENT) { return XmlChildRole.HTML_DOCUMENT; } else { return ChildRoleBase.NONE; } }
@Override public int getChildRole(ASTNode child) { LOG.assertTrue(child.getTreeParent() == this); if (child.getElementType() == XML_DOCUMENT || child.getElementType() == HTML_DOCUMENT) { return XmlChildRole.XML_DOCUMENT; } else { return ChildRoleBase.NONE; } }
@Override public int getChildRole(ASTNode child) { LOG.assertTrue(child.getTreeParent() == this); if (child.getElementType() == XML_DOCTYPE) { return XmlChildRole.XML_DOCTYPE; } else { return ChildRoleBase.NONE; } }
protected static TextRange xmlAttributeValueRange(final XmlAttributeValue xmlAttributeValue) { ASTNode valueNode = XmlChildRole.ATTRIBUTE_VALUE_VALUE_FINDER.findChild(xmlAttributeValue.getNode()); PsiElement toHighlight = valueNode == null ? xmlAttributeValue : valueNode.getPsi(); TextRange childRange = toHighlight.getTextRange(); TextRange range = xmlAttributeValue.getTextRange(); return childRange.shiftRight(-range.getStartOffset()); }
@Override public List<PsiElement> unwrap(Editor editor, PsiElement element) throws IncorrectOperationException { final TextRange range = element.getTextRange(); final ASTNode startTagNameEnd = XmlChildRole.START_TAG_END_FINDER.findChild(element.getNode()); final ASTNode endTagNameStart = XmlChildRole.CLOSING_TAG_START_FINDER.findChild(element.getNode()); if (endTagNameStart != null) { editor.getDocument().replaceString(endTagNameStart.getTextRange().getStartOffset(), range.getEndOffset(), ""); editor.getDocument().replaceString(range.getStartOffset(), startTagNameEnd.getTextRange().getEndOffset(), ""); } else { editor.getDocument().replaceString(range.getStartOffset(), range.getEndOffset(), ""); } return Collections.emptyList(); }
@NotNull @Override public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { if (!(element instanceof XmlTag)) { return PsiReference.EMPTY_ARRAY; } final Module module = ModuleUtilCore.findModuleForPsiElement(element); if (module == null || AndroidFacet.getInstance(module) == null) { return PsiReference.EMPTY_ARRAY; } final ASTNode startTagName = XmlChildRole.START_TAG_NAME_FINDER.findChild(element.getNode()); final String baseClassQName = computeBaseClass((XmlTag)element); if (baseClassQName == null) { return PsiReference.EMPTY_ARRAY; } final List<PsiReference> result = new ArrayList<PsiReference>(); final XmlTag tag = (XmlTag)element; if (startTagName != null && areReferencesProvidedByReferenceProvider(startTagName)) { addReferences(tag, startTagName.getPsi(), result, module, baseClassQName, true); } final ASTNode closingTagName = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(element.getNode()); if (closingTagName != null && areReferencesProvidedByReferenceProvider(closingTagName)) { addReferences(tag, closingTagName.getPsi(), result, module, baseClassQName, false); } return result.toArray(new PsiReference[result.size()]); }
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); }