public Set<SNode> findDescendants(SNode node, Set<SNode> descendantsKnownInModel) {
    if (!myFindUsagesSupported) return new HashSet<SNode>();
    boolean changed = false;
    if (myModelDescriptor instanceof EditableSModelDescriptor) {
      changed = ((EditableSModelDescriptor) myModelDescriptor).isChanged();
    }
    boolean atLeastRootsLoaded =
        myModelDescriptor.getLoadingState().compareTo(ModelLoadingState.ROOTS_LOADED) >= 0;
    if (atLeastRootsLoaded && !changed && !descendantsKnownInModel.isEmpty())
      return descendantsKnownInModel;
    if (myNeedSearchForStrings
        && !myModelRootManager.containsString(myModelDescriptor, node.getId()))
      return descendantsKnownInModel;

    SModel model = myModelDescriptor.getSModel();
    Set<SNode> result = new HashSet<SNode>();
    if (model != null) {
      for (SNode root : model.roots()) {
        addDescendants(root, node, result);
      }
    }
    descendantsKnownInModel.clear();
    descendantsKnownInModel.addAll(result);
    return descendantsKnownInModel;
  }
  public boolean hasImportedModel(SModelDescriptor modelDescriptor) {
    if (!myFindUsagesSupported) return false;
    if (myNeedSearchForStrings
        && !myModelRootManager.containsString(myModelDescriptor, modelDescriptor.toString()))
      return false;

    SModel model = myModelDescriptor.getSModel();
    if (model == null) return false;

    return SModelOperations.getImportElement(model, modelDescriptor.getSModelReference()) != null;
  }
  public boolean hasLanguage(Language language) {
    if (!myFindUsagesSupported) return false;

    if (myNeedSearchForStrings
        && !myModelRootManager.containsString(myModelDescriptor, language.getModuleFqName()))
      return false;

    SModel model = myModelDescriptor.getSModel();
    if (model == null) return false;

    return SModelOperations.hasLanguage(model, language.getModuleReference());
  }