/*
* Copyright 2003-2017 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.runtime;
import jetbrains.mps.generator.impl.GenerationFailureException;
import jetbrains.mps.util.annotation.ToRemove;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.mps.openapi.language.SContainmentLink;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.model.SNodeReference;
import java.util.Collection;
/**
* Utility to perform weaving of a node. Context-aware, the only way to obtain its instance is
* {@link TemplateExecutionEnvironment#prepareWeave(WeaveContext, SNodeReference)}.
* Knows parent and anchor for nodes being weaved (either one by one or by means of another {@link #weaveTemplate(TemplateDeclaration) template}
*
* @author Artem Tikhomirov
* @since 3.3
*/
public interface NodeWeaveFacility {
/**
* @return context to evaluate templates with.
*/
@NotNull
TemplateContext getTemplateContext();
/*
*
* FIXME Consider splitting validation aspect from child addition, which could be generated right inside template code.
* If there's use for 'validate(parent, role, child) elsewhere, shall get rid of distinct weaveNode method as it does nothing but validateChild+addChild
*/
/**
* Inject new node, with respect to context this facility was created in (i.e. {@link WeaveContext#getContextNode() parent node} and
* {@link jetbrains.mps.generator.runtime.NodeWeaveFacility.WeaveContext#getAnchorNode(SNode, SNode) anchor}.
* @param childRole role for the child
* @param outputNodeToWeave new child node
* @throws GenerationFailureException
*/
void weaveNode(@NotNull SContainmentLink childRole, @NotNull SNode outputNodeToWeave) throws GenerationFailureException;
/**
* weave template from another generator
* Method intended for use from generated generators
* @return FIXME contract shall be identical to {@link TemplateDeclarationWeavingAware2#weave(WeaveContext, NodeWeaveFacility)}
*/
Collection<SNode> weaveTemplate(@NotNull SNodeReference templateDeclaration, Object... args) throws GenerationException;
/**
* weave template from the same generated generator
* Method intended for use from generated generators
* @return FIXME contract shall be identical to {@link TemplateDeclarationWeavingAware2#weave(WeaveContext, NodeWeaveFacility)}
*/
Collection<SNode> weaveTemplate(@NotNull TemplateDeclaration templateDeclaration) throws GenerationException;
// there's need to pass more than 1 parameter to weaving, hence the context.
interface WeaveContext {
/**
* @return context node of a weaving rule or macro. Not necessarily the parent nodes get weaved into, as actual parent
* could be affected by TF.contextNodeQuery query
*/
@NotNull
SNode getContextNode();
/**
* NOTE: PROVISIONAL API, DO NOT USE. INSTEAD, RELY ON {@link NodeWeaveFacility#getTemplateContext()}.
*
* XXX not sure whether TC is part of WeavingContext or NodeWeaveFacility (and if I care to tell the two, actually. That's why I
* limit generated code to NWF only, without WeaveContext)
*/
@NotNull
TemplateContext getTemplateContext();
@Nullable
SNode getAnchorNode(@NotNull SNode outputParent, @NotNull SNode outputNode) throws GenerationFailureException;
}
}