<commit_before>// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.daemon.impl;

import com.intellij.ide.actions.QualifiedNameProvider;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.ui.JBColor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.function.Function;
import java.util.function.Predicate;

import static com.intellij.openapi.keymap.KeymapUtil.getPreferredShortcutText;
import static com.intellij.openapi.util.io.FileUtil.toSystemIndependentName;
import static com.intellij.psi.util.PsiTreeUtil.getStubOrPsiParentOfType;
import static com.intellij.psi.util.PsiUtilCore.getVirtualFile;
import static com.intellij.ui.ColorUtil.toHex;

public final class GutterTooltipHelper {
  private static final JBColor CONTEXT_HELP_FOREGROUND
    = JBColor.namedColor("GutterTooltip.ContextHelp.foreground", new JBColor(0x787878, 0x878787));

  private GutterTooltipHelper() {
  }

  /**
   * @param elements        a collection of elements to create a formatted tooltip text
   * @param prefix          a text to insert before all elements
   * @param skipFirstMember {@code true} to skip a method (or field) name in the link to element
   * @param actionId        an action identifier to generate context help or {@code null} if not applicable
   */
  @NotNull
  public static <E extends PsiElement> String getTooltipText(@NotNull Collection<E> elements,
                                                             @NotNull String prefix,
                                                             boolean skipFirstMember,
                                                             @Nullable String actionId) {
    String elementPrefix = 1 < elements.size() ? "<br>&nbsp;&nbsp;&nbsp;&nbsp; " : " ";
    return getTooltipText(prefix, elements, e -> elementPrefix, e -> skipFirstMember, actionId);
  }

  /**
   * @param elements  a collection of elements to create a formatted tooltip text
   * @param function  a function that returns a text to insert before the current element
   * @param predicate a function that returns {@code true} to skip a method (or field) name for the current element
   * @param actionId  an action identifier to generate context help or {@code null} if not applicable
   */
  @NotNull
  public static <E extends PsiElement> String getTooltipText(@NotNull Collection<E> elements,
                                                             @NotNull Function<E, String> function,
                                                             @NotNull Predicate<E> predicate,
                                                             @Nullable String actionId) {
    return getTooltipText(null, elements, function, predicate, actionId);
  }

  @NotNull
  private static <E extends PsiElement> String getTooltipText(@Nullable String prefix,
                                                              @NotNull Collection<E> elements,
                                                              @NotNull Function<E, String> function,
                                                              @NotNull Predicate<E> predicate,
                                                              @Nullable String actionId) {
    StringBuilder sb = new StringBuilder("<html><body>");
    if (prefix != null) sb.append(prefix);
    for (E element : elements) {
      String elementPrefix = function.apply(element);
      if (elementPrefix != null) sb.append(elementPrefix);
      appendElement(sb, element, predicate.test(element));
    }
    appendContextHelp(sb, actionId);
    sb.append("</body></html>");
    return sb.toString();
  }

  private static void appendElement(@NotNull StringBuilder sb, @NotNull PsiElement element, boolean skip) {
    boolean useSingleLink = Registry.is("gutter.tooltip.single.link");
    String packageName = null;
    boolean addedSingleLink = useSingleLink && appendLink(sb, element);
    PsiElement skipped = null;
    if (skip && (element instanceof PsiMethod || element instanceof PsiField)) {
      skipped = element; // use skipped member as first separate link
      element = getContainingElement(element);
    }
    while (element != null) {
      String name = getPresentableName(element);
      if (name != null) {
        boolean addedLink = !useSingleLink && appendLink(sb, skipped != null ? skipped : element);
        // Swing uses simple HTML processing and paints a link incorrectly if it contains different fonts.
        // This is the reason why I use monospaced font not only for element name, but for a whole link.
        // By the same reason I have to comment out support for deprecated elements.
        //<commit_msg>IDEA-189709: use more descriptive names after review<commit_after>// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.daemon.impl;

import com.intellij.ide.actions.QualifiedNameProvider;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.ui.JBColor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.function.Function;
import java.util.function.Predicate;

import static com.intellij.openapi.keymap.KeymapUtil.getPreferredShortcutText;
import static com.intellij.openapi.util.io.FileUtil.toSystemIndependentName;
import static com.intellij.psi.util.PsiTreeUtil.getStubOrPsiParentOfType;
import static com.intellij.psi.util.PsiUtilCore.getVirtualFile;
import static com.intellij.ui.ColorUtil.toHex;

public final class GutterTooltipHelper {
  private static final JBColor CONTEXT_HELP_FOREGROUND
    = JBColor.namedColor("GutterTooltip.ContextHelp.foreground", new JBColor(0x787878, 0x878787));

  private GutterTooltipHelper() {
  }

  /**
   * @param elements        a collection of elements to create a formatted tooltip text
   * @param prefix          a text to insert before all elements
   * @param skipFirstMember {@code true} to skip a method (or field) name in the link to element
   * @param actionId        an action identifier to generate context help or {@code null} if not applicable
   */
  @NotNull
  public static <E extends PsiElement> String getTooltipText(@NotNull Collection<E> elements,
                                                             @NotNull String prefix,
                                                             boolean skipFirstMember,
                                                             @Nullable String actionId) {
    String elementPrefix = 1 < elements.size() ? "<br>&nbsp;&nbsp;&nbsp;&nbsp; " : " ";
    return getTooltipText(prefix, elements, e -> elementPrefix, e -> skipFirstMember, actionId);
  }

  /**
   * @param elements                 a collection of elements to create a formatted tooltip text
   * @param elementToPrefix          a function that returns a text to insert before the current element
   * @param skipFirstMemberOfElement a function that returns {@code true} to skip a method (or field) name for the current element
   * @param actionId                 an action identifier to generate context help or {@code null} if not applicable
   */
  @NotNull
  public static <E extends PsiElement> String getTooltipText(@NotNull Collection<E> elements,
                                                             @NotNull Function<E, String> elementToPrefix,
                                                             @NotNull Predicate<E> skipFirstMemberOfElement,
                                                             @Nullable String actionId) {
    return getTooltipText(null, elements, elementToPrefix, skipFirstMemberOfElement, actionId);
  }

  @NotNull
  private static <E extends PsiElement> String getTooltipText(@Nullable String prefix,
                                                              @NotNull Collection<E> elements,
                                                              @NotNull Function<E, String> elementToPrefix,
                                                              @NotNull Predicate<E> skipFirstMemberOfElement,
                                                              @Nullable String actionId) {
    StringBuilder sb = new StringBuilder("<html><body>");
    if (prefix != null) sb.append(prefix);
    for (E element : elements) {
      String elementPrefix = elementToPrefix.apply(element);
      if (elementPrefix != null) sb.append(elementPrefix);
      appendElement(sb, element, skipFirstMemberOfElement.test(element));
    }
    appendContextHelp(sb, actionId);
    sb.append("</body></html>");
    return sb.toString();
  }

  private static void appendElement(@NotNull StringBuilder sb, @NotNull PsiElement element, boolean skip) {
    boolean useSingleLink = Registry.is("gutter.tooltip.single.link");
    String packageName = null;
    boolean addedSingleLink = useSingleLink && appendLink(sb, element);
    PsiElement skipped = null;
    if (skip && (element instanceof PsiMethod || element instanceof PsiField)) {
      skipped = element; // use skipped member as first separate link
      element = getContainingElement(element);
    }
    while (element != null) {
      String name = getPresentableName(element);
      if (name != null) {
        boolean addedLink = !useSingleLink && appendLink(sb, skipped != null ? skipped : element);
        // Swing uses simple HTML processing and paints a link incorrectly if it contains different fonts.
        // This is the reason why I use monospaced font not only for element name, but for a whole link.
        // By the same reason I have to comment out support for deprecated elements.
        //
{'fraction_non_alphanumeric': 0.0802403333656362, 'fraction_numerical': 0.005426882449849792, 'mean_word_length': 2.4912043301759135, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 40, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6544365', 'n_tokens_mistral': 2565, 'n_tokens_neox': 2495, 'n_words': 826}