void (final @NotNull Project project, @NotNull PsiFile file, final @Nullable Editor editor, @NotNull PsiElement startElement, @NotNull PsiElement endElement) { XmlTag myTag = (XmlTag)startElement; ASTNode treeElement = SourceTreeToPsiMap.psiElementToTree(myTag); final XmlElementDescriptor descriptor = myTag.getDescriptor(); if (descriptor == null) { return; } final XmlAttributeDescriptor attrDescriptor = descriptor.getAttributeDescriptor(myAttrName, myTag); final boolean indirectSyntax = XmlExtension.getExtension(myTag.getContainingFile()).isIndirectSyntax(attrDescriptor); boolean insertShorthand = myTag instanceof HtmlTag && attrDescriptor != null && HtmlUtil.isBooleanAttribute(attrDescriptor, myTag); PsiElement anchor = SourceTreeToPsiMap.treeElementToPsi( XmlChildRole.EMPTY_TAG_END_FINDER.findChild(treeElement) ); final boolean anchorIsEmptyTag = anchor != null; if (anchor == null) { anchor = SourceTreeToPsiMap.treeElementToPsi( XmlChildRole.START_TAG_END_FINDER.findChild(treeElement) ); } if (anchor == null) return; final Template template = TemplateManager.getInstance(project).createTemplate("", ""); String valuePostfix = "\""; if (indirectSyntax) { if (anchorIsEmptyTag) template.addTextSegment(">"); template.addTextSegment("<jsp:attribute name=\"" + myAttrName + "\">"); } else { template.addTextSegment(" " + myAttrName); if (!insertShorthand) { String quote = XmlEditUtil.getAttributeQuote(file); AttributeValuePresentation presentation = XmlExtension.getExtension(file).getAttributeValuePresentation(myTag, myAttrName, quote); valuePostfix = presentation.getPostfix(); template.addTextSegment("=" + presentation.getPrefix()); } } Expression expression = new ConstantNode("").withLookupStrings(myValues); if (!insertShorthand) template.addVariable(NAME_TEMPLATE_VARIABLE, expression, expression, true); if (indirectSyntax) { template.addTextSegment("</jsp:attribute>"); template.addEndVariable(); if (anchorIsEmptyTag) template.addTextSegment("</" + myTag.getName() + ">"); } else if (!insertShorthand) { template.addTextSegment(valuePostfix); } int textOffset = anchor.getTextOffset(); if (!anchorIsEmptyTag && indirectSyntax) ++textOffset; editor.getCaretModel().moveToOffset(textOffset); if (anchorIsEmptyTag && indirectSyntax) { editor.getDocument().deleteString(textOffset, textOffset + 2); } TemplateManager.getInstance(project).startTemplate(editor, template); }