/*
 * Copyright 2016 The Bazel Authors. All rights reserved.
 *
 * 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.google.idea.blaze.base;

import com.google.common.collect.ImmutableList;
import com.google.idea.blaze.base.lang.buildfile.psi.StringLiteral;
import com.google.idea.blaze.base.lang.buildfile.psi.util.PsiUtils;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.testFramework.EditorTestUtil;
import com.intellij.testFramework.EditorTestUtil.CaretAndSelectionState;
import com.intellij.testFramework.EditorTestUtil.CaretInfo;
import com.intellij.testFramework.EdtTestUtil;
import com.intellij.testFramework.fixtures.CodeInsightTestFixture;
import com.intellij.util.ThrowableRunnable;
import java.util.Arrays;
import javax.annotation.Nullable;

/** Helper methods for editor tests. */
public class EditorTestHelper {
  private final Project project;
  private final CodeInsightTestFixture testFixture;

  public EditorTestHelper(Project project, CodeInsightTestFixture testFixture) {
    this.project = project;
    this.testFixture = testFixture;
  }

  public Editor openFileInEditor(PsiFile file) {
    return openFileInEditor(file.getVirtualFile());
  }

  public Editor openFileInEditor(VirtualFile file) {
    EdtTestUtil.runInEdtAndWait(
        (ThrowableRunnable<Throwable>) () -> testFixture.openFileInEditor(file));
    return testFixture.getEditor();
  }

  /** @return null if the only item was auto-completed */
  @Nullable
  public String[] getCompletionItemsAsStrings() {
    LookupElement[] completionItems = testFixture.completeBasic();
    if (completionItems == null) {
      return null;
    }
    return Arrays.stream(completionItems)
        .map(LookupElement::getLookupString)
        .toArray(String[]::new);
  }

  /** @return null if the only item was auto-completed */
  @Nullable
  public String[] getCompletionItemsAsSuggestionStrings() {
    LookupElement[] completionItems = testFixture.completeBasic();
    if (completionItems == null) {
      return null;
    }
    LookupElementPresentation presentation = new LookupElementPresentation();
    String[] strings = new String[completionItems.length];
    for (int i = 0; i < strings.length; i++) {
      completionItems[i].renderElement(presentation);
      strings[i] = presentation.getItemText();
    }
    return strings;
  }

  /** @return true if a LookupItem was inserted. */
  public boolean completeIfUnique() {
    LookupElement[] completionItems = testFixture.completeBasic();
    if (completionItems == null) {
      return true;
    }
    if (completionItems.length != 1) {
      return false;
    }
    testFixture.getLookup().setCurrentItem(completionItems[0]);
    testFixture.finishLookup(Lookup.NORMAL_SELECT_CHAR);
    return true;
  }

  /** Simulates a user typing action, at current caret position of file. */
  public void performTypingAction(PsiFile file, char typedChar) {
    performTypingAction(openFileInEditor(file.getVirtualFile()), typedChar);
  }

  /** Simulates a user typing action, at current caret position of document. */
  public void performTypingAction(Editor editor, char typedChar) {
    EditorTestUtil.performTypingAction(editor, typedChar);
    project.getComponent(PostprocessReformattingAspect.class).doPostponedFormatting();
    PsiDocumentManager.getInstance(project).commitAllDocuments();
  }

  /**
   * Clicks the specified button in current document at the current caret position
   *
   * @param action which button to click (see {@link IdeActions})
   */
  public final void pressButton(final String action) {
    CommandProcessor.getInstance()
        .executeCommand(project, () -> testFixture.performEditorAction(action), "", null);
  }

  public void setCaretPosition(Editor editor, int lineNumber, int columnNumber) {
    final CaretInfo info = new CaretInfo(new LogicalPosition(lineNumber, columnNumber), null);
    EdtTestUtil.runInEdtAndWait(
        (ThrowableRunnable<Throwable>)
            () ->
                EditorTestUtil.setCaretsAndSelection(
                    editor, new CaretAndSelectionState(ImmutableList.of(info), null)));
  }

  public void assertCaretPosition(Editor editor, int lineNumber, int columnNumber) {
    CaretInfo info = new CaretInfo(new LogicalPosition(lineNumber, columnNumber), null);
    EditorTestUtil.verifyCaretAndSelectionState(
        editor, new CaretAndSelectionState(ImmutableList.of(info), null));
  }

  public void replaceStringContents(StringLiteral string, String newStringContents) {
    Runnable renameOp =
        () -> {
          ASTNode node = string.getNode();
          node.replaceChild(
              node.getFirstChildNode(),
              PsiUtils.createNewLabel(string.getProject(), newStringContents));
        };
    ApplicationManager.getApplication()
        .runWriteAction(() -> CommandProcessor.getInstance().runUndoTransparentAction(renameOp));
  }
}

@@ -4312,29 +4312,8 @@
     
-project.getComponent(
 Post
@@ -4338,21 +4338,35 @@
 gAspect.
-class
+getInstance(project
 ).doPost

Fix EditorTestHelper to work with 2020.2