@Override public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { if (!element.isWritable()) return false; boolean isTwigFile = GravFileTemplateUtil.isTwigTemplateFile(element.getContainingFile()) || element.getContainingFile() instanceof HtmlFileImpl; boolean isXmlAttribute = false; if (!isTwigFile) return false; if (element.getParent() instanceof XmlAttributeValueImpl) { XmlAttributeValueImpl parent0 = ((XmlAttributeValueImpl) element.getParent()); boolean hasTwigElement = PsiTreeUtil.findChildOfType(parent0, OuterLanguageElement.class) != null; if (!hasTwigElement && parent0.getParent() instanceof XmlAttributeImpl) { XmlAttributeImpl parent1 = (XmlAttributeImpl) parent0.getParent(); if (parent1.getName().equalsIgnoreCase("href") || parent1.getName().equalsIgnoreCase("src")) isXmlAttribute = true; } } return isXmlAttribute; }
@SuppressWarnings({ "AutoUnboxing" }) private synchronized long queryCount() { for (XmlAttribute decl : myNSDecls) { if (!decl.isValid()) { return update(); } final Integer modCount = decl.getUserData(MOD_COUNT); if (modCount != null && ((XmlAttributeImpl)decl).getModificationCount() != modCount) { return update(); } } final ArrayList<XmlAttribute> list = getNSDecls(false); if (!list.equals(myNSDecls)) { return update(); } myRootCount = myRootTag.getModificationCount(); return myCount; }
@SuppressWarnings({"AutoUnboxing"}) private synchronized long queryCount() { for(XmlAttribute decl : myNSDecls) { if(!decl.isValid()) { return update(); } final Long modCount = decl.getUserData(MOD_COUNT); if(modCount != null && ((XmlAttributeImpl) decl).getContainingFile().getModificationStamp() != modCount) { return update(); } } final ArrayList<XmlAttribute> list = getNSDecls(false); if(!list.equals(myNSDecls)) { return update(); } myRootCount = myFile.getModificationStamp(); return myCount; }
private ArrayList<XmlAttribute> getNSDecls(boolean updateModCount) { final ArrayList<XmlAttribute> list = new ArrayList<XmlAttribute>(Arrays.asList(myRootTag.getAttributes())); final Iterator<XmlAttribute> it = list.iterator(); while(it.hasNext()) { final XmlAttribute attribute = it.next(); if(!attribute.isNamespaceDeclaration()) { it.remove(); } if(updateModCount) { attribute.putUserData(MOD_COUNT, ((XmlAttributeImpl) attribute).getContainingFile().getModificationStamp()); } } return list; }
private ArrayList<XmlAttribute> getNSDecls(boolean updateModCount) { final ArrayList<XmlAttribute> list = new ArrayList<XmlAttribute>(Arrays.asList(myRootTag.getAttributes())); final Iterator<XmlAttribute> it = list.iterator(); while (it.hasNext()) { final XmlAttribute attribute = it.next(); if (!attribute.isNamespaceDeclaration()) it.remove(); if (updateModCount) { attribute.putUserData(MOD_COUNT, ((XmlAttributeImpl)attribute).getModificationCount()); } } return list; }
private static void addVariants(final CompletionResultSet result, final XmlAttribute[] attributes, final XmlAttributeDescriptor[] descriptors, XmlAttribute attribute, @Nullable InsertHandler<LookupElement> replacementInsertHandler) { final XmlTag tag = attribute.getParent(); final PsiFile file = tag.getContainingFile(); final XmlExtension extension = XmlExtension.getExtension(file); final String prefix = attribute.getName().contains(":") && ((XmlAttributeImpl) attribute).getRealLocalName().length() > 0 ? attribute.getNamespacePrefix() + ":" : null; CompletionData completionData = CompletionUtil.getCompletionDataByElement(attribute, attribute.getContainingFile().getOriginalFile()); boolean caseSensitive = !(completionData instanceof HtmlCompletionData) || ((HtmlCompletionData)completionData).isCaseSensitive(); for (XmlAttributeDescriptor descriptor : descriptors) { if (isValidVariant(attribute, descriptor, attributes, extension)) { String name = descriptor.getName(tag); InsertHandler<LookupElement> insertHandler = XmlAttributeInsertHandler.INSTANCE; if (tag instanceof HtmlTag && HtmlUtil.isShortNotationOfBooleanAttributePreferred() && HtmlUtil.isBooleanAttribute(descriptor, tag)) { insertHandler = null; } if (replacementInsertHandler != null) { insertHandler = replacementInsertHandler; } else if (descriptor instanceof NamespaceAwareXmlAttributeDescriptor) { final String namespace = ((NamespaceAwareXmlAttributeDescriptor)descriptor).getNamespace(tag); if (file instanceof XmlFile && namespace != null && namespace.length() > 0 && !name.contains(":") && tag.getPrefixByNamespace(namespace) == null) { insertHandler = new XmlAttributeInsertHandler(namespace); } } if (prefix == null || name.startsWith(prefix)) { if (prefix != null && name.length() > prefix.length()) { name = descriptor.getName(tag).substring(prefix.length()); } LookupElementBuilder element = LookupElementBuilder.create(name); if (descriptor instanceof PsiPresentableMetaData) { element = element.withIcon(((PsiPresentableMetaData)descriptor).getIcon()); } final int separator = name.indexOf(':'); if (separator > 0) { element = element.withLookupString(name.substring(separator + 1)); } element = element .withCaseSensitivity(caseSensitive) .withInsertHandler(insertHandler); result.addElement( descriptor.isRequired() ? PrioritizedLookupElement.withPriority(element.appendTailText("(required)", true), 100) : HtmlUtil.isOwnHtmlAttribute(descriptor) ? PrioritizedLookupElement.withPriority(element, 50) : element); } } } }
private static void addVariants(final CompletionResultSet result, final XmlAttribute[] attributes, final XmlAttributeDescriptor[] descriptors, XmlAttribute attribute, @Nullable InsertHandler<LookupElement> replacementInsertHandler) { final XmlTag tag = attribute.getParent(); final PsiFile file = tag.getContainingFile(); final XmlExtension extension = XmlExtension.getExtension(file); final String prefix = attribute.getName().contains(":") && ((XmlAttributeImpl) attribute).getRealLocalName().length() > 0 ? attribute.getNamespacePrefix() + ":" : null; CompletionData completionData = CompletionUtil.getCompletionDataByElement(attribute, attribute.getContainingFile().getOriginalFile()); boolean caseSensitive = !(completionData instanceof HtmlCompletionData) || ((HtmlCompletionData)completionData).isCaseSensitive(); for (XmlAttributeDescriptor descriptor : descriptors) { if (isValidVariant(attribute, descriptor, attributes, extension)) { String name = descriptor.getName(tag); InsertHandler<LookupElement> insertHandler = XmlAttributeInsertHandler.INSTANCE; if (replacementInsertHandler != null) { insertHandler = replacementInsertHandler; } else if (descriptor instanceof NamespaceAwareXmlAttributeDescriptor) { final String namespace = ((NamespaceAwareXmlAttributeDescriptor)descriptor).getNamespace(tag); if (file instanceof XmlFile && namespace != null && namespace.length() > 0 && !name.contains(":") && tag.getPrefixByNamespace(namespace) == null) { insertHandler = new XmlAttributeInsertHandler(namespace); } } if (prefix == null || name.startsWith(prefix)) { if (prefix != null && name.length() > prefix.length()) { name = descriptor.getName(tag).substring(prefix.length()); } LookupElementBuilder element = LookupElementBuilder.create(name); if (descriptor instanceof PsiPresentableMetaData) { element = element.withIcon(((PsiPresentableMetaData)descriptor).getIcon()); } final int separator = name.indexOf(':'); if (separator > 0) { element = element.withLookupString(name.substring(separator + 1)); } element = element .withCaseSensitivity(caseSensitive) .withInsertHandler(insertHandler); result.addElement( descriptor.isRequired() ? PrioritizedLookupElement.withPriority(element.appendTailText("(required)", true), 100) : element); } } } }
@Override public void validate(@NotNull XmlTag context, @NotNull ValidationHost host) { final XmlTag parentTag = context.getParentTag(); if (parentTag != null) { final XmlAttribute attribute = context.getAttribute(FxmlConstants.FX_CONTROLLER); if (attribute != null) { host.addMessage(((XmlAttributeImpl)attribute).getNameElement(), "fx:controller can only be applied to root element", ValidationHost.ErrorType.ERROR); //todo add delete/move to upper tag fix } } PsiClass aClass = myPsiClass; final XmlAttribute constAttr = context.getAttribute(FxmlConstants.FX_CONSTANT); if (constAttr != null) { final PsiField constField = aClass.findFieldByName(constAttr.getValue(), false); if (constField != null) { aClass = PsiUtil.resolveClassInType(constField.getType()); } } else { final XmlAttribute factoryAttr = context.getAttribute(FxmlConstants.FX_FACTORY); if (factoryAttr != null) { final XmlAttributeValue valueElement = factoryAttr.getValueElement(); if (valueElement != null) { final PsiReference reference = valueElement.getReference(); final PsiElement staticFactoryMethod = reference != null ? reference.resolve() : null; if (staticFactoryMethod instanceof PsiMethod && ((PsiMethod)staticFactoryMethod).getParameterList().getParametersCount() == 0 && ((PsiMethod)staticFactoryMethod).hasModifierProperty(PsiModifier.STATIC)) { aClass = PsiUtil.resolveClassInType(((PsiMethod)staticFactoryMethod).getReturnType()); } } } } final String canCoerceError = JavaFxPsiUtil.isClassAcceptable(parentTag, aClass); if (canCoerceError != null) { host.addMessage(context.getNavigationElement(), canCoerceError, ValidationHost.ErrorType.ERROR); } if (aClass != null && aClass.isValid()) { final String message = JavaFxPsiUtil.isAbleToInstantiate(aClass); if (message != null) { host.addMessage(context, message, ValidationHost.ErrorType.ERROR); } } }
@Override public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { final PsiElement element = getElement(); ((XmlAttributeImpl) element).setValue(newElementName); return element; }
private static void addVariants(final CompletionResultSet result, final XmlAttribute[] attributes, final XmlAttributeDescriptor[] descriptors, XmlAttribute attribute, @Nullable InsertHandler<LookupElement> replacementInsertHandler) { final XmlTag tag = attribute.getParent(); final PsiFile file = tag.getContainingFile(); final XmlExtension extension = XmlExtension.getExtension(file); final String prefix = attribute.getName().contains(":") && ((XmlAttributeImpl) attribute).getRealLocalName().length() > 0 ? attribute.getNamespacePrefix() + ":" : null; for(XmlAttributeDescriptor descriptor : descriptors) { if(isValidVariant(attribute, descriptor, attributes, extension)) { String name = descriptor.getName(tag); InsertHandler<LookupElement> insertHandler = XmlAttributeInsertHandler.INSTANCE; if(tag instanceof HtmlTag && HtmlUtil.isShortNotationOfBooleanAttributePreferred() && HtmlUtil.isBooleanAttribute(descriptor, tag)) { insertHandler = null; } if(replacementInsertHandler != null) { insertHandler = replacementInsertHandler; } else if(descriptor instanceof NamespaceAwareXmlAttributeDescriptor) { final String namespace = ((NamespaceAwareXmlAttributeDescriptor) descriptor).getNamespace(tag); if(file instanceof XmlFile && namespace != null && namespace.length() > 0 && !name.contains(":") && tag.getPrefixByNamespace(namespace) == null) { insertHandler = new XmlAttributeInsertHandler(namespace); } } if(prefix == null || name.startsWith(prefix)) { if(prefix != null && name.length() > prefix.length()) { name = descriptor.getName(tag).substring(prefix.length()); } LookupElementBuilder element = LookupElementBuilder.create(name); if(descriptor instanceof PsiPresentableMetaData) { element = element.withIcon(((PsiPresentableMetaData) descriptor).getIcon()); } final int separator = name.indexOf(':'); if(separator > 0) { element = element.withLookupString(name.substring(separator + 1)); } element = element.withCaseSensitivity(!(descriptor instanceof HtmlAttributeDescriptorImpl)).withInsertHandler(insertHandler); result.addElement(descriptor.isRequired() ? PrioritizedLookupElement.withPriority(element.appendTailText("(required)", true), 100) : HtmlUtil.isOwnHtmlAttribute(descriptor) ? PrioritizedLookupElement.withPriority(element, 50) : element); } } } }