/* * Copyright 2003-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.mps.generator.impl; import jetbrains.mps.generator.runtime.NodePostProcessor; import org.jetbrains.annotations.NotNull; import org.jetbrains.mps.openapi.model.SNode; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Post-processing (end of generation step) code */ public class DelayedChanges { private static final String MAP_SRC_TEMP_NODE = "mapSrcTempNode"; private final List<NodePostProcessor> myPostProcessors = new ArrayList<NodePostProcessor>(); public DelayedChanges() { } public boolean isEmpty() { return myPostProcessors.isEmpty(); } public void add(@NotNull NodePostProcessor postProcessor) { // FIXME unlike old code, we mark as temp nodes with post-processing only. Likely, shall get rid of this temp notion altogether, // or let NodePostProcessor tell me here whether it substitutes the node or not markNodeAsTemp(postProcessor.getOutputAnchor()); synchronized (myPostProcessors) { myPostProcessors.add(postProcessor); } } public void doAllChanges(@NotNull TemplateGenerator generator) throws GenerationFailureException { SNode[] newOutputNodes = new SNode[myPostProcessors.size()]; int i = 0; for (NodePostProcessor p : myPostProcessors) { SNode child = p.substitute(); if (child == null) { generator.getLogger().error(p.getTemplateNode(), "Unexpected null value. Transform function of MAP-SRC didn't produce any result. Please check the function and make sure it always supplies a node"); continue; } if (child != p.getOutputAnchor()) { ChildAdopter ca = new ChildAdopter(generator); ca.checkIsExpectedLanguage(Collections.singletonList(child), p.getTemplateNode(), p.getTemplateContext()); child = ca.adopt(child, p.getTemplateContext()); generator.replacePlaceholderNode(p, child); } newOutputNodes[i++] = child; } i = 0; for (NodePostProcessor p : myPostProcessors) { if (newOutputNodes[i] != null) { p.postProcess(newOutputNodes[i++]); } } myPostProcessors.clear(); } public static boolean isTempNode(@NotNull SNode node) { return node.getUserObject(MAP_SRC_TEMP_NODE) != null; } private void markNodeAsTemp(SNode childToReplace) { childToReplace.putUserObject(MAP_SRC_TEMP_NODE, MAP_SRC_TEMP_NODE); } }