<commit_before>/*
 * Copyright 2000-2017 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.lang.html;


import com.intellij.application.options.CodeStyle;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
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.XmlRecursiveElementVisitor;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.formatter.xml.HtmlCodeStyleSettings;
import com.intellij.psi.impl.source.codeStyle.PostFormatProcessorHelper;
import com.intellij.psi.impl.source.codeStyle.PreFormatProcessor;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlTokenType;
import com.intellij.util.DocumentUtil;
import org.jetbrains.annotations.NotNull;

public class HtmlQuotesFormatPreprocessor implements PreFormatProcessor {
  @NotNull
  @Override
  public TextRange process(@NotNull ASTNode node, @NotNull TextRange range) {
    PsiElement psiElement = node.getPsi();
    if (psiElement != null &&
        psiElement.isValid() &&
        psiElement.getLanguage().is(HTMLLanguage.INSTANCE)) {
      CodeStyleSettings rootSettings = CodeStyle.getSettings(psiElement.getContainingFile());
      HtmlCodeStyleSettings htmlSettings = rootSettings.getCustomSettings(HtmlCodeStyleSettings.class);
      CodeStyleSettings.QuoteStyle quoteStyle = htmlSettings.HTML_QUOTE_STYLE;
      if (quoteStyle != CodeStyleSettings.QuoteStyle.None && htmlSettings.HTML_ENFORCE_QUOTES) {
        PostFormatProcessorHelper postFormatProcessorHelper =
          new PostFormatProcessorHelper(rootSettings.getCommonSettings(HTMLLanguage.INSTANCE));
        postFormatProcessorHelper.setResultTextRange(range);
        HtmlQuotesConverter converter = new HtmlQuotesConverter(quoteStyle, psiElement, postFormatProcessorHelper);
        Document document = converter.getDocument();
        if (document != null) {
          DocumentUtil.executeInBulk(document, true, converter);
        }
        return postFormatProcessorHelper.getResultTextRange();
      }
    }
    return range;
  }


  public static class HtmlQuotesConverter extends XmlRecursiveElementVisitor implements Runnable {
    private final TextRange myOriginalRange;
    private final Document myDocument;
    private final PsiDocumentManager myDocumentManager;
    private final PostFormatProcessorHelper myPostProcessorHelper;
    private final PsiElement myContext;
    private final String myNewQuote;

    public HtmlQuotesConverter(@NotNull CodeStyleSettings.QuoteStyle style,
                               @NotNull PsiElement context,
                               @NotNull PostFormatProcessorHelper postFormatProcessorHelper) {
      myPostProcessorHelper = postFormatProcessorHelper;
      Project project = context.getProject();
      PsiFile file = context.getContainingFile();
      myContext = context;<commit_msg>html formatter: don't enforce quotes on format if quote style matches injection host context and would break it (WEB-30108)<commit_after>/*
 * Copyright 2000-2017 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.lang.html;


import com.intellij.application.options.CodeStyle;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
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.XmlRecursiveElementVisitor;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.formatter.xml.HtmlCodeStyleSettings;
import com.intellij.psi.impl.source.codeStyle.PostFormatProcessorHelper;
import com.intellij.psi.impl.source.codeStyle.PreFormatProcessor;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlTokenType;
import com.intellij.util.DocumentUtil;
import org.jetbrains.annotations.NotNull;

public class HtmlQuotesFormatPreprocessor implements PreFormatProcessor {
  @NotNull
  @Override
  public TextRange process(@NotNull ASTNode node, @NotNull TextRange range) {
    PsiElement psiElement = node.getPsi();
    if (psiElement != null &&
        psiElement.isValid() &&
        psiElement.getLanguage().is(HTMLLanguage.INSTANCE)) {
      PsiFile file = psiElement.getContainingFile();
      PsiElement fileContext = file.getContext();
      String contextQuote = fileContext != null ? Character.toString(fileContext.getText().charAt(0)) : null;
      CodeStyleSettings rootSettings = CodeStyle.getSettings(file);
      HtmlCodeStyleSettings htmlSettings = rootSettings.getCustomSettings(HtmlCodeStyleSettings.class);
      CodeStyleSettings.QuoteStyle quoteStyle = htmlSettings.HTML_QUOTE_STYLE;
      if (quoteStyle != CodeStyleSettings.QuoteStyle.None
          && htmlSettings.HTML_ENFORCE_QUOTES
          && !StringUtil.equals(quoteStyle.quote, contextQuote)) {
        PostFormatProcessorHelper postFormatProcessorHelper =
          new PostFormatProcessorHelper(rootSettings.getCommonSettings(HTMLLanguage.INSTANCE));
        postFormatProcessorHelper.setResultTextRange(range);
        HtmlQuotesConverter converter = new HtmlQuotesConverter(quoteStyle, psiElement, postFormatProcessorHelper);
        Document document = converter.getDocument();
        if (document != null) {
          DocumentUtil.executeInBulk(document, true, converter);
        }
        return postFormatProcessorHelper.getResultTextRange();
      }
    }
    return range;
  }


  public static class HtmlQuotesConverter extends XmlRecursiveElementVisitor implements Runnable {
    private final TextRange myOriginalRange;
    private final Document myDocument;
    private final PsiDocumentManager myDocumentManager;
    private final PostFormatProcessorHelper myPostProcessorHelper;
    private final PsiElement myContext;
    private final String myNewQuote;

    public HtmlQuotesConverter(@NotNull CodeStyleSettings.QuoteStyle style,
                               @NotNull PsiElement context,
                               @NotNull PostFormatProcessorHelper postFormatProcessorHelper) {
      myPostProcessorHelper = postFormatProcessorHelper;
      Project project = context.getProject();
      PsiFile file = context.getContainingFile();
      myContext = context;
{'fraction_non_alphanumeric': 0.07718251394473992, 'fraction_numerical': 0.0038915553249448697, 'mean_word_length': 4.357887421820709, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 6}, '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': '7060565', 'n_tokens_mistral': 2086, 'n_tokens_neox': 2026, 'n_words': 501}