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; }