diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlTagImpl.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlTagImpl.java index ad8b39453c27..3be34482656a 100644 --- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlTagImpl.java +++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlTagImpl.java @@ -25,6 +25,7 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.PomManager; @@ -106,14 +107,7 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag, HintedReferenc private volatile TextRange[] myTextElements = null; private volatile Map myAttributeValueMap = null; private volatile XmlTagValue myValue = null; - private volatile Map> myNSDescriptorsMap = null; - private volatile String myCachedNamespace; - private volatile long myModCount; - private volatile XmlElementDescriptor myCachedDescriptor; - private volatile long myDescriptorModCount = -1; - private volatile long myExtResourcesModCount = -1; private volatile boolean myHasNamespaceDeclarations = false; - private volatile BidirectionalMap myNamespaceMap = null; public XmlTagImpl() { this(XmlElementType.XML_TAG); @@ -154,16 +148,11 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag, HintedReferenc public void clearCaches() { myName = null; myLocalName = null; - myNamespaceMap = null; - myCachedNamespace = null; - myCachedDescriptor = null; - myDescriptorModCount = -1; myAttributes = null; myTextElements = null; myAttributeValueMap = null; myHasNamespaceDeclarations = false; myValue = null; - myNSDescriptorsMap = null; super.clearCaches(); } @@ -267,7 +256,7 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag, HintedReferenc } } - Map> map = initNSDescriptorsMap(); + Map> map = getNSDescriptorsMap(); final CachedValue descriptor = map.get(namespace); if (descriptor != null) { final XmlNSDescriptor value = descriptor.getValue(); @@ -334,16 +323,10 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag, HintedReferenc return tag.getValue().getText(); } - protected final Map> initNSDescriptorsMap() { - Map> map = myNSDescriptorsMap; - if (map == null) { - RecursionGuard.StackStamp stamp = ourGuard.markStack(); - map = computeNsDescriptorMap(); - if (stamp.mayCacheNow()) { - myNSDescriptorsMap = map; - } - } - return map; + protected final Map> getNSDescriptorsMap() { + return CachedValuesManager.getCachedValue(this, () -> + CachedValueProvider.Result.create(computeNsDescriptorMap(), + PsiModificationTracker.MODIFICATION_COUNT, externalResourceModificationTracker())); } @NotNull @@ -487,23 +470,15 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag, HintedReferenc @Override public XmlElementDescriptor getDescriptor() { - final long curModCount = getManager().getModificationTracker().getModificationCount(); - long curExtResourcesModCount = ExternalResourceManagerEx.getInstanceEx().getModificationCount(getProject()); - if (myDescriptorModCount != curModCount || myExtResourcesModCount != curExtResourcesModCount) { - if (myExtResourcesModCount != curExtResourcesModCount) { - myNSDescriptorsMap = null; - } - RecursionGuard.StackStamp stamp = ourGuard.markStack(); - XmlElementDescriptor descriptor = computeElementDescriptor(); - if (!stamp.mayCacheNow()) { - return descriptor; - } + return CachedValuesManager.getCachedValue(this, () -> + CachedValueProvider.Result.create(computeElementDescriptor(), + PsiModificationTracker.MODIFICATION_COUNT, externalResourceModificationTracker())); + } - myCachedDescriptor = descriptor; - myDescriptorModCount = curModCount; - myExtResourcesModCount = curExtResourcesModCount; - } - return myCachedDescriptor; + private ModificationTracker externalResourceModificationTracker() { + Project project = getProject(); + ExternalResourceManagerEx manager = ExternalResourceManagerEx.getInstanceEx(); + return () -> manager.getModificationCount(project); } @Nullable @@ -671,10 +646,8 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag, HintedReferenc } XmlTagImpl current = this; - PsiElement parent = getParent(); - - while (current != null) { - BidirectionalMap map = current.initNamespaceMaps(parent); + while (true) { + BidirectionalMap map = current.getNamespaceMap(); if (map != null) { List keysByValue = map.getKeysByValue(namespace); if (keysByValue != null && !keysByValue.isEmpty()) { @@ -688,8 +661,11 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag, HintedReferenc } } - current = parent instanceof XmlTag ? (XmlTagImpl)parent : null; - parent = parent.getParent(); + PsiElement parent = current.getParent(); + if (!(parent instanceof XmlTag)) { + break; + } + current = (XmlTagImpl)parent; } if (namespace.isEmpty() || getNamespace().equals(namespace)) { @@ -787,20 +763,8 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag, HintedReferenc @Override @NotNull public String getNamespace() { - String cachedNamespace = myCachedNamespace; - final long curModCount = getManager().getModificationTracker().getModificationCount(); - if (cachedNamespace != null && myModCount == curModCount) { - return cachedNamespace; - } - RecursionGuard.StackStamp stamp = ourGuard.markStack(); - cachedNamespace = getNamespaceByPrefix(getNamespacePrefix()); - if (!stamp.mayCacheNow()) { - return cachedNamespace; - } - - myCachedNamespace = cachedNamespace; - myModCount = curModCount; - return cachedNamespace; + return CachedValuesManager.getCachedValue(this, () -> + CachedValueProvider.Result.create(getNamespaceByPrefix(getNamespacePrefix()), PsiModificationTracker.MODIFICATION_COUNT)); } @Override @@ -812,11 +776,7 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag, HintedReferenc @Override @NotNull public String getNamespaceByPrefix(String prefix) { - final PsiElement parent = getParent(); - if (!parent.isValid()) { - LOG.error(this.isValid()); - } - BidirectionalMap map = initNamespaceMaps(parent); + BidirectionalMap map = getNamespaceMap(); if (map != null) { final String ns = map.get(prefix); if (ns != null) return ns; @@ -855,8 +815,7 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag, HintedReferenc @Override public String getPrefixByNamespace(String namespace) { - final PsiElement parent = getParent(); - BidirectionalMap map = initNamespaceMaps(parent); + BidirectionalMap map = getNamespaceMap(); if (map != null) { List keysByValue = map.getKeysByValue(namespace); final String ns = keysByValue == null || keysByValue.isEmpty() ? null : keysByValue.get(0); @@ -872,7 +831,7 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag, HintedReferenc @Override public String[] knownNamespaces() { final PsiElement parentElement = getParent(); - BidirectionalMap map = initNamespaceMaps(parentElement); + BidirectionalMap map = getNamespaceMap(); Set known = Collections.emptySet(); if (map != null) { known = new HashSet(map.values()); @@ -898,18 +857,9 @@ public class XmlTagImpl extends XmlElementImpl implements XmlTag, HintedReferenc } @Nullable - private BidirectionalMap initNamespaceMaps(PsiElement parent) { - BidirectionalMap map = myNamespaceMap; - - if (map == null) { - RecursionGuard.StackStamp stamp = ourGuard.markStack(); - map = computeNamespaceMap(parent); - if (stamp.mayCacheNow()) { - myNamespaceMap = map; - } - } - - return map; + private BidirectionalMap getNamespaceMap() { + return CachedValuesManager.getCachedValue(this, () -> + CachedValueProvider.Result.create(computeNamespaceMap(getParent()), PsiModificationTracker.MODIFICATION_COUNT)); } @Nullable