<commit_before>
package com.intellij.codeInsight.daemon.impl.analysis;

import com.intellij.codeInsight.CodeInsightUtil;
import com.intellij.codeInsight.daemon.XmlErrorMessages;
import com.intellij.codeInsight.daemon.impl.ShowAutoImportPass;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.HintAction;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.ide.util.FQNameCellRenderer;
import com.intellij.javaee.ExternalResourceManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.cache.impl.idCache.IdTableBuilding;
import com.intellij.psi.jsp.JspFile;
import com.intellij.psi.meta.PsiMetaData;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.IncorrectOperationException;
import com.intellij.xml.XmlElementDescriptor;
import com.intellij.xml.XmlExtension;
import com.intellij.xml.XmlSchemaProvider;
import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
import com.intellij.xml.impl.schema.XmlNSDescriptorImpl;
import com.intellij.xml.util.XmlUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
* User: Maxim.Mossienko
* Date: Nov 29, 2007
* Time: 11:13:33 PM
* To change this template use File | Settings | File Templates.
*/
public class CreateNSDeclarationIntentionFix implements HintAction, LocalQuickFix {
  @NotNull private final XmlTag myTag;
  private final String myNamespacePrefix;
  @Nullable private final PsiElement myElement;
  private XmlFile myFile;

  public CreateNSDeclarationIntentionFix(@NotNull final XmlTag tag, @NotNull final String namespacePrefix) {
    this(tag, namespacePrefix, null);
  }

  public CreateNSDeclarationIntentionFix(@NotNull final XmlTag tag,
                                         @NotNull final String namespacePrefix,
                                         @Nullable final PsiElement element) {
    myTag = tag;
    myNamespacePrefix = namespacePrefix;
    myElement = element;
    myFile = (XmlFile)tag.getContainingFile();
  }

  @NotNull
  public String getText() {
    final String alias = StringUtil.capitalize(XmlExtension.getExtension(myFile).getNamespaceAlias());
    return XmlErrorMessages.message("create.namespace.declaration.quickfix", alias);
  }

  @NotNull
  public String getName() {
    return getFamilyName();
  }

  @NotNull
  public String getFamilyName() {
    return getText();
  }

  public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
    final PsiFile containingFile = descriptor.getPsiElement().getContainingFile();
    Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
    final PsiFile file = editor != null ? PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()):null;
    if (file == null || file.getVirtualFile() != containingFile.getVirtualFile()) return;

    try { invoke(project, editor, containingFile); } catch (IncorrectOperationException ex) { ex.printStackTrace(); }
  }

  public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
    return true;
  }

  private static String[] guessNamespace(final PsiFile file, String name) {
    final Set<String> possibleUris = new LinkedHashSet<String>();
    final ExternalUriProcessor processor = new ExternalUriProcessor() {
      public void process(@NotNull String ns, final String url) {
        possibleUris.add(ns);
      }
    };

    processExternalUris(new TagMetaHandler(name), file, processor);

    return possibleUris.toArray( new String[possibleUris.size()] );
  }

  public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
    if (!CodeInsightUtil.prepareFileForWrite(file)) return;

    String[] namespaces;
    final XmlSchemaProvider provider = XmlSchemaProvider.getAvailableProvider((XmlFile)file);
    if (provider == null) {
      namespaces = guessNamespace(file, myElement == null ? myTag.getLocalName() : myElement.getText());
    } else {
      final Set<String> strings = provider.getAvailableNamespaces((XmlFile)file);
      namespaces = strings.toArray(new String[strings.size()]);
    }
    Arrays.sort(namespaces);

    runActionOverSeveralAttributeValuesAfterLettingUserSelectTheNeededOne(
      namespaces,
      project,
      new StringToAttributeProcessor() {
        public void doSomethingWithGivenStringToProduceXmlAttributeNowPlease(@NotNull final String namespace) throws IncorrectOperationException {

          final int offset = editor.getCaretModel().getOffset();
          final RangeMarker marker = editor.getDocument().createRangeMarker(offset, offset);
          final XmlExtension extension = XmlExtension.getExtension((XmlFile)file);
          extension.insertNamespaceDeclaration((XmlFile)file, editor, Collections.singleton(namespace), myNamespacePrefix, new XmlExtension.Runner<String, IncorrectOperationException>() {
            public void run(final String param) throws IncorrectOperationException {
              if (namespace.length() > 0) {
                editor.getCaretModel().moveToOffset(marker.getStartOffset());
              }
            }
          });
        }
      }, getTitle(),
      this,
      editor);
  }

  private String getTitle() {
    return XmlErrorMessages.message("select.namespace.title", StringUtil.capitalize(XmlExtension.getExtension(myFile).getNamespaceAlias()));
  }

  public boolean startInWriteAction() {
    return true;
  }

  public boolean showHint(final Editor editor) {
    final XmlFile xmlFile = (XmlFile)myTag.getContainingFile();
    final XmlSchemaProvider provider = XmlSchemaProvider.getAvailableProvider(xmlFile);
    if (provider == null) {
      return false;
    }
    final Set<String> namespaces = provider.getAvailableNamespaces(xmlFile);
    if (!namespaces.isEmpty()) {
      final String message = ShowAutoImportPass.getMessage(namespaces.size() > 1, namespaces.iterator().next());
      final String title = getTitle();
      final JspFile jspFile = PsiUtil.getJspFile(myTag);
      final PsiElement element = myElement == null ? myTag : myElement;
      final ImportNSAction action = new ImportNSAction(namespaces, jspFile, myElement != null ? null : myTag, editor, title);
      HintManager.getInstance().showQuestionHint(editor, message, element.getTextOffset(), element.getTextRange().getEndOffset(), action);
      return true;
    }
    return false;
  }

  private static boolean checkIfGivenXmlHasTheseWords(final String name, final XmlFile tldFileByUri) {
    if (name == null || name.length() == 0) return true;
    final List<String> list = StringUtil.getWordsIn(name);
    final String[] words = list.toArray(new String[list.size()]);
    final boolean[] wordsFound = new boolean[words.length];
    final int[] wordsFoundCount = new int[1];

    IdTableBuilding.ScanWordProcessor wordProcessor = new IdTableBuilding.ScanWordProcessor() {
      public void run(final CharSequence chars, int start, int end, char[] charArray) {
        if (wordsFoundCount[0] == words.length) return;
        final int foundWordLen = end - start;

        Next:
        for (int i = 0; i < words.length; ++i) {
          final String localName = words[i];
          if (wordsFound[i] || localName.length() != foundWordLen) continue;

          for (int j = 0; j < localName.length(); ++j) {<commit_msg>refactored<commit_after>
package com.intellij.codeInsight.daemon.impl.analysis;

import com.intellij.codeInsight.CodeInsightUtil;
import com.intellij.codeInsight.daemon.XmlErrorMessages;
import com.intellij.codeInsight.daemon.impl.ShowAutoImportPass;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.HintAction;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.ide.util.FQNameCellRenderer;
import com.intellij.javaee.ExternalResourceManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.cache.impl.idCache.IdTableBuilding;
import com.intellij.psi.meta.PsiMetaData;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.IncorrectOperationException;
import com.intellij.xml.XmlElementDescriptor;
import com.intellij.xml.XmlExtension;
import com.intellij.xml.XmlSchemaProvider;
import com.intellij.xml.impl.schema.AnyXmlElementDescriptor;
import com.intellij.xml.impl.schema.XmlNSDescriptorImpl;
import com.intellij.xml.util.XmlUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
* User: Maxim.Mossienko
* Date: Nov 29, 2007
* Time: 11:13:33 PM
* To change this template use File | Settings | File Templates.
*/
public class CreateNSDeclarationIntentionFix implements HintAction, LocalQuickFix {
  @NotNull private final XmlTag myTag;
  private final String myNamespacePrefix;
  @Nullable private final PsiElement myElement;
  private XmlFile myFile;

  public CreateNSDeclarationIntentionFix(@NotNull final XmlTag tag, @NotNull final String namespacePrefix) {
    this(tag, namespacePrefix, null);
  }

  public CreateNSDeclarationIntentionFix(@NotNull final XmlTag tag,
                                         @NotNull final String namespacePrefix,
                                         @Nullable final PsiElement element) {
    myTag = tag;
    myNamespacePrefix = namespacePrefix;
    myElement = element;
    myFile = (XmlFile)tag.getContainingFile();
  }

  @NotNull
  public String getText() {
    final String alias = StringUtil.capitalize(XmlExtension.getExtension(myFile).getNamespaceAlias());
    return XmlErrorMessages.message("create.namespace.declaration.quickfix", alias);
  }

  @NotNull
  public String getName() {
    return getFamilyName();
  }

  @NotNull
  public String getFamilyName() {
    return getText();
  }

  public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
    final PsiFile containingFile = descriptor.getPsiElement().getContainingFile();
    Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
    final PsiFile file = editor != null ? PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()):null;
    if (file == null || file.getVirtualFile() != containingFile.getVirtualFile()) return;

    try { invoke(project, editor, containingFile); } catch (IncorrectOperationException ex) { ex.printStackTrace(); }
  }

  public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
    return true;
  }

  private static String[] guessNamespace(final PsiFile file, String name) {
    final Set<String> possibleUris = new LinkedHashSet<String>();
    final ExternalUriProcessor processor = new ExternalUriProcessor() {
      public void process(@NotNull String ns, final String url) {
        possibleUris.add(ns);
      }
    };

    processExternalUris(new TagMetaHandler(name), file, processor);

    return possibleUris.toArray( new String[possibleUris.size()] );
  }

  public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
    if (!CodeInsightUtil.prepareFileForWrite(file)) return;

    String[] namespaces;
    final XmlSchemaProvider provider = XmlSchemaProvider.getAvailableProvider((XmlFile)file);
    if (provider == null) {
      namespaces = guessNamespace(file, myElement == null ? myTag.getLocalName() : myElement.getText());
    } else {
      final Set<String> strings = provider.getAvailableNamespaces((XmlFile)file);
      namespaces = strings.toArray(new String[strings.size()]);
    }
    Arrays.sort(namespaces);

    runActionOverSeveralAttributeValuesAfterLettingUserSelectTheNeededOne(
      namespaces,
      project,
      new StringToAttributeProcessor() {
        public void doSomethingWithGivenStringToProduceXmlAttributeNowPlease(@NotNull final String namespace) throws IncorrectOperationException {

          final int offset = editor.getCaretModel().getOffset();
          final RangeMarker marker = editor.getDocument().createRangeMarker(offset, offset);
          final XmlExtension extension = XmlExtension.getExtension((XmlFile)file);
          extension.insertNamespaceDeclaration((XmlFile)file, editor, Collections.singleton(namespace), myNamespacePrefix, new XmlExtension.Runner<String, IncorrectOperationException>() {
            public void run(final String param) throws IncorrectOperationException {
              if (namespace.length() > 0) {
                editor.getCaretModel().moveToOffset(marker.getStartOffset());
              }
            }
          });
        }
      }, getTitle(),
      this,
      editor);
  }

  private String getTitle() {
    return XmlErrorMessages.message("select.namespace.title", StringUtil.capitalize(XmlExtension.getExtension(myFile).getNamespaceAlias()));
  }

  public boolean startInWriteAction() {
    return true;
  }

  public boolean showHint(final Editor editor) {
    final XmlFile xmlFile = (XmlFile)myTag.getContainingFile();
    final XmlSchemaProvider provider = XmlSchemaProvider.getAvailableProvider(xmlFile);
    if (provider == null) {
      return false;
    }
    final Set<String> namespaces = provider.getAvailableNamespaces(xmlFile);
    if (!namespaces.isEmpty()) {
      final String message = ShowAutoImportPass.getMessage(namespaces.size() > 1, namespaces.iterator().next());
      final String title = getTitle();
      final PsiElement element = myElement == null ? myTag : myElement;
      final ImportNSAction action = new ImportNSAction(namespaces, myFile, myElement != null ? null : myTag, editor, title);
      HintManager.getInstance().showQuestionHint(editor, message, element.getTextOffset(), element.getTextRange().getEndOffset(), action);
      return true;
    }
    return false;
  }

  private static boolean checkIfGivenXmlHasTheseWords(final String name, final XmlFile tldFileByUri) {
    if (name == null || name.length() == 0) return true;
    final List<String> list = StringUtil.getWordsIn(name);
    final String[] words = list.toArray(new String[list.size()]);
    final boolean[] wordsFound = new boolean[words.length];
    final int[] wordsFoundCount = new int[1];

    IdTableBuilding.ScanWordProcessor wordProcessor = new IdTableBuilding.ScanWordProcessor() {
      public void run(final CharSequence chars, int start, int end, char[] charArray) {
        if (wordsFoundCount[0] == words.length) return;
        final int foundWordLen = end - start;

        Next:
        for (int i = 0; i < words.length; ++i) {
          final String localName = words[i];
          if (wordsFound[i] || localName.length() != foundWordLen) continue;

          for (int j = 0; j < localName.length(); ++j) {
{'fraction_non_alphanumeric': 0.10018248175182481, 'fraction_numerical': 0.0023114355231143554, 'mean_word_length': 4.339720688535238, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 22}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5533048', 'n_tokens_mistral': 4657, 'n_tokens_neox': 4538, 'n_words': 1026}