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()]);
}
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));
}
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();
}
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();
});
}
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;
});
}
Aggregations