protected final Map<String, CachedValue<XmlNSDescriptor>> initNSDescriptorsMap() {
   Map<String, CachedValue<XmlNSDescriptor>> map = myNSDescriptorsMap;
   if (map == null) {
     RecursionGuard.StackStamp stamp = ourGuard.markStack();
     map = computeNsDescriptorMap();
     if (stamp.mayCacheNow()) {
       myNSDescriptorsMap = map;
     }
   }
   return map;
 }
  @Nullable
  private BidirectionalMap<String, String> initNamespaceMaps(PsiElement parent) {
    BidirectionalMap<String, String> map = myNamespaceMap;

    if (map == null) {
      RecursionGuard.StackStamp stamp = ourGuard.markStack();
      map = computeNamespaceMap(parent);
      if (stamp.mayCacheNow()) {
        myNamespaceMap = map;
      }
    }

    return map;
  }
  @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;
  }
  @Nullable
  private <TRef extends PsiReference, TResult> TResult resolve(
      @NotNull final TRef ref,
      @NotNull final AbstractResolver<TRef, TResult> resolver,
      boolean needToPreventRecursion,
      final boolean incompleteCode,
      boolean isPoly,
      boolean isPhysical) {
    ProgressIndicatorProvider.checkCanceled();
    if (isPhysical) {
      ApplicationManager.getApplication().assertReadAccessAllowed();
    }

    int index = getIndex(isPhysical, incompleteCode, isPoly);
    ConcurrentMap<TRef, TResult> map = getMap(index);
    TResult result = map.get(ref);
    if (result != null) {
      return result;
    }

    RecursionGuard.StackStamp stamp = myGuard.markStack();
    result =
        needToPreventRecursion
            ? myGuard.doPreventingRecursion(
                Trinity.create(ref, incompleteCode, isPoly),
                true,
                new Computable<TResult>() {
                  @Override
                  public TResult compute() {
                    return resolver.resolve(ref, incompleteCode);
                  }
                })
            : resolver.resolve(ref, incompleteCode);
    PsiElement element =
        result instanceof ResolveResult ? ((ResolveResult) result).getElement() : null;
    LOG.assertTrue(element == null || element.isValid(), result);

    if (stamp.mayCacheNow()) {
      cache(ref, map, result);
    }
    return result;
  }
  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;
      }

      myCachedDescriptor = descriptor;
      myDescriptorModCount = curModCount;
      myExtResourcesModCount = curExtResourcesModCount;
    }
    return myCachedDescriptor;
  }
  @NotNull
  public <T extends PsiPolyVariantReference> ResolveResult[] resolveWithCaching(
      @NotNull final T ref,
      @NotNull final PolyVariantContextResolver<T> resolver,
      boolean needToPreventRecursion,
      final boolean incompleteCode,
      @NotNull final PsiFile containingFile) {
    ProgressIndicatorProvider.checkCanceled();
    ApplicationManager.getApplication().assertReadAccessAllowed();

    int index = getIndex(containingFile.isPhysical(), incompleteCode, true);
    ConcurrentMap<T, ResolveResult[]> map = getMap(index);
    ResolveResult[] result = map.get(ref);
    if (result != null) {
      return result;
    }

    RecursionGuard.StackStamp stamp = myGuard.markStack();
    result =
        needToPreventRecursion
            ? myGuard.doPreventingRecursion(
                Pair.create(ref, incompleteCode),
                true,
                new Computable<ResolveResult[]>() {
                  @Override
                  public ResolveResult[] compute() {
                    return resolver.resolve(ref, containingFile, incompleteCode);
                  }
                })
            : resolver.resolve(ref, containingFile, incompleteCode);

    if (stamp.mayCacheNow()) {
      cache(ref, map, result);
    }
    return result == null ? ResolveResult.EMPTY_ARRAY : result;
  }