public static List<INodeSubstituteAction> createDefaultActions(
      @NotNull SNode applicableConcept,
      SNode parentNode,
      SNode currentChild,
      IChildNodeSetter setter,
      IOperationContext operationContext) {

    String conceptFqName = NameUtil.nodeFQName(applicableConcept);
    SNode link = null;
    if (setter instanceof DefaultChildNodeSetter) {
      DefaultChildNodeSetter defaultSetter = (DefaultChildNodeSetter) setter;
      link = defaultSetter.getLinkDeclaration();
    }

    IScope scope = operationContext.getScope();

    if (!ModelConstraintsManager.canBeChild(conceptFqName, operationContext, parentNode, link)) {
      return new ArrayList<INodeSubstituteAction>();
    }

    SNode smartRef = ReferenceConceptUtil.getCharacteristicReference(applicableConcept);
    if (smartRef != null) {
      List<INodeSubstituteAction> smartActions =
          createSmartReferenceActions(
              applicableConcept, smartRef, parentNode, currentChild, setter, operationContext);
      if (smartActions != null) {
        return smartActions;
      } else {
        return Collections.emptyList();
      }
    } else {
      return Arrays.asList(
          (INodeSubstituteAction)
              new DefaultChildNodeSubstituteAction(
                  applicableConcept, parentNode, currentChild, setter, scope));
    }
  }
예제 #2
0
  @Override
  public void doUpdate(AnActionEvent event) {
    removeAll();

    SModel modelDescriptor = event.getData(MPSDataKeys.CONTEXT_MODEL);
    if (modelDescriptor == null) {
      setEnabledState(event.getPresentation(), false);
      return;
    }

    if (!(modelDescriptor instanceof EditableSModel)
        || (((EditableSModel) modelDescriptor).isReadOnly())) {
      event.getPresentation().setEnabled(false);
      event.getPresentation().setVisible(false);
      return;
    }

    IScope scope = event.getData(MPSDataKeys.SCOPE);
    IOperationContext context = event.getData(MPSDataKeys.OPERATION_CONTEXT);

    boolean isStubModel =
        SModelStereotype.isStubModelStereotype(SModelStereotype.getStereotype(modelDescriptor));
    if (scope == null || context == null || isStubModel) {
      setEnabledState(event.getPresentation(), false);
      return;
    }

    boolean inEditor = event.getData(MPSDataKeys.LOGICAL_VIEW_SELECTION_SIZE) == null;

    if (!inEditor) {
      Integer selectedItemsCount = event.getData(MPSDataKeys.LOGICAL_VIEW_SELECTION_SIZE);
      boolean singleItemSelected = selectedItemsCount != null && selectedItemsCount == 1;

      if (!singleItemSelected) {
        setEnabledState(event.getPresentation(), false);
        return;
      }

      TreeNode treeNode = event.getData(MPSDataKeys.LOGICAL_VIEW_NODE);

      if (!(treeNode instanceof PackageNode)) {
        myPackage = null;
      } else {
        final PackageNode node = (PackageNode) treeNode;
        myPackage = node.getPackage();
      }
    } else {
      SNode node = event.getData(MPSDataKeys.NODE);
      myPackage = null;
      if (node != null) {
        SNode root = node.getContainingRoot();
        myPackage =
            SNodeAccessUtil.getProperty(root, SNodeUtil.property_BaseConcept_virtualPackage);
      }
    }

    setEnabledState(event.getPresentation(), true);

    List<Language> modelLanguages = SModelOperations.getLanguages(modelDescriptor, scope);

    LanguageAspect aspect = Language.getModelAspect(modelDescriptor);
    if (aspect != null) {
      SModuleReference ref = aspect.getMainLanguage();
      Language lang = scope.getLanguage(ref);
      if (lang != null) {
        modelLanguages.remove(lang);

        for (SNode conceptDeclaration : lang.getConceptDeclarations()) {
          if (ModelConstraintsManager.canBeRoot(
              context, NameUtil.nodeFQName(conceptDeclaration), modelDescriptor)) {
            add(
                new NewRootNodeAction(
                    new jetbrains.mps.smodel.SNodePointer(conceptDeclaration), modelDescriptor));
          }
        }

        addSeparator();
      }
    }

    Collections.sort(modelLanguages, new ToStringComparator());

    List<Language> languagesWithRoots = new ArrayList<Language>();
    for (final Language language : modelLanguages) {
      for (SNode conceptDeclaration : language.getConceptDeclarations()) {
        if (ModelConstraintsManager.canBeRoot(
            context, NameUtil.nodeFQName(conceptDeclaration), modelDescriptor)) {
          languagesWithRoots.add(language);
          break;
        }
      }
    }

    boolean plain = myPlain || (languagesWithRoots.size() == 1 && aspect == null);

    for (final Language language : languagesWithRoots) {
      String name = language.getModuleName();
      Icon icon = IconManager.getIconForNamespace(language.getModuleName());
      BaseGroup langRootsGroup;

      if (!plain) {
        langRootsGroup = new BaseGroup(NameUtil.compactNamespace(name), name, icon);
        langRootsGroup.setPopup(true);
      } else {
        langRootsGroup = this;
      }

      for (SNode conceptDeclaration : language.getConceptDeclarations()) {
        if (ModelConstraintsManager.getInstance()
            .canBeRoot(context, NameUtil.nodeFQName(conceptDeclaration), modelDescriptor)) {
          langRootsGroup.add(
              new NewRootNodeAction(
                  new jetbrains.mps.smodel.SNodePointer(conceptDeclaration), modelDescriptor));
        }
      }
      if (!plain) {
        this.add(langRootsGroup);
      } else {
        this.addSeparator();
      }
    }

    if (getChildrenCount() == 0) {
      add(
          ActionManager.getInstance()
              .getAction(
                  "jetbrains.mps.ide.editor.actions.AddLanguageImport_Action" /* FIXME AddLanguageImport_Action.class.getName()*/));
    }
  }
  public void checkNode(
      final SNode node,
      LanguageErrorsComponent component,
      final IOperationContext operationContext,
      IScope scope) {
    final ConstraintsDescriptor newDescriptor =
        ConceptRegistry.getInstance().getConstraintsDescriptorNew(node.getConceptFqName());

    final CheckingNodeContext checkingNodeContext =
        new jetbrains.mps.smodel.structure.CheckingNodeContext();

    if (SNodeOperations.getParent(node) != null) {
      component.addDependency(SNodeOperations.getParent(node));
    }
    if (SNodeOperations.getParent(node) != null
        && !(jetbrains.mps.smodel.SNodeOperations.isUnknown(SNodeOperations.getParent(node)))) {
      final SNode link = SNodeOperations.getContainingLinkDeclaration(node);
      if (link == null) {
        component.addError(node, "Child in a role with unknown link", null);
        return;
      }
      boolean canBeChild =
          component.runCheckingAction(
              new _FunctionTypes._return_P0_E0<Boolean>() {
                public Boolean invoke() {
                  return ModelConstraintsManager.canBeChild(
                      newDescriptor,
                      node.getConceptFqName(),
                      operationContext,
                      SNodeOperations.getParent(node),
                      link,
                      checkingNodeContext);
                }
              });
      if (!(canBeChild)) {
        SNode rule = getBreakingNodeAndClearContext(checkingNodeContext);
        component.addError(
            node,
            "Node " + node + " cannot be child of node " + SNodeOperations.getParent(node),
            rule);
      }
    }

    if (node.isRoot()) {
      boolean canBeRoot =
          component.runCheckingAction(
              new _FunctionTypes._return_P0_E0<Boolean>() {
                public Boolean invoke() {
                  return ModelConstraintsManager.canBeRoot(
                      newDescriptor,
                      operationContext,
                      node.getConceptFqName(),
                      SNodeOperations.getModel(node),
                      checkingNodeContext);
                }
              });
      if (!(canBeRoot)) {
        SNode rule = getBreakingNodeAndClearContext(checkingNodeContext);
        component.addError(node, "Not rootable concept added as root", rule);
      }
    }

    for (SNode child : SNodeOperations.getChildren(node)) {
      component.addDependency(child);
      final SNode childConcept = SNodeOperations.getConceptDeclaration(child);
      final SNode childLink = SNodeOperations.getContainingLinkDeclaration(child);
      if (childLink == null) {
        continue;
      }
      boolean canBeParent =
          component.runCheckingAction(
              new _FunctionTypes._return_P0_E0<Boolean>() {
                public Boolean invoke() {
                  return ModelConstraintsManager.canBeParent(
                      newDescriptor,
                      node,
                      childConcept,
                      childLink,
                      operationContext,
                      checkingNodeContext);
                }
              });
      if (!(canBeParent)) {
        SNode rule = getBreakingNodeAndClearContext(checkingNodeContext);
        component.addError(node, "Node " + node + " cannot be parent of node " + child, rule);
      }

      // todo: do it right, with runCheckingAction!
      if (!(ModelConstraintsManager.canBeAncestor(
          node, childConcept, operationContext, checkingNodeContext))) {
        SNode rule =
            SNodeOperations.cast(
                getBreakingNodeAndClearContext(checkingNodeContext),
                "jetbrains.mps.lang.constraints.structure.ConstraintFunction_CanBeAnAncestor");
        component.addError(
            child,
            "Concept "
                + SLinkOperations.getTarget(
                    SNodeOperations.as(
                        SNodeOperations.getParent(rule),
                        "jetbrains.mps.lang.constraints.structure.ConceptConstraints"),
                    "concept",
                    false)
                + " cannot be ancestor of node "
                + child,
            rule);
      }
    }

    // Properties validation
    SNode concept = SNodeOperations.getConceptDeclaration(node);
    component.addDependency(concept);
    ConceptAndSuperConceptsScope chs = new ConceptAndSuperConceptsScope(concept);
    for (SNode parentConcept : chs.getConcepts()) {
      component.addDependency(parentConcept);
    }
    List<SNode> props =
        ((List<SNode>)
            chs.getNodes(
                new Condition<SNode>() {
                  public boolean met(SNode n) {
                    return SNodeOperations.isInstanceOf(
                        n, "jetbrains.mps.lang.structure.structure.PropertyDeclaration");
                  }
                }));
    for (SNode p : ListSequence.fromList(props)) {
      final PropertySupport ps = PropertySupport.getPropertySupport(p);
      final String propertyName = SPropertyOperations.getString(p, "name");
      if (propertyName == null) {
        LOG.error(
            "Property declaration has a null name, declaration id: "
                + p.getSNodeId()
                + ", model: "
                + SNodeOperations.getModel(p).getSModelFqName());
        continue;
      }
      final String value = ps.fromInternalValue(node.getProperty(propertyName));
      final PropertyConstraintsDescriptor propertyDescriptor =
          newDescriptor.getProperty(propertyName);
      boolean canSetValue =
          component.runCheckingAction(
              new _FunctionTypes._return_P0_E0<Boolean>() {
                public Boolean invoke() {
                  return ps.canSetValue(
                      propertyDescriptor, node, propertyName, value, operationContext.getScope());
                }
              });
      if (!(canSetValue)) {
        // RE-2426 Ñ disabling the "Property constraint violation for property" error messages

        /*
        // TODO this is a hack for anonymous classes
        if ("name".equals(SPropertyOperations.getString(p, "name")) && ("AnonymousClass".equals(SPropertyOperations.getString(concept, "name")) || "InternalAnonymousClass".equals(SPropertyOperations.getString(concept, "name")))) {
          continue;
        }
        // todo find a rule
        component.addError(node, "Property constraint violation for property \"" + SPropertyOperations.getString(p, "name") + "\"", null, new PropertyMessageTarget(SPropertyOperations.getString(p, "name")));
        */
      }
    }
  }
  private static List<INodeSubstituteAction> createActions_internal(
      SNode parentNode,
      SNode currentChild,
      SNode childConcept,
      IChildNodeSetter childSetter,
      IOperationContext context) {
    List<INodeSubstituteAction> resultActions = new ArrayList<INodeSubstituteAction>();
    if (childConcept == null) {
      return resultActions;
    }

    // special case
    if (childConcept == SModelUtil.getBaseConcept()) {
      if ((currentChild == null
          || currentChild.getConcept().getId().equals(SNodeUtil.concept_BaseConcept))) {
        resultActions = new ArrayList<INodeSubstituteAction>();
        ISearchScope conceptsSearchScope =
            SModelSearchUtil.createConceptsFromModelLanguagesScope(
                parentNode.getModel(), true, context.getScope());
        List<SNode> allVisibleConcepts = conceptsSearchScope.getNodes();
        for (final SNode visibleConcept : allVisibleConcepts) {
          resultActions.add(
              new DefaultChildNodeSubstituteAction(
                  visibleConcept, parentNode, currentChild, childSetter, context.getScope()) {
                public String getMatchingText(String pattern) {
                  return getMatchingText(pattern, true, true);
                }

                public String getVisibleMatchingText(String pattern) {
                  return getMatchingText(pattern);
                }

                public String getDescriptionText(String pattern) {
                  String fqName = NameUtil.nodeFQName(visibleConcept);
                  return "lang: "
                      + NameUtil.compactNamespace(NameUtil.namespaceFromConceptFQName(fqName));
                }

                public Icon getIconFor(String pattern) {
                  return getIconFor(pattern, true);
                }
              });
        }
        return resultActions;
      }

      // pretend we are going to substitute more concrete concept
      childConcept = ChildSubstituteActionsUtil.getRefinedChildConcept(currentChild);
    }

    Language primaryLanguage = SModelUtil.getDeclaringLanguage(childConcept);
    if (primaryLanguage == null) {
      LOG.error(
          "Couldn't build actions : couldn't get declaring language for concept "
              + org.jetbrains.mps.openapi.model.SNodeUtil.getDebugText(childConcept));
      return resultActions;
    }

    List<SNode> allBuilders =
        ChildSubstituteActionsUtil.getActionsBuilders(
            parentNode, currentChild, childConcept, childSetter, context);
    if (!ChildSubstituteActionsUtil.containsRemoveDefaults(allBuilders)) {
      resultActions.addAll(
          createPrimaryChildSubstituteActions(
              parentNode, currentChild, childConcept, childSetter, context));
    }

    for (SNode builder : allBuilders) {
      List<INodeSubstituteAction> addActions =
          ChildSubstituteActionsUtil.invokeActionFactory(
              builder, parentNode, currentChild, childConcept, childSetter, context);
      resultActions.addAll(addActions);
    }

    for (SNode builder : allBuilders) {
      resultActions =
          ChildSubstituteActionsUtil.applyActionFilter(
              builder, resultActions, parentNode, currentChild, childConcept, context);
    }

    if (childSetter instanceof DefaultChildNodeSetter
        || childSetter instanceof AbstractCellMenuPart_ReplaceNode_CustomNodeConcept
            && currentChild != null) {
      SNode linkDeclaration;
      if (childSetter instanceof DefaultChildNodeSetter) {
        linkDeclaration = ((DefaultChildNodeSetter) childSetter).myLinkDeclaration;
      } else {
        linkDeclaration = currentChild.getRoleLink();
      }

      Iterator<INodeSubstituteAction> it = resultActions.iterator();
      while (it.hasNext()) {
        INodeSubstituteAction action = it.next();

        SNode conceptNode = action.getOutputConcept();
        if (conceptNode == null) {
          continue;
        }

        if (!ModelConstraintsManager.canBeParent(parentNode, conceptNode, linkDeclaration, context)
            || !ModelConstraintsManager.canBeAncestor(parentNode, conceptNode, context)) {
          it.remove();
        }
      }
    }

    return resultActions;
  }