Search in sources :

Example 6 with DomCollectionChildDescription

use of com.intellij.util.xml.reflect.DomCollectionChildDescription in project intellij-community by JetBrains.

the class AddDomElementAction method getChildren.

@NotNull
public AnAction[] getChildren(@Nullable AnActionEvent e) {
    Project project = e == null ? null : e.getProject();
    if (project == null)
        return AnAction.EMPTY_ARRAY;
    DomCollectionChildDescription[] descriptions = getDomCollectionChildDescriptions(e);
    final List<AnAction> actions = new ArrayList<>();
    for (DomCollectionChildDescription description : descriptions) {
        final TypeChooser chooser = DomManager.getDomManager(project).getTypeChooserManager().getTypeChooser(description.getType());
        for (Type type : chooser.getChooserTypes()) {
            final Class<?> rawType = ReflectionUtil.getRawType(type);
            String name = TypePresentationService.getService().getTypePresentableName(rawType);
            Icon icon = null;
            if (!showAsPopup() || descriptions.length == 1) {
                //          if (descriptions.length > 1) {
                icon = ElementPresentationManager.getIconForClass(rawType);
            //          }
            }
            actions.add(createAddingAction(e, ApplicationBundle.message("action.add") + " " + name, icon, type, description));
        }
    }
    if (actions.size() > 1 && showAsPopup()) {
        ActionGroup group = new ActionGroup() {

            @Override
            @NotNull
            public AnAction[] getChildren(@Nullable AnActionEvent e) {
                return actions.toArray(new AnAction[actions.size()]);
            }
        };
        return new AnAction[] { new ShowPopupAction(group) };
    } else {
        if (actions.size() > 1) {
            actions.add(Separator.getInstance());
        } else if (actions.size() == 1) {
        }
    }
    return actions.toArray(new AnAction[actions.size()]);
}
Also used : ArrayList(java.util.ArrayList) Project(com.intellij.openapi.project.Project) Type(java.lang.reflect.Type) TypeChooser(com.intellij.util.xml.TypeChooser) DomCollectionChildDescription(com.intellij.util.xml.reflect.DomCollectionChildDescription) Nullable(org.jetbrains.annotations.Nullable) NotNull(org.jetbrains.annotations.NotNull)

Example 7 with DomCollectionChildDescription

use of com.intellij.util.xml.reflect.DomCollectionChildDescription in project intellij-community by JetBrains.

the class DomBasicsTest method testAddChildrenByReflection.

public void testAddChildrenByReflection() throws Throwable {
    final MyElement element = createElement("<a><child-element/></a>");
    final DomGenericInfo info = element.getGenericInfo();
    final DomCollectionChildDescription collectionChild = info.getCollectionChildDescription("child-element");
    final List<? extends DomElement> values = collectionChild.getValues(element);
    MyElement newChild = (MyElement) collectionChild.addValue(element);
    List<DomElement> newChildren = Arrays.asList(values.get(0), newChild);
    assertEquals(newChildren, element.getChildElements());
    assertEquals(newChildren, collectionChild.getValues(element));
    MyElement lastChild = (MyElement) collectionChild.addValue(element, 0);
    newChildren = Arrays.asList(lastChild, values.get(0), newChild);
    assertEquals(newChildren, element.getChildElements());
    assertEquals(newChildren, collectionChild.getValues(element));
}
Also used : DomCollectionChildDescription(com.intellij.util.xml.reflect.DomCollectionChildDescription) DomGenericInfo(com.intellij.util.xml.reflect.DomGenericInfo)

Example 8 with DomCollectionChildDescription

use of com.intellij.util.xml.reflect.DomCollectionChildDescription in project intellij-community by JetBrains.

the class DomHighlightingHelperImpl method checkRequired.

@Override
@NotNull
public List<DomElementProblemDescriptor> checkRequired(final DomElement element, final DomElementAnnotationHolder holder) {
    final Required required = element.getAnnotation(Required.class);
    if (required != null) {
        final XmlElement xmlElement = element.getXmlElement();
        if (xmlElement == null) {
            if (required.value()) {
                final String xmlElementName = element.getXmlElementName();
                String namespace = element.getXmlElementNamespace();
                if (element instanceof GenericAttributeValue) {
                    return Collections.singletonList(holder.createProblem(element, IdeBundle.message("attribute.0.should.be.defined", xmlElementName), new DefineAttributeQuickFix(xmlElementName, namespace)));
                }
                return Collections.singletonList(holder.createProblem(element, HighlightSeverity.ERROR, IdeBundle.message("child.tag.0.should.be.defined", xmlElementName), new AddRequiredSubtagFix(xmlElementName, namespace)));
            }
        } else if (element instanceof GenericDomValue) {
            return ContainerUtil.createMaybeSingletonList(checkRequiredGenericValue((GenericDomValue) element, required, holder));
        }
    }
    if (DomUtil.hasXml(element)) {
        final SmartList<DomElementProblemDescriptor> list = new SmartList<>();
        final DomGenericInfo info = element.getGenericInfo();
        for (final AbstractDomChildrenDescription description : info.getChildrenDescriptions()) {
            if (description instanceof DomCollectionChildDescription && description.getValues(element).isEmpty()) {
                final DomCollectionChildDescription childDescription = (DomCollectionChildDescription) description;
                final Required annotation = description.getAnnotation(Required.class);
                if (annotation != null && annotation.value()) {
                    list.add(holder.createProblem(element, childDescription, IdeBundle.message("child.tag.0.should.be.defined", ((DomCollectionChildDescription) description).getXmlElementName())));
                }
            }
        }
        return list;
    }
    return Collections.emptyList();
}
Also used : DomGenericInfo(com.intellij.util.xml.reflect.DomGenericInfo) DomCollectionChildDescription(com.intellij.util.xml.reflect.DomCollectionChildDescription) XmlElement(com.intellij.psi.xml.XmlElement) AbstractDomChildrenDescription(com.intellij.util.xml.reflect.AbstractDomChildrenDescription) SmartList(com.intellij.util.SmartList) NotNull(org.jetbrains.annotations.NotNull)

Example 9 with DomCollectionChildDescription

use of com.intellij.util.xml.reflect.DomCollectionChildDescription in project intellij-community by JetBrains.

the class DomSemContributor method registerSemProviders.

@Override
public void registerSemProviders(SemRegistrar registrar) {
    registrar.registerSemElementProvider(DomManagerImpl.FILE_DESCRIPTION_KEY, xmlFile(), xmlFile -> {
        ApplicationManager.getApplication().assertReadAccessAllowed();
        return new FileDescriptionCachedValueProvider(DomManagerImpl.getDomManager(xmlFile.getProject()), xmlFile);
    });
    registrar.registerSemElementProvider(DomManagerImpl.DOM_HANDLER_KEY, xmlTag().withParent(psiElement(XmlElementType.XML_DOCUMENT).withParent(xmlFile())), xmlTag -> {
        final FileDescriptionCachedValueProvider provider = mySemService.getSemElement(DomManagerImpl.FILE_DESCRIPTION_KEY, xmlTag.getContainingFile());
        assert provider != null;
        final DomFileElementImpl element = provider.getFileElement();
        if (element != null) {
            final DomRootInvocationHandler handler = element.getRootHandler();
            if (handler.getXmlTag() == xmlTag) {
                return handler;
            }
        }
        return null;
    });
    final ElementPattern<XmlTag> nonRootTag = xmlTag().withParent(or(xmlTag(), xmlEntityRef().withParent(xmlTag())));
    registrar.registerSemElementProvider(DomManagerImpl.DOM_INDEXED_HANDLER_KEY, nonRootTag, tag -> {
        final XmlTag parentTag = PhysicalDomParentStrategy.getParentTag(tag);
        assert parentTag != null;
        DomInvocationHandler parent = getParentDom(parentTag);
        if (parent == null)
            return null;
        final String localName = tag.getLocalName();
        final String namespace = tag.getNamespace();
        final DomFixedChildDescription description = findChildrenDescription(parent.getGenericInfo().getFixedChildrenDescriptions(), tag, parent);
        if (description != null) {
            final int totalCount = description.getCount();
            int index = 0;
            PsiElement current = tag;
            while (true) {
                current = current.getPrevSibling();
                if (current == null) {
                    break;
                }
                if (current instanceof XmlTag) {
                    final XmlTag xmlTag = (XmlTag) current;
                    if (localName.equals(xmlTag.getLocalName()) && namespace.equals(xmlTag.getNamespace())) {
                        index++;
                        if (index >= totalCount) {
                            return null;
                        }
                    }
                }
            }
            final DomManagerImpl myDomManager = parent.getManager();
            return new IndexedElementInvocationHandler(parent.createEvaluatedXmlName(description.getXmlName()), (FixedChildDescriptionImpl) description, index, new PhysicalDomParentStrategy(tag, myDomManager), myDomManager, null);
        }
        return null;
    });
    registrar.registerSemElementProvider(DomManagerImpl.DOM_COLLECTION_HANDLER_KEY, nonRootTag, tag -> {
        final XmlTag parentTag = PhysicalDomParentStrategy.getParentTag(tag);
        assert parentTag != null;
        DomInvocationHandler parent = getParentDom(parentTag);
        if (parent == null)
            return null;
        final DomCollectionChildDescription description = findChildrenDescription(parent.getGenericInfo().getCollectionChildrenDescriptions(), tag, parent);
        if (description != null) {
            DomStub parentStub = parent.getStub();
            if (parentStub != null) {
                int index = ArrayUtil.indexOf(parentTag.findSubTags(tag.getName(), tag.getNamespace()), tag);
                ElementStub stub = parentStub.getElementStub(tag.getLocalName(), index);
                if (stub != null) {
                    XmlName name = description.getXmlName();
                    EvaluatedXmlNameImpl evaluatedXmlName = EvaluatedXmlNameImpl.createEvaluatedXmlName(name, name.getNamespaceKey(), true);
                    return new CollectionElementInvocationHandler(evaluatedXmlName, (AbstractDomChildDescriptionImpl) description, parent.getManager(), stub);
                }
            }
            return new CollectionElementInvocationHandler(description.getType(), tag, (AbstractCollectionChildDescription) description, parent, null);
        }
        return null;
    });
    registrar.registerSemElementProvider(DomManagerImpl.DOM_CUSTOM_HANDLER_KEY, nonRootTag, new NullableFunction<XmlTag, CollectionElementInvocationHandler>() {

        private final RecursionGuard myGuard = RecursionManager.createGuard("customDomParent");

        @Override
        public CollectionElementInvocationHandler fun(XmlTag tag) {
            if (StringUtil.isEmpty(tag.getName()))
                return null;
            final XmlTag parentTag = PhysicalDomParentStrategy.getParentTag(tag);
            assert parentTag != null;
            DomInvocationHandler parent = myGuard.doPreventingRecursion(tag, true, (NullableComputable<DomInvocationHandler>) () -> getParentDom(parentTag));
            if (parent == null)
                return null;
            DomGenericInfoEx info = parent.getGenericInfo();
            final List<? extends CustomDomChildrenDescription> customs = info.getCustomNameChildrenDescription();
            if (customs.isEmpty())
                return null;
            if (mySemService.getSemElement(DomManagerImpl.DOM_INDEXED_HANDLER_KEY, tag) == null && mySemService.getSemElement(DomManagerImpl.DOM_COLLECTION_HANDLER_KEY, tag) == null) {
                String localName = tag.getLocalName();
                XmlFile file = parent.getFile();
                for (final DomFixedChildDescription description : info.getFixedChildrenDescriptions()) {
                    XmlName xmlName = description.getXmlName();
                    if (localName.equals(xmlName.getLocalName()) && DomImplUtil.isNameSuitable(xmlName, tag, parent, file)) {
                        return null;
                    }
                }
                for (CustomDomChildrenDescription description : customs) {
                    if (description.getTagNameDescriptor() != null) {
                        AbstractCollectionChildDescription desc = (AbstractCollectionChildDescription) description;
                        Type type = description.getType();
                        return new CollectionElementInvocationHandler(type, tag, desc, parent, null);
                    }
                }
            }
            return null;
        }
    });
    registrar.registerSemElementProvider(DomManagerImpl.DOM_ATTRIBUTE_HANDLER_KEY, xmlAttribute(), attribute -> {
        final XmlTag tag = PhysicalDomParentStrategy.getParentTag(attribute);
        final DomInvocationHandler handler = tag == null ? null : getParentDom(tag);
        if (handler == null)
            return null;
        final String localName = attribute.getLocalName();
        final Ref<AttributeChildInvocationHandler> result = Ref.create(null);
        handler.getGenericInfo().processAttributeChildrenDescriptions(description -> {
            if (description.getXmlName().getLocalName().equals(localName)) {
                final EvaluatedXmlName evaluatedXmlName = handler.createEvaluatedXmlName(description.getXmlName());
                final String ns = evaluatedXmlName.getNamespace(tag, handler.getFile());
                if (ns.equals(tag.getNamespace()) && localName.equals(attribute.getName()) || ns.equals(attribute.getNamespace())) {
                    final DomManagerImpl myDomManager = handler.getManager();
                    final AttributeChildInvocationHandler attributeHandler = new AttributeChildInvocationHandler(evaluatedXmlName, description, myDomManager, new PhysicalDomParentStrategy(attribute, myDomManager), null);
                    result.set(attributeHandler);
                    return false;
                }
            }
            return true;
        });
        return result.get();
    });
}
Also used : DomStub(com.intellij.util.xml.stubs.DomStub) CustomDomChildrenDescription(com.intellij.util.xml.reflect.CustomDomChildrenDescription) EvaluatedXmlName(com.intellij.util.xml.EvaluatedXmlName) XmlName(com.intellij.util.xml.XmlName) PsiElement(com.intellij.psi.PsiElement) EvaluatedXmlName(com.intellij.util.xml.EvaluatedXmlName) XmlFile(com.intellij.psi.xml.XmlFile) RecursionGuard(com.intellij.openapi.util.RecursionGuard) NullableComputable(com.intellij.openapi.util.NullableComputable) EvaluatedXmlNameImpl(com.intellij.util.xml.EvaluatedXmlNameImpl) XmlElementType(com.intellij.psi.xml.XmlElementType) Type(java.lang.reflect.Type) DomCollectionChildDescription(com.intellij.util.xml.reflect.DomCollectionChildDescription) DomFixedChildDescription(com.intellij.util.xml.reflect.DomFixedChildDescription) ElementStub(com.intellij.util.xml.stubs.ElementStub) XmlTag(com.intellij.psi.xml.XmlTag)

Example 10 with DomCollectionChildDescription

use of com.intellij.util.xml.reflect.DomCollectionChildDescription in project intellij-community by JetBrains.

the class DomImplUtil method getCustomSubTags.

public static List<XmlTag> getCustomSubTags(final DomInvocationHandler handler, final XmlTag[] subTags, final XmlFile file) {
    if (subTags.length == 0) {
        return Collections.emptyList();
    }
    final DomGenericInfoEx info = handler.getGenericInfo();
    final Set<XmlName> usedNames = new THashSet<>();
    List<? extends DomCollectionChildDescription> collectionChildrenDescriptions = info.getCollectionChildrenDescriptions();
    //noinspection ForLoopReplaceableByForEach
    for (int i = 0, size = collectionChildrenDescriptions.size(); i < size; i++) {
        DomCollectionChildDescription description = collectionChildrenDescriptions.get(i);
        usedNames.add(description.getXmlName());
    }
    List<? extends DomFixedChildDescription> fixedChildrenDescriptions = info.getFixedChildrenDescriptions();
    //noinspection ForLoopReplaceableByForEach
    for (int i = 0, size = fixedChildrenDescriptions.size(); i < size; i++) {
        DomFixedChildDescription description = fixedChildrenDescriptions.get(i);
        usedNames.add(description.getXmlName());
    }
    return ContainerUtil.findAll(subTags, tag -> {
        if (StringUtil.isEmpty(tag.getName()))
            return false;
        for (final XmlName name : usedNames) {
            if (isNameSuitable(name, tag, handler, file)) {
                return false;
            }
        }
        return true;
    });
}
Also used : DomCollectionChildDescription(com.intellij.util.xml.reflect.DomCollectionChildDescription) DomFixedChildDescription(com.intellij.util.xml.reflect.DomFixedChildDescription) THashSet(gnu.trove.THashSet)

Aggregations

DomCollectionChildDescription (com.intellij.util.xml.reflect.DomCollectionChildDescription)11 DomFixedChildDescription (com.intellij.util.xml.reflect.DomFixedChildDescription)5 DomGenericInfo (com.intellij.util.xml.reflect.DomGenericInfo)4 XmlTag (com.intellij.psi.xml.XmlTag)3 Type (java.lang.reflect.Type)3 NotNull (org.jetbrains.annotations.NotNull)3 Nullable (org.jetbrains.annotations.Nullable)3 Project (com.intellij.openapi.project.Project)2 PsiElement (com.intellij.psi.PsiElement)2 XmlFile (com.intellij.psi.xml.XmlFile)2 SimpleNode (com.intellij.ui.treeStructure.SimpleNode)2 AbstractDomChildrenDescription (com.intellij.util.xml.reflect.AbstractDomChildrenDescription)2 Document (com.intellij.openapi.editor.Document)1 NullableComputable (com.intellij.openapi.util.NullableComputable)1 RecursionGuard (com.intellij.openapi.util.RecursionGuard)1 PsiDocumentManager (com.intellij.psi.PsiDocumentManager)1 PsiFile (com.intellij.psi.PsiFile)1 PsiWhiteSpace (com.intellij.psi.PsiWhiteSpace)1 XmlElement (com.intellij.psi.xml.XmlElement)1 XmlElementType (com.intellij.psi.xml.XmlElementType)1