private static void showParameterHint(
      final PsiElement element,
      final Editor editor,
      final Object[] descriptors,
      final Project project,
      @Nullable PsiElement highlighted,
      final int elementStart,
      final ParameterInfoHandler handler,
      final boolean requestFocus) {
    if (ParameterInfoController.isAlreadyShown(editor, elementStart)) return;

    if (editor.isDisposed() || !editor.getComponent().isVisible()) return;
    final ParameterInfoComponent component =
        new ParameterInfoComponent(descriptors, editor, handler, requestFocus);
    component.setParameterOwner(element);
    component.setRequestFocus(requestFocus);
    if (highlighted != null) {
      component.setHighlightedParameter(highlighted);
    }

    component.update(); // to have correct preferred size

    final LightweightHint hint = new LightweightHint(component);
    hint.setSelectingHint(true);
    final HintManagerImpl hintManager = HintManagerImpl.getInstanceImpl();
    final ShowParameterInfoHandler.BestLocationPointProvider provider =
        new MyBestLocationPointProvider(editor);
    final Pair<Point, Short> pos =
        provider.getBestPointPosition(hint, element, elementStart, true, HintManager.UNDER);

    PsiDocumentManager.getInstance(project)
        .performLaterWhenAllCommitted(
            () -> {
              if (editor.isDisposed() || DumbService.isDumb(project)) return;

              final Document document = editor.getDocument();
              if (document.getTextLength() < elementStart) return;

              HintHint hintHint =
                  HintManagerImpl.createHintHint(editor, pos.getFirst(), hint, pos.getSecond());
              hintHint.setExplicitClose(true);
              hintHint.setRequestFocus(requestFocus);

              Editor editorToShow =
                  editor instanceof EditorWindow ? ((EditorWindow) editor).getDelegate() : editor;
              // is case of injection we need to calculate position for EditorWindow
              // also we need to show the hint in the main editor because of intention bulb
              hintManager.showEditorHint(
                  hint,
                  editorToShow,
                  pos.getFirst(),
                  HintManager.HIDE_BY_ESCAPE | HintManager.UPDATE_BY_SCROLLING,
                  0,
                  false,
                  hintHint);
              new ParameterInfoController(project, editor, elementStart, hint, handler, provider);
            });
  }
  private void adjustPositionForLookup(@NotNull Lookup lookup) {
    if (!myHint.isVisible() || myEditor.isDisposed()) {
      Disposer.dispose(this);
      return;
    }

    IdeTooltip tooltip = myHint.getCurrentIdeTooltip();
    if (tooltip != null) {
      JRootPane root = myEditor.getComponent().getRootPane();
      if (root != null) {
        Point p = tooltip.getShowingPoint().getPoint(root.getLayeredPane());
        if (lookup.isPositionedAboveCaret()) {
          if (Position.above == tooltip.getPreferredPosition()) {
            myHint.pack();
            myHint.updatePosition(Position.below);
            myHint.updateLocation(p.x, p.y + tooltip.getPositionChangeY());
          }
        } else {
          if (Position.below == tooltip.getPreferredPosition()) {
            myHint.pack();
            myHint.updatePosition(Position.above);
            myHint.updateLocation(p.x, p.y - tooltip.getPositionChangeY());
          }
        }
      }
    }
  }
  void loadFromEditor(@NotNull Editor editor) {
    assertDispatchThread();
    LOG.assertTrue(!editor.isDisposed());
    clear();

    PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
    documentManager.commitDocument(editor.getDocument());
    PsiFile file = documentManager.getPsiFile(editor.getDocument());

    SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(myProject);
    EditorFoldingInfo info = EditorFoldingInfo.get(editor);
    FoldRegion[] foldRegions = editor.getFoldingModel().getAllFoldRegions();
    for (FoldRegion region : foldRegions) {
      if (!region.isValid()) continue;
      PsiElement element = info.getPsiElement(region);
      boolean expanded = region.isExpanded();
      boolean collapseByDefault =
          element != null
              && FoldingPolicy.isCollapseByDefault(element)
              && !FoldingUtil.caretInsideRange(editor, TextRange.create(region));
      if (collapseByDefault == expanded || element == null) {
        FoldingInfo fi = new FoldingInfo(region.getPlaceholderText(), expanded);
        if (element != null) {
          myPsiElements.add(smartPointerManager.createSmartPsiElementPointer(element, file));
          element.putUserData(FOLDING_INFO_KEY, fi);
        } else if (region.isValid()) {
          myRangeMarkers.add(region);
          region.putUserData(FOLDING_INFO_KEY, fi);
        }
      }
    }
  }
 private void releaseEditor() {
   if (myEditorAdapter != null) {
     final Editor editor = myEditorAdapter.getEditor();
     if (!editor.isDisposed()) {
       EditorFactory.getInstance().releaseEditor(editor);
     }
   }
 }
 private void releaseAllEditors() {
   for (final Editor editor : myEditors.values()) {
     if (!editor.isDisposed()) {
       EditorFactory.getInstance().releaseEditor(editor);
     }
   }
   myEditors.clear();
 }
  private void updateComponent() {
    if (!myHint.isVisible()) {
      Disposer.dispose(this);
      return;
    }

    final PsiFile file =
        PsiDocumentManager.getInstance(myProject).getPsiFile(myEditor.getDocument());
    CharSequence chars = myEditor.getDocument().getCharsSequence();
    boolean noDelimiter =
        myHandler instanceof ParameterInfoHandlerWithTabActionSupport
            && ((ParameterInfoHandlerWithTabActionSupport) myHandler)
                    .getActualParameterDelimiterType()
                == TokenType.WHITE_SPACE;
    int caretOffset = myEditor.getCaretModel().getOffset();
    final int offset =
        noDelimiter ? caretOffset : CharArrayUtil.shiftBackward(chars, caretOffset - 1, " \t") + 1;

    final UpdateParameterInfoContext context = new MyUpdateParameterInfoContext(offset, file);
    final Object elementForUpdating = myHandler.findElementForUpdatingParameterInfo(context);

    if (elementForUpdating != null) {
      myHandler.updateParameterInfo(elementForUpdating, context);
      if (!myDisposed
          && myHint.isVisible()
          && !myEditor.isDisposed()
          && myEditor.getComponent().getRootPane() != null) {
        myComponent.update();
        IdeTooltip tooltip = myHint.getCurrentIdeTooltip();
        short position =
            tooltip != null ? toShort(tooltip.getPreferredPosition()) : HintManager.UNDER;
        Pair<Point, Short> pos =
            myProvider.getBestPointPosition(
                myHint,
                elementForUpdating instanceof PsiElement ? (PsiElement) elementForUpdating : null,
                caretOffset,
                true,
                position);
        HintManagerImpl.adjustEditorHintPosition(myHint, myEditor, pos.getFirst(), pos.getSecond());
      }
    } else {
      context.removeHint();
    }
  }
 public static Editor openEditorFor(@NotNull PsiFile file, @NotNull Project project) {
   Document document = PsiDocumentManager.getInstance(project).getDocument(file);
   // may return editor injected in current selection in the host editor, not for the file passed
   // as argument
   VirtualFile virtualFile = file.getVirtualFile();
   if (virtualFile == null) {
     return null;
   }
   if (virtualFile instanceof VirtualFileWindow) {
     virtualFile = ((VirtualFileWindow) virtualFile).getDelegate();
   }
   Editor editor =
       FileEditorManager.getInstance(project)
           .openTextEditor(new OpenFileDescriptor(project, virtualFile, -1), false);
   if (editor == null || editor instanceof EditorWindow || editor.isDisposed()) return editor;
   if (document instanceof DocumentWindowImpl) {
     return EditorWindow.create((DocumentWindowImpl) document, (EditorImpl) editor, file);
   }
   return editor;
 }
 private VCOutputFile generateVCs(VirtualFile resolveFile, Editor editor, Project project) {
   boolean forceGeneration = true; // from action, they really mean it
   RunRESOLVEOnLanguageFile gen = new RunRESOLVEOnLanguageFile(resolveFile, project, "gen vcs");
   // SMTestRunnerConnectionUtil
   Map<String, String> argMap = new LinkedHashMap<>();
   argMap.put("-lib", RunRESOLVEOnLanguageFile.getContentRoot(project, resolveFile).getPath());
   argMap.put("-vcs", "");
   gen.addArgs(argMap);
   boolean successful = false;
   try {
     successful =
         ProgressManager.getInstance()
             .run(gen); // , "Generating", canBeCancelled, e.getData(PlatformDataKeys.PROJECT));
   } catch (Exception e1) {
   }
   if (successful && !editor.isDisposed()) {
     return gen.getVCOutput();
   }
   return null;
 }
  private void updateChangesForDocument(@NotNull final Document document) {
    ApplicationManager.getApplication().assertIsDispatchThread();
    if (DaemonListeners.isUnderIgnoredAction(null) || myProject.isDisposed()) return;
    List<Pair<PsiElement, Boolean>> toUpdate = changedElements.get(document);
    if (toUpdate == null) {
      // The document has been changed, but psi hasn't
      // We may still need to rehighlight the file if there were changes inside highlighted ranges.
      if (UpdateHighlightersUtil.isWhitespaceOptimizationAllowed(document)) return;

      // don't create PSI for files in other projects
      PsiElement file = PsiDocumentManager.getInstance(myProject).getCachedPsiFile(document);
      if (file == null) return;

      toUpdate = Collections.singletonList(Pair.create(file, true));
    }
    Application application = ApplicationManager.getApplication();
    final Editor editor = FileEditorManager.getInstance(myProject).getSelectedTextEditor();
    if (editor != null && !application.isUnitTestMode()) {
      application.invokeLater(
          () -> {
            if (!editor.isDisposed()) {
              EditorMarkupModel markupModel = (EditorMarkupModel) editor.getMarkupModel();
              PsiFile file =
                  PsiDocumentManager.getInstance(myProject).getPsiFile(editor.getDocument());
              TrafficLightRenderer.setOrRefreshErrorStripeRenderer(
                  markupModel, myProject, editor.getDocument(), file);
            }
          },
          ModalityState.stateForComponent(editor.getComponent()),
          myProject.getDisposed());
    }

    for (Pair<PsiElement, Boolean> changedElement : toUpdate) {
      PsiElement element = changedElement.getFirst();
      Boolean whiteSpaceOptimizationAllowed = changedElement.getSecond();
      updateByChange(element, document, whiteSpaceOptimizationAllowed);
    }
    changedElements.remove(document);
  }
 private void showHint(
     @NotNull String text,
     @Nullable final Editor editor,
     @NotNull final RelativePoint popupPosition,
     @NotNull FindUsagesHandler handler,
     int maxUsages,
     @NotNull FindUsagesOptions options) {
   JComponent label =
       createHintComponent(
           text, handler, popupPosition, editor, HIDE_HINTS_ACTION, maxUsages, options);
   if (editor == null || editor.isDisposed()) {
     HintManager.getInstance()
         .showHint(
             label,
             popupPosition,
             HintManager.HIDE_BY_ANY_KEY
                 | HintManager.HIDE_BY_TEXT_CHANGE
                 | HintManager.HIDE_BY_SCROLLING,
             0);
   } else {
     HintManager.getInstance().showInformationHint(editor, label);
   }
 }
  private void invokeCompletion(final ExpressionContext context) {
    final Project project = context.getProject();
    final Editor editor = context.getEditor();

    final PsiFile psiFile = editor != null ? PsiUtilBase.getPsiFileInEditor(editor, project) : null;
    Runnable runnable =
        () -> {
          if (project.isDisposed()
              || editor == null
              || editor.isDisposed()
              || psiFile == null
              || !psiFile.isValid()) return;

          // it's invokeLater, so another completion could have started
          if (CompletionServiceImpl.getCompletionService().getCurrentCompletion() != null) return;

          CommandProcessor.getInstance()
              .executeCommand(
                  project,
                  () -> {
                    // if we're in some completion's insert handler, make sure our new completion
                    // isn't treated as the second invocation
                    CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);

                    invokeCompletionHandler(project, editor);
                    Lookup lookup = LookupManager.getInstance(project).getActiveLookup();

                    if (lookup != null) {
                      lookup.addLookupListener(
                          new MyLookupListener(context, myCheckCompletionChar));
                    }
                  },
                  "",
                  null);
        };
    ApplicationManager.getApplication().invokeLater(runnable);
  }
 @NotNull
 public static Editor getInjectedEditorForInjectedFile(
     @NotNull Editor hostEditor, @Nullable final PsiFile injectedFile) {
   if (injectedFile == null || hostEditor instanceof EditorWindow || hostEditor.isDisposed())
     return hostEditor;
   Project project = hostEditor.getProject();
   if (project == null) project = injectedFile.getProject();
   Document document = PsiDocumentManager.getInstance(project).getDocument(injectedFile);
   if (!(document instanceof DocumentWindowImpl)) return hostEditor;
   DocumentWindowImpl documentWindow = (DocumentWindowImpl) document;
   SelectionModel selectionModel = hostEditor.getSelectionModel();
   if (selectionModel.hasSelection()) {
     int selstart = selectionModel.getSelectionStart();
     int selend = selectionModel.getSelectionEnd();
     if (!documentWindow.containsRange(selstart, selend)) {
       // selection spreads out the injected editor range
       return hostEditor;
     }
   }
   if (!documentWindow.isValid())
     return hostEditor; // since the moment we got hold of injectedFile and this moment call,
                        // document may have been dirtied
   return EditorWindow.create(documentWindow, (EditorImpl) hostEditor, injectedFile);
 }
Exemplo n.º 13
0
    private void showHint(Info info) {
      if (myDisposed || myEditor.isDisposed()) return;
      Component internalComponent = myEditor.getContentComponent();
      if (myHighlighter != null) {
        if (!info.isSimilarTo(myHighlighter.getStoredInfo())) {
          disposeHighlighter();
        } else {
          // highlighter already set
          internalComponent.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
          return;
        }
      }

      if (!info.isValid(myEditor.getDocument())) {
        return;
      }

      myHighlighter = installHighlighterSet(info, myEditor);

      DocInfo docInfo = info.getInfo();

      if (docInfo.text == null) return;

      if (myDocumentationManager.hasActiveDockedDocWindow()) {
        info.showDocInfo(myDocumentationManager);
      }

      HyperlinkListener hyperlinkListener =
          docInfo.docProvider == null
              ? null
              : new QuickDocHyperlinkListener(docInfo.docProvider, info.myElementAtPointer);
      final Ref<QuickDocInfoPane> quickDocPaneRef = new Ref<QuickDocInfoPane>();
      MouseListener mouseListener =
          new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
              QuickDocInfoPane pane = quickDocPaneRef.get();
              if (pane != null) {
                pane.mouseEntered(e);
              }
            }

            @Override
            public void mouseExited(MouseEvent e) {
              QuickDocInfoPane pane = quickDocPaneRef.get();
              if (pane != null) {
                pane.mouseExited(e);
              }
            }

            @Override
            public void mouseClicked(MouseEvent e) {
              QuickDocInfoPane pane = quickDocPaneRef.get();
              if (pane != null) {
                pane.mouseClicked(e);
              }
            }
          };
      Ref<Consumer<String>> newTextConsumerRef = new Ref<Consumer<String>>();
      JComponent label =
          HintUtil.createInformationLabel(
              docInfo.text, hyperlinkListener, mouseListener, newTextConsumerRef);
      Consumer<String> newTextConsumer = newTextConsumerRef.get();
      QuickDocInfoPane quickDocPane = null;
      if (docInfo.documentationAnchor != null) {
        quickDocPane =
            new QuickDocInfoPane(docInfo.documentationAnchor, info.myElementAtPointer, label);
        quickDocPaneRef.set(quickDocPane);
      }

      JComponent hintContent = quickDocPane == null ? label : quickDocPane;

      final LightweightHint hint = new LightweightHint(hintContent);
      myHint = hint;
      hint.addHintListener(
          new HintListener() {
            @Override
            public void hintHidden(EventObject event) {
              myHint = null;
            }
          });
      myDocAlarm.cancelAllRequests();
      if (newTextConsumer != null
          && docInfo.docProvider != null
          && docInfo.documentationAnchor != null) {
        fulfillDocInfo(
            docInfo.text,
            docInfo.docProvider,
            info.myElementAtPointer,
            docInfo.documentationAnchor,
            newTextConsumer,
            hint);
      }

      showHint(hint);
    }
Exemplo n.º 14
0
  public void patch(final FlooPatch res) {
    final TextBuf b = this;
    Flog.info("Got _on_patch");

    String text;
    String md5FromDoc;
    final Document d;

    String oldText = buf;
    VirtualFile virtualFile = b.getVirtualFile();
    if (virtualFile == null) {
      Flog.warn("VirtualFile is null, no idea what do do. Aborting everything %s", this);
      getBuf();
      return;
    }
    d = Buf.getDocumentForVirtualFile(virtualFile);
    if (d == null) {
      Flog.warn("Document not found for %s", virtualFile);
      getBuf();
      return;
    }
    String viewText;
    if (virtualFile.exists()) {
      viewText = d.getText();
      if (viewText.equals(oldText)) {
        b.forced_patch = false;
      } else if (!b.forced_patch) {
        b.forced_patch = true;
        oldText = viewText;
        b.send_patch(viewText);
        Flog.warn("Sending force patch for %s. this is dangerous!", b.path);
      }
    } else {
      viewText = oldText;
    }

    b.cancelTimeout();

    String md5Before = DigestUtils.md5Hex(viewText);
    if (!md5Before.equals(res.md5_before)) {
      Flog.warn("starting md5s don't match for %s. this is dangerous!", b.path);
    }

    List<diff_match_patch.Patch> patches = dmp.patch_fromText(res.patch);
    final Object[] results = dmp.patch_apply((LinkedList<diff_match_patch.Patch>) patches, oldText);
    final String patchedContents = (String) results[0];
    final boolean[] patchesClean = (boolean[]) results[1];
    final FlooPatchPosition[] positions = (FlooPatchPosition[]) results[2];

    for (boolean clean : patchesClean) {
      if (!clean) {
        Flog.log("Patch not clean for %s. Sending get_buf and setting readonly.", d);
        getBuf();
        return;
      }
    }
    // XXX: If patchedContents have carriage returns this will be a problem:
    String md5After = DigestUtils.md5Hex(patchedContents);
    if (!md5After.equals(res.md5_after)) {
      Flog.info("MD5 after mismatch (ours %s remote %s)", md5After, res.md5_after);
    }

    if (!d.isWritable()) {
      d.setReadOnly(false);
    }
    if (!ReadonlyStatusHandler.ensureDocumentWritable(context.project, d)) {
      Flog.info("Document: %s is not writable.", d);
      return;
    }

    final Editor[] editors = EditorFactory.getInstance().getEditors(d, context.project);
    final HashMap<ScrollingModel, Integer[]> original = new HashMap<ScrollingModel, Integer[]>();
    for (Editor editor : editors) {
      if (editor.isDisposed()) {
        continue;
      }
      ScrollingModel scrollingModel = editor.getScrollingModel();
      original.put(
          scrollingModel,
          new Integer[] {
            scrollingModel.getHorizontalScrollOffset(), scrollingModel.getVerticalScrollOffset()
          });
    }
    for (FlooPatchPosition flooPatchPosition : positions) {
      int start = Math.max(0, flooPatchPosition.start);
      int end_ld = Math.max(start + flooPatchPosition.end, start);
      end_ld = Math.min(end_ld, d.getTextLength());
      String contents = NEW_LINE.matcher(flooPatchPosition.text).replaceAll("\n");
      Throwable e = null;
      try {
        Listener.flooDisable();
        d.replaceString(start, end_ld, contents);
      } catch (Throwable exception) {
        e = exception;
      } finally {
        Listener.flooEnable();
      }

      if (e != null) {
        Flog.warn(e);
        getBuf();
        return;
      }
    }
    text = d.getText();
    md5FromDoc = DigestUtils.md5Hex(text);
    if (!md5FromDoc.equals(res.md5_after)) {
      Flog.info("md5FromDoc mismatch (ours %s remote %s)", md5FromDoc, res.md5_after);
      b.setGetBufTimeout();
    }

    for (Map.Entry<ScrollingModel, Integer[]> entry : original.entrySet()) {
      ScrollingModel model = entry.getKey();
      Integer[] offsets = entry.getValue();
      model.scrollHorizontally(offsets[0]);
      model.scrollVertically(offsets[1]);
    }

    b.set(text, md5FromDoc);
    Flog.log("Patched %s", res.path);
  }
 /**
  * Name <code>isValid</code> is in use in <code>java.awt.Component</code> so we change the name of
  * method to <code>isEditorValid</code>
  *
  * @return whether the editor is valid or not
  */
 boolean isEditorValid() {
   return myValid && !myEditor.isDisposed();
 }
Exemplo n.º 16
0
  void doPrintNotification(final Notification notification) {
    Editor editor = myLogEditor.getValue();
    if (editor.isDisposed()) {
      return;
    }

    Document document = editor.getDocument();
    boolean scroll =
        document.getTextLength() == editor.getCaretModel().getOffset()
            || !editor.getContentComponent().hasFocus();

    Long notificationTime = myProjectModel.getNotificationTime(notification);
    if (notificationTime == null) {
      return;
    }

    String date = DateFormatUtil.formatTimeWithSeconds(notificationTime) + " ";
    append(document, date);

    int startLine = document.getLineCount() - 1;

    EventLog.LogEntry pair =
        EventLog.formatForLog(notification, StringUtil.repeatSymbol(' ', date.length()));

    final NotificationType type = notification.getType();
    TextAttributesKey key =
        type == NotificationType.ERROR
            ? ConsoleViewContentType.LOG_ERROR_OUTPUT_KEY
            : type == NotificationType.INFORMATION
                ? ConsoleViewContentType.NORMAL_OUTPUT_KEY
                : ConsoleViewContentType.LOG_WARNING_OUTPUT_KEY;

    int msgStart = document.getTextLength();
    String message = pair.message;
    append(document, message);

    TextAttributes attributes =
        EditorColorsManager.getInstance().getGlobalScheme().getAttributes(key);
    int layer = HighlighterLayer.CARET_ROW + 1;
    editor
        .getMarkupModel()
        .addRangeHighlighter(
            msgStart,
            document.getTextLength(),
            layer,
            attributes,
            HighlighterTargetArea.EXACT_RANGE);

    for (Pair<TextRange, HyperlinkInfo> link : pair.links) {
      myHyperlinkSupport
          .getValue()
          .addHyperlink(
              link.first.getStartOffset() + msgStart,
              link.first.getEndOffset() + msgStart,
              null,
              link.second);
    }

    append(document, "\n");

    if (scroll) {
      editor.getCaretModel().moveToOffset(document.getTextLength());
      editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
    }

    if (notification.isImportant()) {
      highlightNotification(notification, pair.status, startLine, document.getLineCount() - 1);
    }
  }
  private void addVCGutterIcons(
      VCOutputFile vco, Editor editor, Project project, MyProverListener listener) {
    if (!editor.isDisposed()) {
      highlighters.clear();
      MarkupModel markup = editor.getMarkupModel();
      RESOLVEPluginController controller = RESOLVEPluginController.getInstance(project);
      markup.removeAllHighlighters();

      // A mapping from [line number] -> [vc_1, .., vc_j]
      Map<Integer, List<VC>> byLine = vco.getVCsGroupedByLineNumber();
      List<RangeHighlighter> vcRelatedHighlighters = new ArrayList<>();

      for (Map.Entry<Integer, List<VC>> vcsByLine : byLine.entrySet()) {
        List<AnAction> actionsPerVC = new ArrayList<>();
        // create clickable actions for each vc
        for (VC vc : vcsByLine.getValue()) {
          actionsPerVC.add(
              new VCNavigationAction(listener, vc.getNumber() + "", vc.getExplanation()));
        }

        highlighter =
            markup.addLineHighlighter(
                vcsByLine.getKey() - 1, HighlighterLayer.ELEMENT_UNDER_CARET, null);
        highlighter.setGutterIconRenderer(
            new GutterIconRenderer() {
              @NotNull
              @Override
              public Icon getIcon() {
                return RESOLVEIcons.VC;
              }

              @Override
              public boolean equals(Object obj) {
                return false;
              }

              @Override
              public int hashCode() {
                return 0;
              }

              @Override
              public boolean isNavigateAction() {
                return true;
              }

              @Nullable
              public ActionGroup getPopupMenuActions() {
                DefaultActionGroup g = new DefaultActionGroup();
                g.addAll(actionsPerVC);
                return g;
              }

              @Nullable
              public AnAction getClickAction() {
                return null;
              }
            });
        vcRelatedHighlighters.add(highlighter);
        highlighters.add(highlighter);
      }

      editor
          .getDocument()
          .addDocumentListener(
              new DocumentListener() {
                @Override
                public void beforeDocumentChange(DocumentEvent event) {}

                @Override
                public void documentChanged(DocumentEvent event) {
                  // remove all highlighters
                  for (RangeHighlighter h : vcRelatedHighlighters) {
                    markup.removeHighlighter(h);
                  }
                  VerifierPanel verifierPanel = controller.getVerifierPanel();
                  controller.getVerifierWindow().hide(null);
                  verifierPanel.revertToBaseGUI();
                }
              });
    }
  }