/** * Tries to parse given element as <a href="http://msdn.microsoft.com/en-us/library/ms537512(v=vs.85).aspx">conditional comment</a>. * * @param host target element to parse * @return <code>null</code> if given element is not a conditional comment; * pair like <code>(conditional comment start element; conditional comment end element)</code> otherwise */ @Nullable private static Pair<ASTNode, ASTNode> parseConditionalCommentBoundaries(@NotNull PsiElement host) { if (!(host instanceof XmlComment)) { return null; } final ASTNode comment = host.getNode(); if (comment == null) { return null; } final ASTNode conditionalStart = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_START_END)); if (conditionalStart == null) { return null; } final ASTNode conditionalEnd = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_END_START)); if (conditionalEnd == null) { return null; } final ASTNode endOfEnd = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_END)); return endOfEnd == null ? null : Pair.create(conditionalStart, conditionalEnd); }
public static boolean isInContext(@NotNull PsiElement element) { if (PsiTreeUtil.getParentOfType(element, XmlComment.class) != null) { return false; } if (PsiTreeUtil.getParentOfType(element, XmlText.class) != null) { return true; } if (element.getNode().getElementType() == XmlTokenType.XML_START_TAG_START) { return true; } PsiElement parent = element.getParent(); if (parent instanceof PsiErrorElement) { parent = parent.getParent(); } return parent instanceof XmlDocument; }
@Nullable private static String getCommentBeforeEatComment(XmlTag tag) { PsiElement comment = XmlDocumentationProvider.findPreviousComment(tag); for (int i = 0; i < 5; ++i) { if (comment == null) { break; } String value = StringUtil.trim(XmlUtil.getCommentText((XmlComment)comment)); // This check is there to ignore "formatting" comments like the first and third lines in // <!-- ============== --> // <!-- Generic styles --> // <!-- ============== --> if (!StringUtil.isEmpty(value) && value.charAt(0) != '*' && value.charAt(0) != '=') { return value; } comment = XmlDocumentationProvider.findPreviousComment(comment.getPrevSibling()); } return null; }
/** * Tries to parse given element as <a href="http://msdn.microsoft.com/en-us/library/ms537512(v=vs.85).aspx">conditional comment</a>. * * @param host target element to parse * @return <code>null</code> if given element is not a conditional comment; * pair like <code>(conditional comment start element; conditional comment end element)</code> otherwise */ @Nullable private static Pair<ASTNode, ASTNode> parseConditionalCommentBoundaries(@NotNull PsiElement host) { if (!(host instanceof XmlComment)) { return null; } final ASTNode comment = host.getNode(); if (comment == null) { return null; } final ASTNode conditionalStart = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_START_END)); if (conditionalStart == null) { return null; } final ASTNode conditionalEnd = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_END_START)); if (conditionalEnd == null) { return null; } final ASTNode endOfEnd = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_END)); return endOfEnd == null ? null : new Pair<ASTNode, ASTNode>(conditionalStart, conditionalEnd); }
/** * Return the first child Node from the current node. If result is not null, set the current Node. */ public PsiElement firstChild() { if (currentElement == null) return null; PsiElement[] children = currentElement.getChildren(); PsiElement node = null; for(PsiElement child : children) { if(!(child instanceof XmlComment)) { node = child; break; } } //PsiElement node = currentElement.getFirstChild(); if (node != null) currentElement = node; return node; }
/** * Return the last child Node from the current node. If result is not null, set the current Node. */ public PsiElement lastChild() { if (currentElement == null) return null; PsiElement[] children = currentElement.getChildren(); PsiElement node = null; for(int i = children.length - 1; i >= 0; i--) { if(!(children[i] instanceof XmlComment)) { node = children[i]; break; } } //PsiElement node = currentElement.getLastChild(); if (node != null) currentElement = node; return node; }
/** * Return the previous sibling Node from the current node. If result is not null, set the current Node. */ public PsiElement previousSibling() { if (currentElement == null) return null; PsiElement node = currentElement.getPrevSibling(); /* Skip comment siblings */ while(node instanceof XmlComment) { node = node.getPrevSibling(); } //PsiElement node = currentElement.getPrevSibling(); if (node != null) currentElement = node; return node; }
/** * Return the next sibling Node from the current node. If result is not null, set the current Node. */ public PsiElement nextSibling() { if (currentElement == null) return null; PsiElement node = currentElement.getNextSibling(); /* Skip comment siblings */ while(node instanceof XmlComment) { node = node.getNextSibling(); } //PsiElement node = currentElement.getNextSibling(); if (node != null) currentElement = node; return node; }
private static void parseDocComment(XmlTag tag, AttributeDefinition def, @Nullable String styleable) { PsiElement comment = XmlDocumentationProvider.findPreviousComment(tag); if (comment != null) { String docValue = XmlUtil.getCommentText((XmlComment)comment); if (docValue != null && !StringUtil.isEmpty(docValue)) { def.addDocValue(docValue, styleable); } } }
private void parseAndAddValues(AttributeDefinition def, XmlTag[] values) { for (XmlTag value : values) { final String valueName = value.getAttributeValue(ATTR_NAME); if (valueName == null) { LOG.info("Unknown value for tag: " + value.getText()); } else { def.addValue(valueName); PsiElement comment = XmlDocumentationProvider.findPreviousComment(value); if (comment != null) { String docValue = XmlUtil.getCommentText((XmlComment)comment); if (!StringUtil.isEmpty(docValue)) { def.addValueDoc(valueName, docValue); } } final String strIntValue = value.getAttributeValue(ATTR_VALUE); if (strIntValue != null) { try { // Integer.decode cannot handle "ffffffff", see JDK issue 6624867 int intValue = (int) (long) Long.decode(strIntValue); Map<String, Integer> value2Int = myEnumMap.get(def.getName()); if (value2Int == null) { value2Int = new HashMap<String, Integer>(); myEnumMap.put(def.getName(), value2Int); } value2Int.put(valueName, intValue); } catch (NumberFormatException ignored) { } } } } }
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { final XmlTag anchor = getAnchor(element); if (anchor == null) return; PsiElement prevSibling = anchor.getPrevSibling(); while (prevSibling instanceof PsiWhiteSpace || prevSibling instanceof XmlText) { prevSibling = prevSibling.getPrevSibling(); } if (prevSibling instanceof XmlProlog) { prevSibling = prevSibling.getLastChild(); if (prevSibling != null && !(prevSibling instanceof XmlComment)) { prevSibling = PsiTreeUtil.getPrevSiblingOfType(prevSibling, XmlComment.class); } } if (prevSibling instanceof XmlComment) { final XmlComment comment = (XmlComment)prevSibling; final String text = XmlUtil.getCommentText(comment); if (text != null && InspectionUtil.SUPPRESSION_PATTERN.matcher(text).matches()) { final String s = text.trim() + ", " + myToolId; final XmlComment newComment = createComment(project, s); CodeStyleManager.getInstance(PsiManager.getInstance(project).getProject()).reformat(comment.replace(newComment)); } else { addNoinspectionComment(project, anchor); } } else { addNoinspectionComment(project, anchor); } }
private void addNoinspectionComment(Project project, XmlTag anchor) throws IncorrectOperationException { final XmlComment newComment = createComment(project, "noinspection " + myToolId); PsiElement parent = anchor.getParentTag(); if (parent == null) { parent = PsiTreeUtil.getPrevSiblingOfType(anchor, XmlProlog.class); if (parent != null) { CodeStyleManager.getInstance(PsiManager.getInstance(project).getProject()).reformat(parent.add(newComment)); } } else { CodeStyleManager.getInstance(PsiManager.getInstance(project).getProject()).reformat(parent.addBefore(newComment, anchor)); } }
@NotNull private static XmlComment createComment(Project project, String s) throws IncorrectOperationException { final XmlTag element = XmlElementFactory.getInstance(project).createTagFromText("<foo><!-- " + s + " --></foo>", XMLLanguage.INSTANCE); final XmlComment newComment = PsiTreeUtil.getChildOfType(element, XmlComment.class); assert newComment != null; return newComment; }
@Nullable public String generateDoc(PsiElement psiElement, PsiElement psiElement1) { if (psiElement instanceof DocElement) { final DocElement element = (DocElement)psiElement; return getDocumentation(element.getName(), element.getCategory()); } if (psiElement instanceof XsltElement) { final XmlTag t = ((XsltElement)psiElement).getTag(); PsiElement p = t.getPrevSibling(); while (p instanceof PsiWhiteSpace || p instanceof XmlText) { p = p.getPrevSibling(); } if (p instanceof XmlComment) { final String commentText = XmlUtil.getCommentText((XmlComment)p); return commentText != null ? commentText.replaceAll("&", "&").replaceAll("<", "<") : null; } else { return null; } } final XmlTag tag = getTag(psiElement1); if (tag != null) { return getDocumentation(tag.getLocalName(), "element"); } else if (psiElement instanceof XPathFunction) { return getDocumentation(((XPathFunction)psiElement).getName(), "function"); } return null; }
@Override @NotNull public String getType(@NotNull PsiElement element) { if(element instanceof XmlTag) { final PsiMetaData metaData = ((XmlTag) element).getMetaData(); if(metaData != null && metaData.getDeclaration() instanceof XmlTag) { return ((XmlTag) metaData.getDeclaration()).getName(); } return LangBundle.message("xml.terms.xml.tag"); } if(element instanceof XmlElementDecl) { return LangBundle.message("xml.terms.tag"); } else if(element instanceof XmlAttributeDecl) { return LangBundle.message("xml.terms.attribute"); } else if(element instanceof XmlAttributeValue) { return LangBundle.message("xml.terms.attribute.value"); } else if(element instanceof XmlEntityDecl) { return LangBundle.message("xml.terms.entity"); } else if(element instanceof XmlAttribute) { return LangBundle.message("xml.terms.attribute"); } else if(element instanceof XmlComment) { return LangBundle.message("xml.terms.variable"); } throw new IllegalArgumentException("Cannot get type for " + element); }
@Override public boolean canFindUsagesFor(@NotNull PsiElement element) { return element instanceof XmlElementDecl || element instanceof XmlAttributeDecl || element instanceof XmlEntityDecl || element instanceof XmlTag || element instanceof XmlAttributeValue || element instanceof PsiFile || element instanceof XmlComment; }