use of com.intellij.util.xml.stubs.DomStub in project intellij-community by JetBrains.
the class DomInvocationHandler method getFixedChild.
@NotNull
final IndexedElementInvocationHandler getFixedChild(final Pair<FixedChildDescriptionImpl, Integer> info) {
final FixedChildDescriptionImpl description = info.first;
XmlName xmlName = description.getXmlName();
final EvaluatedXmlName evaluatedXmlName = createEvaluatedXmlName(xmlName);
if (myStub != null && description.isStubbed()) {
List<DomStub> stubs = myStub.getChildrenByName(xmlName.getLocalName(), xmlName.getNamespaceKey());
DomStub stub = stubs.isEmpty() ? null : stubs.get(0);
DomParentStrategy strategy = stub == null ? new StubParentStrategy.Empty(myStub) : new StubParentStrategy(stub);
return new IndexedElementInvocationHandler(evaluatedXmlName, description, 0, strategy, myManager, (ElementStub) stub);
}
final XmlTag tag = getXmlTag();
final int index = info.second;
if (tag != null) {
if (!tag.isValid()) {
throw new PsiInvalidElementAccessException(tag);
}
final XmlTag[] subTags = tag.getSubTags();
for (int i = 0, subTagsLength = subTags.length; i < subTagsLength; i++) {
XmlTag xmlTag = subTags[i];
if (!xmlTag.isValid()) {
throw new PsiInvalidElementAccessException(xmlTag, "invalid children of valid tag: " + tag.getText() + "; subtag=" + xmlTag + "; index=" + i);
}
}
final List<XmlTag> tags = DomImplUtil.findSubTags(subTags, evaluatedXmlName, getFile());
if (tags.size() > index) {
final XmlTag child = tags.get(index);
final IndexedElementInvocationHandler semElement = myManager.getSemService().getSemElement(DomManagerImpl.DOM_INDEXED_HANDLER_KEY, child);
if (semElement == null) {
final IndexedElementInvocationHandler take2 = myManager.getSemService().getSemElement(DomManagerImpl.DOM_INDEXED_HANDLER_KEY, child);
throw new AssertionError("No DOM at XML. Parent=" + tag + "; child=" + child + "; index=" + index + "; second attempt=" + take2);
}
return semElement;
}
}
return new IndexedElementInvocationHandler(evaluatedXmlName, description, index, new VirtualDomParentStrategy(this), myManager, null);
}
use of com.intellij.util.xml.stubs.DomStub in project intellij-community by JetBrains.
the class DomInvocationHandler method getCollectionChildren.
public List<? extends DomElement> getCollectionChildren(final AbstractCollectionChildDescription description) {
if (myStub != null && description.isStubbed()) {
if (description instanceof DomChildDescriptionImpl) {
XmlName xmlName = ((DomChildDescriptionImpl) description).getXmlName();
List<DomStub> stubs = myStub.getChildrenByName(xmlName.getLocalName(), xmlName.getNamespaceKey());
return ContainerUtil.map(stubs, stub -> stub.getOrCreateHandler((DomChildDescriptionImpl) description, myManager).getProxy());
} else if (description instanceof CustomDomChildrenDescriptionImpl) {
List<DomStub> stubs = myStub.getChildrenStubs();
return ContainerUtil.mapNotNull(stubs, (NullableFunction<DomStub, DomElement>) stub -> {
if (stub instanceof ElementStub && stub.isCustom()) {
EvaluatedXmlName name = new DummyEvaluatedXmlName(stub.getName(), "");
return new CollectionElementInvocationHandler(name, (CustomDomChildrenDescriptionImpl) description, myManager, (ElementStub) stub).getProxy();
}
return null;
});
}
}
XmlTag tag = getXmlTag();
if (tag == null)
return Collections.emptyList();
final List<XmlTag> subTags = getCollectionSubTags(description, tag);
if (subTags.isEmpty())
return Collections.emptyList();
List<DomElement> elements = new ArrayList<>(subTags.size());
for (XmlTag subTag : subTags) {
final SemKey<? extends DomInvocationHandler> key = description instanceof CustomDomChildrenDescription ? DomManagerImpl.DOM_CUSTOM_HANDLER_KEY : DomManagerImpl.DOM_COLLECTION_HANDLER_KEY;
final DomInvocationHandler semElement = myManager.getSemService().getSemElement(key, subTag);
if (semElement == null) {
String msg = "No child for subTag '" + subTag.getName() + "' in tag '" + tag.getName() + "' using key " + key + "; subtag count=" + subTags.size();
DomInvocationHandler anyDom = myManager.getDomHandler(subTag);
if (anyDom != null) {
msg += "\n sub-dom=" + anyDom + " with " + anyDom.getChildDescription();
}
throw new AssertionError(msg);
} else {
elements.add(semElement.getProxy());
}
}
return Collections.unmodifiableList(elements);
}
use of com.intellij.util.xml.stubs.DomStub 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();
});
}
Aggregations