protected void doTest(final Test test) {
    assert myFile != null : "configure first";

    final VirtualFile vFile = myFile.getVirtualFile();
    assert vFile != null : "no virtual file for " + myFile;

    final FileEditor fileEditor =
        FileEditorManager.getInstance(getProject()).getSelectedEditor(vFile);
    assert fileEditor != null : "editor not opened for " + vFile;

    final StructureViewBuilder builder =
        LanguageStructureViewBuilder.INSTANCE.getStructureViewBuilder(myFile);
    assert builder != null : "no builder for " + myFile;

    StructureViewComponent component = null;
    try {
      component = (StructureViewComponent) builder.createStructureView(fileEditor, myProject);
      test.test(component);
    } finally {
      if (component != null) Disposer.dispose(component);
    }
  }
  @Override
  public void invoke(
      @NotNull final Project project, @NotNull final Editor editor, @NotNull PsiFile file) {
    PsiDocumentManager.getInstance(project).commitAllDocuments();

    PsiElement container = null;
    WeakReference<LightweightHint> ref = editor.getUserData(MY_LAST_HINT_KEY);
    if (ref != null) {
      LightweightHint hint = ref.get();
      if (hint != null && hint.isVisible()) {
        hint.hide();
        container = hint.getUserData(CONTAINER_KEY);
        if (container != null && !container.isValid()) {
          container = null;
        }
      }
    }

    StructureViewBuilder builder =
        LanguageStructureViewBuilder.INSTANCE.getStructureViewBuilder(file);
    if (builder instanceof TreeBasedStructureViewBuilder) {
      StructureViewModel model =
          ((TreeBasedStructureViewBuilder) builder).createStructureViewModel();
      boolean goOneLevelUp = true;
      if (container == null) {
        goOneLevelUp = false;
        Object element = model.getCurrentEditorElement();
        if (element instanceof PsiElement) {
          container = (PsiElement) element;
        }
      }
      while (true) {
        if (container == null || container instanceof PsiFile) {
          return;
        }
        if (goOneLevelUp) {
          goOneLevelUp = false;
        } else {
          if (!isDeclarationVisible(container, editor)) {
            break;
          }
        }

        container = container.getParent();
        while (container != null
            && DeclarationRangeUtil.getPossibleDeclarationAtRange(container) == null) {
          container = container.getParent();
          if (container instanceof PsiFile) return;
        }
      }
    }
    if (container == null) {
      return;
    }

    final TextRange range = DeclarationRangeUtil.getPossibleDeclarationAtRange(container);
    if (range == null) {
      return;
    }
    final PsiElement _container = container;
    ApplicationManager.getApplication()
        .invokeLater(
            new Runnable() {
              @Override
              public void run() {
                LightweightHint hint =
                    EditorFragmentComponent.showEditorFragmentHint(editor, range, true, true);
                if (hint != null) {
                  hint.putUserData(CONTAINER_KEY, _container);
                  editor.putUserData(MY_LAST_HINT_KEY, new WeakReference<LightweightHint>(hint));
                }
              }
            });
  }
 protected boolean isValidForFile(Project project, Editor editor, final PsiFile file) {
   return LanguageStructureViewBuilder.INSTANCE.getStructureViewBuilder(file)
       instanceof TreeBasedStructureViewBuilder;
 }