package jetbrains.mps.lang.generator.helper; /*Generated by MPS */ import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import jetbrains.mps.smodel.adapter.structure.MetaAdapterFactory; import jetbrains.mps.openapi.editor.cells.EditorCell; import org.jetbrains.mps.openapi.language.SProperty; import jetbrains.mps.smodel.legacy.ConceptMetaInfoConverter; import jetbrains.mps.lang.smodel.generator.smodelAdapter.AttributeOperations; import jetbrains.mps.lang.smodel.generator.smodelAdapter.IAttributeDescriptor; import org.jetbrains.mps.openapi.language.SReferenceLink; import org.jetbrains.mps.openapi.language.SAbstractConcept; import jetbrains.mps.internal.collections.runtime.ListSequence; import jetbrains.mps.internal.collections.runtime.IWhereFilter; import jetbrains.mps.smodel.action.SNodeFactoryOperations; import jetbrains.mps.lang.core.behavior.PropertyAttribute__BehaviorDescriptor; import jetbrains.mps.lang.core.behavior.LinkAttribute__BehaviorDescriptor; import jetbrains.mps.internal.collections.runtime.Sequence; import jetbrains.mps.internal.collections.runtime.IVisitor; import jetbrains.mps.nodeEditor.cells.EditorCell_Property; import jetbrains.mps.nodeEditor.cells.ModelAccessor; import jetbrains.mps.nodeEditor.cells.PropertyAccessor; public final class EditingUtil { public static boolean isNodeMacroApplicable(SNode node) { return isAnyMacroApplicable(node) || SNodeOperations.isInstanceOf(node, MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd47ed6742L, "jetbrains.mps.lang.generator.structure.NodeMacro")); } public static boolean isPropertyMacroApplicable(SNode node, EditorCell cell) { if (cell == null) { return false; } if (!(isAnyMacroApplicable(node))) { return false; } // ----- // it can be 'ref.cell->{name}'. in this case both are 'applicable'. but link has priority String linkRole = EditingUtil.getEditedLinkRole(cell); if (linkRole != null) { return false; } String propertyName = EditingUtil.getEditedPropertyName(cell); if (propertyName == null) { return false; } SProperty p = ((ConceptMetaInfoConverter) SNodeOperations.getConcept(node)).convertProperty(propertyName); return AttributeOperations.getAttribute(node, new IAttributeDescriptor.PropertyAttribute(MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd47e9f6f0L, "jetbrains.mps.lang.generator.structure.PropertyMacro"), p)) == null; } public static boolean isReferenceMacroApplicable(SNode node, EditorCell cell) { if (cell == null) { return false; } if (!(isAnyMacroApplicable(node))) { return false; } String linkRole = EditingUtil.getEditedLinkRole(cell); if (linkRole == null) { return false; } SNode referentNode = EditingUtil.getEditedLinkReferentNode(cell); SReferenceLink ref = ((ConceptMetaInfoConverter) SNodeOperations.getConcept(node)).convertAssociation(linkRole); return AttributeOperations.getAttribute(referentNode, new IAttributeDescriptor.LinkAttribute(MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd7f44d616L, "jetbrains.mps.lang.generator.structure.ReferenceMacro"), ref)) == null; } public static boolean isAnyMacroApplicable(SNode node) { // not inside 'root template annotation' if (SNodeOperations.getNodeAncestor(node, MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x11017244494L, "jetbrains.mps.lang.generator.structure.RootTemplateAnnotation"), true, false) != null) { return false; } // not inside any kind of macro (code shown in inspector) but OK on a macro node itself SNode ancestorTemplateElement = SNodeOperations.getNodeAncestorWhereConceptInList(node, new SAbstractConcept[]{MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd47ed6742L, "jetbrains.mps.lang.generator.structure.NodeMacro"), MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd47e9f6f0L, "jetbrains.mps.lang.generator.structure.PropertyMacro"), MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd7f44d616L, "jetbrains.mps.lang.generator.structure.ReferenceMacro"), MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x112103dd1e8L, "jetbrains.mps.lang.generator.structure.InlineTemplate_RuleConsequence"), MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x7b85dded0be53d6cL, "jetbrains.mps.lang.generator.structure.InlineTemplateWithContext_RuleConsequence"), MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xff1b29b76cL, "jetbrains.mps.lang.generator.structure.TemplateFragment")}, true, false); if (ancestorTemplateElement != null) { // exception: can be inside 'alternativeConsequence' in IF-macro if (SNodeOperations.isInstanceOf(ancestorTemplateElement, MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x112103dd1e8L, "jetbrains.mps.lang.generator.structure.InlineTemplate_RuleConsequence")) || SNodeOperations.isInstanceOf(ancestorTemplateElement, MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x7b85dded0be53d6cL, "jetbrains.mps.lang.generator.structure.InlineTemplateWithContext_RuleConsequence"))) { return true; } return false; } // inside 'root template' if (AttributeOperations.getAttribute(SNodeOperations.getContainingRoot(node), new IAttributeDescriptor.NodeAttribute(MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x11017244494L, "jetbrains.mps.lang.generator.structure.RootTemplateAnnotation"))) != null) { return true; } // inside template declaration if (SNodeOperations.getNodeAncestorWhereConceptInList(node, new SAbstractConcept[]{MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfe43cb41d0L, "jetbrains.mps.lang.generator.structure.TemplateDeclaration"), MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x112103dd1e8L, "jetbrains.mps.lang.generator.structure.InlineTemplate_RuleConsequence"), MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x7b85dded0be53d6cL, "jetbrains.mps.lang.generator.structure.InlineTemplateWithContext_RuleConsequence")}, false, false) != null) { return true; } return false; } public static SNode addNodeMacro(SNode node) { // do not hang $$ on other attributes SNode applyToNode = ListSequence.fromList(SNodeOperations.getNodeAncestors(node, null, true)).where(new IWhereFilter<SNode>() { public boolean accept(SNode it) { return !(SNodeOperations.isAttribute(it)); } }).first(); // surround with <TF> if necessary if (SNodeOperations.getNodeAncestorWhereConceptInList(applyToNode, new SAbstractConcept[]{MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfe43cb41d0L, "jetbrains.mps.lang.generator.structure.TemplateDeclaration"), MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x7b85dded0be53d6cL, "jetbrains.mps.lang.generator.structure.InlineTemplateWithContext_RuleConsequence")}, false, false) != null) { if (!(EditingUtil.isInsideTemplateFragment(applyToNode))) { EditingUtil.createTemplateFragment(applyToNode); } } SNode nodeMacro = SNodeFactoryOperations.createNewNode(SNodeFactoryOperations.asInstanceConcept(MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd47ed6742L, "jetbrains.mps.lang.generator.structure.NodeMacro")), null); if (SNodeOperations.isInstanceOf(node, MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd47ed6742L, "jetbrains.mps.lang.generator.structure.NodeMacro")) && ListSequence.fromList(SNodeOperations.getChildren(applyToNode)).contains(node)) { SNodeOperations.insertPrevSiblingChild(node, nodeMacro); } else { ListSequence.fromList(AttributeOperations.getAttributeList(applyToNode, new IAttributeDescriptor.NodeAttribute(MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd47ed6742L, "jetbrains.mps.lang.generator.structure.NodeMacro")))).addElement(nodeMacro); } return nodeMacro; } public static SNode addPropertyMacro(SNode node, EditorCell cell) { // surround with <TF> if necessary if (SNodeOperations.getNodeAncestorWhereConceptInList(node, new SAbstractConcept[]{MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfe43cb41d0L, "jetbrains.mps.lang.generator.structure.TemplateDeclaration"), MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x7b85dded0be53d6cL, "jetbrains.mps.lang.generator.structure.InlineTemplateWithContext_RuleConsequence")}, false, false) != null) { if (!(EditingUtil.isInsideTemplateFragment(node))) { EditingUtil.createTemplateFragment(node); } } String propertyName = EditingUtil.getEditedPropertyName(cell); SProperty p = ((ConceptMetaInfoConverter) SNodeOperations.getConcept(node)).convertProperty(propertyName); SNode propertyMacro = SNodeFactoryOperations.setNewAttribute(node, new IAttributeDescriptor.PropertyAttribute(MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd47e9f6f0L, "jetbrains.mps.lang.generator.structure.PropertyMacro"), p), SNodeFactoryOperations.asInstanceConcept(MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd47e9f6f0L, "jetbrains.mps.lang.generator.structure.PropertyMacro"))); if (p != null) { PropertyAttribute__BehaviorDescriptor.setProperty_id6Gg5Klvu8CV.invoke(propertyMacro, p); } return propertyMacro; } public static SNode addReferenceMacro(SNode node, EditorCell cell) { String linkRole = EditingUtil.getEditedLinkRole(cell); SNode referentNode = EditingUtil.getEditedLinkReferentNode(cell); // surround with <TF> if necessary if (SNodeOperations.getNodeAncestorWhereConceptInList(referentNode, new SAbstractConcept[]{MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfe43cb41d0L, "jetbrains.mps.lang.generator.structure.TemplateDeclaration"), MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0x7b85dded0be53d6cL, "jetbrains.mps.lang.generator.structure.InlineTemplateWithContext_RuleConsequence")}, false, false) != null) { if (!(EditingUtil.isInsideTemplateFragment(referentNode))) { EditingUtil.createTemplateFragment(referentNode); } } SReferenceLink ref = ((ConceptMetaInfoConverter) SNodeOperations.getConcept(node)).convertAssociation(linkRole); SNode referenceMacro = SNodeFactoryOperations.setNewAttribute(referentNode, new IAttributeDescriptor.LinkAttribute(MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd7f44d616L, "jetbrains.mps.lang.generator.structure.ReferenceMacro"), ref), SNodeFactoryOperations.asInstanceConcept(MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd7f44d616L, "jetbrains.mps.lang.generator.structure.ReferenceMacro"))); if (ref != null) { LinkAttribute__BehaviorDescriptor.setLink_id6Gg5KlvuxxF.invoke(referenceMacro, ref); } return referenceMacro; } public static boolean isInsideTemplateFragment(SNode node) { Iterable<SNode> ancestorTFs = ListSequence.fromList(SNodeOperations.getNodeAncestors(node, null, true)).where(new IWhereFilter<SNode>() { public boolean accept(SNode it) { return AttributeOperations.getAttribute(it, new IAttributeDescriptor.NodeAttribute(MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xff1b29b76cL, "jetbrains.mps.lang.generator.structure.TemplateFragment"))) != null; } }); return Sequence.fromIterable(ancestorTFs).isNotEmpty(); } public static void createTemplateFragment(final SNode node) { SNodeFactoryOperations.setNewAttribute(node, new IAttributeDescriptor.NodeAttribute(MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xff1b29b76cL, "jetbrains.mps.lang.generator.structure.TemplateFragment")), SNodeFactoryOperations.asInstanceConcept(MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xff1b29b76cL, "jetbrains.mps.lang.generator.structure.TemplateFragment"))); // remove subordinate template fragments // XXX (1) not quite clear why we go only 1 level deep. Why not descendants. Guess, TF could be anywhere? // (2) What if there's attribute (not NodeMacro) with TF attached? We don't remove it here then, and may face // issues like https://youtrack.jetbrains.com/issue/MPS-20691 Iterable<SNode> children = ListSequence.fromList(SNodeOperations.getChildren(node)).where(new IWhereFilter<SNode>() { public boolean accept(SNode it) { return !(SNodeOperations.isAttribute(it)); } }); for (SNode child : Sequence.fromIterable(children)) { ListSequence.fromList(SNodeOperations.getNodeDescendants(child, MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xff1b29b76cL, "jetbrains.mps.lang.generator.structure.TemplateFragment"), false, new SAbstractConcept[]{})).visitAll(new IVisitor<SNode>() { public void visit(SNode it) { SNodeOperations.deleteNode(it); } }); } // re append all macros to make them go 'after' the <TF> ListSequence.fromList(AttributeOperations.getAttributeList(node, new IAttributeDescriptor.NodeAttribute(MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd47ed6742L, "jetbrains.mps.lang.generator.structure.NodeMacro")))).visitAll(new IVisitor<SNode>() { public void visit(SNode it) { ListSequence.fromList(AttributeOperations.getAttributeList(node, new IAttributeDescriptor.NodeAttribute(MetaAdapterFactory.getConcept(0xb401a68083254110L, 0x8fd384331ff25befL, 0xfd47ed6742L, "jetbrains.mps.lang.generator.structure.NodeMacro")))).addElement(it); } }); } public static String getEditedPropertyName(EditorCell cell) { if (cell instanceof EditorCell_Property) { ModelAccessor modelAccessor = ((EditorCell_Property) cell).getModelAccessor(); if (modelAccessor instanceof PropertyAccessor) { String propertyName = ((PropertyAccessor) modelAccessor).getPropertyName(); return propertyName; } } return null; } public static String getEditedLinkRole(EditorCell cell) { if (!(cell.isReferenceCell())) { return null; } return cell.getRole(); } public static SNode getEditedLinkReferentNode(EditorCell cell) { return cell.getSNode(); } }