@NotNull
 public static SpellCheckingEditorCustomization getInstance(boolean enabled) {
   return (SpellCheckingEditorCustomization)
       SpellCheckingEditorCustomizationProvider.getInstance().getCustomization(enabled);
 }
/**
 * Allows to enforce editors to use/don't use spell checking ignoring user-defined spelling
 * inspection settings.
 *
 * <p>Thread-safe.
 *
 * @author Denis Zhdanov
 * @since Aug 20, 2010 3:54:42 PM
 */
public class SpellCheckingEditorCustomization extends SimpleEditorCustomization {
  /**
   * @deprecated use {@link SpellCheckingEditorCustomizationProvider#getEnabledCustomization()}
   *     instead
   */
  public static final SpellCheckingEditorCustomization ENABLED =
      (SpellCheckingEditorCustomization)
          SpellCheckingEditorCustomizationProvider.getInstance().getEnabledCustomization();

  /**
   * @deprecated use {@link SpellCheckingEditorCustomizationProvider#getDisabledCustomization()}
   *     instead
   */
  public static final SpellCheckingEditorCustomization DISABLED =
      (SpellCheckingEditorCustomization)
          SpellCheckingEditorCustomizationProvider.getInstance().getDisabledCustomization();

  private static final Map<String, LocalInspectionToolWrapper> SPELL_CHECK_TOOLS = new HashMap<>();
  private static final boolean READY = init();

  @NotNull
  public static SpellCheckingEditorCustomization getInstance(boolean enabled) {
    return (SpellCheckingEditorCustomization)
        SpellCheckingEditorCustomizationProvider.getInstance().getCustomization(enabled);
  }

  SpellCheckingEditorCustomization(boolean enabled) {
    super(enabled);
  }

  @SuppressWarnings({"unchecked"})
  private static boolean init() {
    // It's assumed that default spell checking inspection settings are just fine for processing all
    // types of data.
    // Please perform corresponding settings tuning if that assumption is broken at future.

    Class<LocalInspectionTool>[] inspectionClasses =
        (Class<LocalInspectionTool>[]) new Class<?>[] {SpellCheckingInspection.class};
    for (Class<LocalInspectionTool> inspectionClass : inspectionClasses) {
      try {
        LocalInspectionTool tool = inspectionClass.newInstance();
        SPELL_CHECK_TOOLS.put(tool.getShortName(), new LocalInspectionToolWrapper(tool));
      } catch (Throwable e) {
        return false;
      }
    }
    return true;
  }

  @Override
  public void customize(@NotNull EditorEx editor) {
    boolean apply = isEnabled();

    if (!READY) {
      return;
    }

    Project project = editor.getProject();
    if (project == null) {
      return;
    }

    PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
    if (file == null) {
      return;
    }

    Function<InspectionProfileImpl, InspectionProfileWrapper> strategy =
        file.getUserData(InspectionProfileWrapper.CUSTOMIZATION_KEY);
    if (strategy == null) {
      file.putUserData(
          InspectionProfileWrapper.CUSTOMIZATION_KEY, strategy = new MyInspectionProfileStrategy());
    }

    if (!(strategy instanceof MyInspectionProfileStrategy)) {
      return;
    }

    ((MyInspectionProfileStrategy) strategy).setUseSpellCheck(apply);

    if (apply) {
      editor.putUserData(IntentionManager.SHOW_INTENTION_OPTIONS_KEY, false);
    }

    // Update representation.
    DaemonCodeAnalyzer analyzer = DaemonCodeAnalyzer.getInstance(project);
    if (analyzer != null) {
      analyzer.restart(file);
    }
  }

  private static class MyInspectionProfileStrategy
      implements Function<InspectionProfileImpl, InspectionProfileWrapper> {
    private final Map<InspectionProfile, MyInspectionProfileWrapper> myWrappers =
        new WeakHashMap<>();
    private boolean myUseSpellCheck;

    @NotNull
    @Override
    public InspectionProfileWrapper apply(@NotNull InspectionProfileImpl inspectionProfile) {
      if (!READY) {
        return new InspectionProfileWrapper(inspectionProfile);
      }
      MyInspectionProfileWrapper wrapper = myWrappers.get(inspectionProfile);
      if (wrapper == null) {
        myWrappers.put(inspectionProfile, wrapper = new MyInspectionProfileWrapper());
      }
      wrapper.setUseSpellCheck(myUseSpellCheck);
      return wrapper;
    }

    public void setUseSpellCheck(boolean useSpellCheck) {
      myUseSpellCheck = useSpellCheck;
    }
  }

  private static class MyInspectionProfileWrapper extends InspectionProfileWrapper {
    private boolean myUseSpellCheck;

    MyInspectionProfileWrapper() {
      super(new InspectionProfileImpl("CommitDialog"));
    }

    @Override
    public boolean isToolEnabled(HighlightDisplayKey key, PsiElement element) {
      return myUseSpellCheck && SPELL_CHECK_TOOLS.containsKey(key.toString());
    }

    public void setUseSpellCheck(boolean useSpellCheck) {
      myUseSpellCheck = useSpellCheck;
    }
  }
}