package jetbrains.mps.ide.make.actions; /*Generated by MPS */ import jetbrains.mps.workbench.action.BaseAction; import javax.swing.Icon; import com.intellij.openapi.actionSystem.AnActionEvent; import java.util.Map; import jetbrains.mps.make.IMakeService; import org.jetbrains.mps.openapi.model.SModel; import jetbrains.mps.generator.GenerationFacade; import org.jetbrains.annotations.NotNull; import jetbrains.mps.project.MPSProject; import jetbrains.mps.ide.actions.MPSCommonDataKeys; import com.intellij.openapi.project.Project; import com.intellij.openapi.actionSystem.CommonDataKeys; import org.jetbrains.mps.openapi.model.SNode; import java.util.List; import jetbrains.mps.ide.make.DefaultMakeMessageHandler; import jetbrains.mps.make.MakeSession; import org.jetbrains.mps.openapi.model.SNodeReference; import jetbrains.mps.make.script.IScript; import jetbrains.mps.make.script.ScriptBuilder; import jetbrains.mps.make.facet.IFacet; import jetbrains.mps.make.facet.ITarget; import org.jetbrains.mps.openapi.model.SModelReference; import java.util.concurrent.Future; import jetbrains.mps.make.script.IResult; import jetbrains.mps.smodel.resources.ModelsToResources; import jetbrains.mps.internal.collections.runtime.Sequence; import com.intellij.openapi.application.ApplicationManager; import jetbrains.mps.ide.make.TextPreviewFile; import jetbrains.mps.smodel.ModelAccessHelper; import jetbrains.mps.util.Computable; import java.util.ArrayList; import jetbrains.mps.lang.core.plugin.TextGenOutcomeResource; import jetbrains.mps.util.NameUtil; import org.jetbrains.mps.openapi.module.SRepository; import jetbrains.mps.lang.smodel.generator.smodelAdapter.SNodeOperations; import jetbrains.mps.text.TextUnit; import jetbrains.mps.textgen.trace.TracingUtil; import jetbrains.mps.internal.collections.runtime.ListSequence; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import jetbrains.mps.ide.projectPane.ProjectPane; import jetbrains.mps.messages.Message; import jetbrains.mps.messages.MessageKind; public class TextPreviewModel_Action extends BaseAction { private static final Icon ICON = null; public TextPreviewModel_Action() { super("Preview Generated Text", "", ICON); this.setIsAlwaysVisible(false); this.setExecuteOutsideCommand(true); } @Override public boolean isDumbAware() { return true; } @Override public boolean isApplicable(AnActionEvent event, final Map<String, Object> _params) { if (IMakeService.INSTANCE.get().isSessionActive()) { return false; } SModel md = TextPreviewModel_Action.this.modelToGenerate(event); return md != null && GenerationFacade.canGenerate(md); } @Override public void doUpdate(@NotNull AnActionEvent event, final Map<String, Object> _params) { this.setEnabledState(event.getPresentation(), this.isApplicable(event, _params)); } @Override protected boolean collectActionData(AnActionEvent event, final Map<String, Object> _params) { if (!(super.collectActionData(event, _params))) { return false; } { MPSProject p = event.getData(MPSCommonDataKeys.MPS_PROJECT); if (p == null) { return false; } } { Project p = event.getData(CommonDataKeys.PROJECT); if (p == null) { return false; } } { SNode p = event.getData(MPSCommonDataKeys.NODE); } { SModel p = event.getData(MPSCommonDataKeys.CONTEXT_MODEL); if (p == null) { return false; } } { List<SModel> p = event.getData(MPSCommonDataKeys.MODELS); } return true; } @Override public void doExecute(@NotNull final AnActionEvent event, final Map<String, Object> _params) { final MPSProject mpsProject = event.getData(MPSCommonDataKeys.MPS_PROJECT); final Project ideaProject = event.getData(CommonDataKeys.PROJECT); final DefaultMakeMessageHandler msgHandler = new DefaultMakeMessageHandler(mpsProject); MakeSession session = new MakeSession(mpsProject, msgHandler, true); final SNodeReference contextNode = (event.getData(MPSCommonDataKeys.NODE) == null ? null : event.getData(MPSCommonDataKeys.NODE).getReference()); if (IMakeService.INSTANCE.get().openNewSession(session)) { IScript scr = new ScriptBuilder().withFacetNames(new IFacet.Name("jetbrains.mps.lang.core.Generate"), new IFacet.Name("jetbrains.mps.lang.core.TextGen"), new IFacet.Name("jetbrains.mps.make.facets.Make")).withFinalTarget(new ITarget.Name("jetbrains.mps.lang.core.TextGen.textGenToMemory")).toScript(); SModel model = TextPreviewModel_Action.this.modelToGenerate(event); final SModelReference model2generateRef = model.getReference(); final Future<IResult> future = IMakeService.INSTANCE.get().make(session, new ModelsToResources(Sequence.<SModel>singleton(model)).resources(false), scr); ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { public void run() { try { final IResult result = future.get(); final List<TextPreviewFile> previewFiles = new ModelAccessHelper(mpsProject.getModelAccess()).runReadAction(new Computable<List<TextPreviewFile>>() { public List<TextPreviewFile> compute() { ArrayList<TextPreviewFile> rv = new ArrayList<TextPreviewFile>(); for (TextGenOutcomeResource tgr : Sequence.fromIterable(result.output()).ofType(TextGenOutcomeResource.class)) { // XXX don't see too much value in modelName, shall drop? String modelName = NameUtil.compactNamespace(tgr.getModel().getModelName()); final SRepository repo = mpsProject.getRepository(); SNode cn = (contextNode == null ? null : contextNode.resolve(repo)); List<SNode> ancestors = (cn == null ? new ArrayList<SNode>() : SNodeOperations.getNodeAncestors(cn, null, true)); for (TextUnit tu : tgr.getTextGenResult().getUnits()) { if (cn != null) { SNode originalStart = TracingUtil.getInputNode(tu.getStartNode(), repo); if (originalStart != null && !(ListSequence.fromList(ancestors).contains(originalStart))) { continue; } } rv.add(new TextPreviewFile(tu, modelName)); } } return rv; } }); ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { if (previewFiles.isEmpty()) { StringBuilder message = new StringBuilder(); message.append("Model processed:"); message.append(model2generateRef); message.append("\n"); if (contextNode != null) { message.append("Context node:"); message.append(contextNode); message.append("\n"); } if (result.isSucessful()) { message.append("Text generation completed successfully\n"); } else { message.append("Text generation completed with errors\n"); } if (contextNode != null) { message.append("None of generated text units reference context node"); } else { message.append("There were no text units generated."); } previewFiles.add(new TextPreviewFile("TextGen", message.toString(), model2generateRef.getModelName())); } FileEditorManager fem = FileEditorManager.getInstance(ideaProject); for (TextPreviewFile f : ListSequence.fromList(previewFiles)) { fem.openTextEditor(new OpenFileDescriptor(ideaProject, f), true); } } }); // to update tree to reveal transient models. is it still necessary? ProjectPane.getInstance(mpsProject).rebuild(); } catch (Exception e) { msgHandler.handle(new Message(MessageKind.ERROR, "TextPreviewModel", e.toString()).setException(e)); } } }); } } private SModel modelToGenerate(final AnActionEvent event) { SModel md = null; if (event.getData(MPSCommonDataKeys.CONTEXT_MODEL) != null) { md = event.getData(MPSCommonDataKeys.CONTEXT_MODEL); } else if (event.getData(MPSCommonDataKeys.MODELS) != null && event.getData(MPSCommonDataKeys.MODELS).size() > 0) { md = event.getData(MPSCommonDataKeys.MODELS).get(0); } return md; } }