<commit_before>package com.intellij.xml.impl.schema;

import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.SchemaReferencesProvider;
import com.intellij.psi.xml.XmlTag;
import com.intellij.xml.XmlAttributeDescriptor;
import com.intellij.xml.XmlElementDescriptor;
import com.intellij.xml.XmlNSDescriptor;
import com.intellij.xml.impl.XmlLangAttributeDescriptor;
import com.intellij.xml.util.XmlUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;

import java.util.*;

/**
 * @author Mike
 */
public class ComplexTypeDescriptor extends TypeDescriptor {
  private final XmlNSDescriptorImpl myDocumentDescriptor;
  private XmlTag myTag;
  private volatile XmlElementDescriptor[] myElementDescriptors = null;
  private volatile XmlAttributeDescriptor[] myAttributeDescriptors = null;
  @NonNls
  public static final String PROHIBITED_ATTR_VALUE = "prohibited";
  @NonNls
  public static final String OTHER_NAMESPACE_ATTR_VALUE = "##other";
  @NonNls private static final String TRUE_ATTR_VALUE = "true";
  @NonNls private static final String REF_ATTR_NAME = "ref";
  @NonNls private static final String NAME_ATTR_NAME = "name";
  @NonNls private static final String ELEMENT_TAG_NAME = "element";
  @NonNls private static final String ATTRIBUTE_TAG_NAME = "attribute";

  public ComplexTypeDescriptor(XmlNSDescriptorImpl documentDescriptor, XmlTag tag) {
    myDocumentDescriptor = documentDescriptor;
    myTag = tag;
  }

  public XmlTag getDeclaration(){
    return myTag;
  }

  public XmlElementDescriptor[] getElements() {
    if(myElementDescriptors != null) return myElementDescriptors;

    synchronized(myDocumentDescriptor) {
      if(myElementDescriptors != null) return myElementDescriptors;
      Map<String,XmlElementDescriptor> map = new LinkedHashMap<String,XmlElementDescriptor>(5);
      collectElements(map, myTag, new HashSet<XmlTag>());
      addSubstitutionGroups(map);
      filterAbstractElements(map);
      return myElementDescriptors = map.values().toArray(
        new XmlElementDescriptor[map.values().size()]
      );
    }
  }

  private void addSubstitutionGroups(Map<String, XmlElementDescriptor> result) {
    mainLoop: while (true) {
      for (final XmlElementDescriptor xmlElementDescriptor : result.values()) {
        XmlElementDescriptorImpl descriptor = (XmlElementDescriptorImpl)xmlElementDescriptor;

        final XmlElementDescriptor[] substitutes = myDocumentDescriptor.getSubstitutes(descriptor.getName(), descriptor.getNamespace());
        boolean toContinue = false;

        for (XmlElementDescriptor substitute : substitutes) {
          if (result.get(substitute.getName()) == null) {
            toContinue = true;
            result.put(substitute.getName(), substitute);
          }
        }

        if (toContinue) continue mainLoop;
      }

      break;
    }
  }

  private static void filterAbstractElements(Map<String,XmlElementDescriptor> result) {
    for (Iterator<XmlElementDescriptor> iterator = result.values().iterator(); iterator.hasNext();) {
      XmlElementDescriptorImpl descriptor = (XmlElementDescriptorImpl)iterator.next();
      if (descriptor.isAbstract()) iterator.remove();
    }
  }

  public XmlAttributeDescriptor[] getAttributes() {
    if(myAttributeDescriptors != null) return myAttributeDescriptors;

    synchronized(myDocumentDescriptor) {
      if(myAttributeDescriptors != null) return myAttributeDescriptors;
      List<XmlAttributeDescriptor> result = new ArrayList<XmlAttributeDescriptor>();
      collectAttributes(result, myTag, new ArrayList<XmlTag>());

      if (myDocumentDescriptor.supportsStdAttributes()) addStdAttributes(result);

      return myAttributeDescriptors = result.toArray(new XmlAttributeDescriptor[result.size()]);
    }
  }

  private static void addStdAttributes(List<XmlAttributeDescriptor> result) {
    result.add(new XmlLangAttributeDescriptor());
  }

  private void collectElements(Map<String,XmlElementDescriptor> result, XmlTag tag, Set<XmlTag> visited) {
    if(visited.contains(tag)) return;
    visited.add(tag);
    if (XmlNSDescriptorImpl.equalsToSchemaName(tag, ELEMENT_TAG_NAME)) {
      String nameAttr = tag.getAttributeValue(NAME_ATTR_NAME);
<commit_msg>deadlock fixed<commit_after>package com.intellij.xml.impl.schema;

import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLock;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.SchemaReferencesProvider;
import com.intellij.psi.xml.XmlTag;
import com.intellij.xml.XmlAttributeDescriptor;
import com.intellij.xml.XmlElementDescriptor;
import com.intellij.xml.XmlNSDescriptor;
import com.intellij.xml.impl.XmlLangAttributeDescriptor;
import com.intellij.xml.util.XmlUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;

import java.util.*;

/**
 * @author Mike
 */
public class ComplexTypeDescriptor extends TypeDescriptor {
  private final XmlNSDescriptorImpl myDocumentDescriptor;
  private XmlTag myTag;
  private volatile XmlElementDescriptor[] myElementDescriptors = null;
  private volatile XmlAttributeDescriptor[] myAttributeDescriptors = null;
  @NonNls
  public static final String PROHIBITED_ATTR_VALUE = "prohibited";
  @NonNls
  public static final String OTHER_NAMESPACE_ATTR_VALUE = "##other";
  @NonNls private static final String TRUE_ATTR_VALUE = "true";
  @NonNls private static final String REF_ATTR_NAME = "ref";
  @NonNls private static final String NAME_ATTR_NAME = "name";
  @NonNls private static final String ELEMENT_TAG_NAME = "element";
  @NonNls private static final String ATTRIBUTE_TAG_NAME = "attribute";

  public ComplexTypeDescriptor(XmlNSDescriptorImpl documentDescriptor, XmlTag tag) {
    myDocumentDescriptor = documentDescriptor;
    myTag = tag;
  }

  public XmlTag getDeclaration(){
    return myTag;
  }

  public XmlElementDescriptor[] getElements() {
    if(myElementDescriptors != null) return myElementDescriptors;

    synchronized(PsiLock.LOCK) {
      if(myElementDescriptors != null) return myElementDescriptors;
      Map<String,XmlElementDescriptor> map = new LinkedHashMap<String,XmlElementDescriptor>(5);
      collectElements(map, myTag, new HashSet<XmlTag>());
      addSubstitutionGroups(map);
      filterAbstractElements(map);
      return myElementDescriptors = map.values().toArray(
        new XmlElementDescriptor[map.values().size()]
      );
    }
  }

  private void addSubstitutionGroups(Map<String, XmlElementDescriptor> result) {
    mainLoop: while (true) {
      for (final XmlElementDescriptor xmlElementDescriptor : result.values()) {
        XmlElementDescriptorImpl descriptor = (XmlElementDescriptorImpl)xmlElementDescriptor;

        final XmlElementDescriptor[] substitutes = myDocumentDescriptor.getSubstitutes(descriptor.getName(), descriptor.getNamespace());
        boolean toContinue = false;

        for (XmlElementDescriptor substitute : substitutes) {
          if (result.get(substitute.getName()) == null) {
            toContinue = true;
            result.put(substitute.getName(), substitute);
          }
        }

        if (toContinue) continue mainLoop;
      }

      break;
    }
  }

  private static void filterAbstractElements(Map<String,XmlElementDescriptor> result) {
    for (Iterator<XmlElementDescriptor> iterator = result.values().iterator(); iterator.hasNext();) {
      XmlElementDescriptorImpl descriptor = (XmlElementDescriptorImpl)iterator.next();
      if (descriptor.isAbstract()) iterator.remove();
    }
  }

  public XmlAttributeDescriptor[] getAttributes() {
    if(myAttributeDescriptors != null) return myAttributeDescriptors;

    synchronized(PsiLock.LOCK) {
      if(myAttributeDescriptors != null) return myAttributeDescriptors;
      List<XmlAttributeDescriptor> result = new ArrayList<XmlAttributeDescriptor>();
      collectAttributes(result, myTag, new ArrayList<XmlTag>());

      if (myDocumentDescriptor.supportsStdAttributes()) addStdAttributes(result);

      return myAttributeDescriptors = result.toArray(new XmlAttributeDescriptor[result.size()]);
    }
  }

  private static void addStdAttributes(List<XmlAttributeDescriptor> result) {
    result.add(new XmlLangAttributeDescriptor());
  }

  private void collectElements(Map<String,XmlElementDescriptor> result, XmlTag tag, Set<XmlTag> visited) {
    if(visited.contains(tag)) return;
    visited.add(tag);
    if (XmlNSDescriptorImpl.equalsToSchemaName(tag, ELEMENT_TAG_NAME)) {
      String nameAttr = tag.getAttributeValue(NAME_ATTR_NAME);

{'fraction_non_alphanumeric': 0.0945692883895131, 'fraction_numerical': 0.00023408239700374532, 'mean_word_length': 4.793220338983051, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 18}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5324372', 'n_tokens_mistral': 2374, 'n_tokens_neox': 2343, 'n_words': 493}